我有一个存储库,其中包含一组嵌套的go软件包,其组织方式如下:
$GOPATH/src/
- mypackage/common/utils.go
- mypackage/app1/main.go
- mypackage/app2/main.go
...
它可以编译为少量二进制文件。为了发布,我将交叉编译多个平台/架构(我反复使用不同的GOOS
和GOARCH
进行部署)。我正在尝试将编译结果写入我选择的目录中,但是我正在与工具链进行斗争。
我可以:
在为我自己的体系结构编译时组合GOBIN
和go install
(即 not 交叉编译):
# build + output all binaries in /somedir/bin
# this works great when compiling for my local architecture.
GOBIN=/somedir/bin go install mypackage/app1 mypackage/app2 mypackage/app3
但是不幸的是,GOBIN
与交叉编译有冲突,例如:
# Throws: "cannot install cross-compiled binaries when GOBIN is set"
GOBIN=/somedir/bin GOARCH=amdm64 GOOS=darwin go install mypackage/app1 mypackage/app2
将go build
与GOOS=X
和GOARCH=Y
用于每个子包
# cross compile one of the binaries
cd /output/darwin-386-bin/ && \
GOOS=darwin GOARCH=386 go build mypackage/app1
# but if given multiple binaries, there is no output. (as documented)
GOOS=darwin GOARCH=386 go build mypackage/app1 mypackage/app2
为go build
提供了多个软件包时,它不再发出二进制文件-只是检查代码是否已编译。要发出所有二进制文件,似乎我必须为每个子包运行一次go build
,所以用-a
构建时它会花费更长的时间,尤其是。
使用go build
这样的另一个可能的问题是,它可能会在同一工作空间中的多个体系结构之间混合二进制文件和中间结果。但这也许只是个口味问题。希望该工具链可以将缓存的结果针对不同的体系结构分开。
在实践中如何处理?尽管共享了共同的代码,我是否应该将每个子包都视为一个单独的包(这样可以安全地并行构建它们)?
相关文章:
进行构建与进行安装:https://groups.google.com/forum/#!topic/golang-nuts/s8Csz3-7EXA(有关交叉编译或多软件包设置的少量信息)
与go 1.5进行交叉编译。:https://dave.cheney.net/2015/08/22/cross-compilation-with-go-1-5(未专门解决多包/通用代码编译问题。此外,关于必须将标准库重新编译为/ usr / local / go / pkg的声明似乎据我所知,不再保留在1.9.1中)
开始构建多个嵌套软件包:Go build multiple/nested packages?。 (接受的答案go build ./...
的行为与在单个构建命令中传递多个软件包的行为相同,因此不输出二进制文件。该线程也不涵盖交叉编译)
答案 0 :(得分:0)
What I'm about to suggest feels like a hack at best, but it might work for you if you're cross-compiling stuff in a container or an isolated build environment.
You can drop the GOBIN from the install command:
# I'm not on this platform, so this is a cross compile
GOOS=darwin GOARCH=amd64 go install mypackage/app1 mypackage/app2
Assuming your package is in $GOPATH/src/mypackage
the above command will install the two binaries to:
$GOPATH/bin/darwin_amd64/{app1, app2}
and the .a compile dependency files in:
$GOPATH/pkg/darwin_amd64/mypackage/{app1,app2,common}
If you're running this in a for loop for all the platforms you plan on supporting, one nuisance with this process is that when you pass GOOS=x GOARCH=y
matching your local architecture (i.e. not cross compiling), then the executables will be placed directly in $GOPATH/bin/
and not $GOPATH/bin/x_y/
.
(packages on the other hand always end up in $GOPATH/pkg/x_y/
, cross compilation or not).
To determine your local architecture, you can follow steps in this answer: https://stackoverflow.com/a/35669816/5556676。
模拟GOBIN=/foo/bin GOOS=x GOARCH=y go install mypackage/app{1,2,3}
更改$GOPATH
对go install写入输出的位置影响很小。使用诸如go get
之类的go命令,您可以通过在$GOPATH
的前面添加新组件来调整软件包的安装位置。但是在1.9版中,go install
总是将二进制文件复制到bin/
文件夹的src/
文件夹中,该文件夹包含要安装的软件包。
您可以假装源文件位于GOBIN=/foo/bin
中(可以使用符号链接),而不使用/foo/src/mypackage
,然后执行GOPATH=/foo GOOS=x GOARCH=y go install mypackage/app{1,2,3}
。由于我在上一段中描述的行为,这会将二进制文件放入/foo/bin
中。
从二进制文件的原始位置获取二进制文件可能比在周围复制源代码树更容易。