【发布时间】:2019-10-12 13:45:57
【问题描述】:
我有 2 个项目,第一个,名称为 A,有一个子模块 a 导入 sqlite3(github.com/mattn/go-sqlite3)。另一个B项目导入A的子模块a,在另一个子模块b中也导入了相同的sqlite3。
A 和 B 都将导入放在 vendor 目录下(由 govendor 管理)。我的 Golang 版本是go version go1.12 linux/amd64。
在构建 B (go build main.go) 时,抛出以下错误(太多,一部分):
/usr/local/go/pkg/tool/linux_amd64/link: running gcc failed: exit status 1
/tmp/go-link-281256755/000029.o: In function `callbackTrampoline':
/tmp/go-build/_cgo_export.c:25: multiple definition of `callbackTrampoline'
/tmp/go-link-281256755/000005.o:/tmp/go-build/_cgo_export.c:25: first defined here
/tmp/go-link-281256755/000029.o: In function `stepTrampoline':
...
/home/xxx/go/src/gitlab.xxxxxxxxx.com/xxxxxxxxx-tools/A/vendor/github.com/mattn/go-sqlite3/sqlite3.go:129: multiple definition of `_sqlite3_result_text'
/tmp/go-link-281256755/000009.o:/home/xxx/go/src/gitlab.xxxxxxxxx.com/xxxxxxxxx-tools/A/vendor/github.com/mattn/go-sqlite3/sqlite3.go:129: first defined here
/tmp/go-link-281256755/000033.o: In function `_sqlite3_result_blob':
...
但是构建A 效果很好。为了测试错误,我开始关注演示,同样使用govendor 发起的vendor,并且构建成功。
package main
import (
"database/sql"
"fmt"
"gitlab.xxxxxxxxx.com/xxxxxxxxxxxxxxx/A/a"
_ "github.com/mattn/go-sqlite3"
)
func main() {
fmt.Println(a.ModuleVariable) // use submodule `a` just like B is doing
_, _ = sql.Open(`sqlite3`, `test.db`) // use sqlite too
}
我认为编译器首先编译A的sqlite3,对象是在/tmp/go-link-281256755/000005.o下创建的(但是构建后没有这个目录),然后编译B的导入sqlite3 并且还创建了一个包含同名函数的对象,然后编译器找到2个同名符号,链接失败。
如何解决这些情况?是否有任何 golang env 设置可以避免这些?
在我删除了vendor 和A 和B 下的sqlite3 包后,它们都使用了~/go/src/github.com/mattn/go-sqlite3/ 下的sqlite3,它们都构建好了。但是我不能这样做,由于项目A的部署平台,我必须将所有依赖项放在vendor下,有没有其他选项可以使用同一个包的多个导入?
【问题讨论】:
-
或许你可以使用modules