如何快速构建/安装交叉编译的嵌套包?

时间:2019-04-05 10:00:32

标签: go

我有一个存储库,其中包含一组嵌套的go软件包,其组织方式如下:

$GOPATH/src/
  - mypackage/common/utils.go
  - mypackage/app1/main.go
  - mypackage/app2/main.go
  ...

它可以编译为少量二进制文件。为了发布,我将交叉编译多个平台/架构(我反复使用不同的GOOSGOARCH进行部署)。我正在尝试将编译结果写入我选择的目录中,但是我正在与工具链进行斗争。

我可以:

  1. 在为我自己的体系结构编译时组合GOBINgo 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
    
  2. go buildGOOS=XGOARCH=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这样的另一个可能的问题是,它可能会在同一工作空间中的多个体系结构之间混合二进制文件和中间结果。但这也许只是个口味问题。希望该工具链可以将缓存的结果针对不同的体系结构分开。

在实践中如何处理?尽管共享了共同的代码,我是否应该将每个子包都视为一个单独的包(这样可以安全地并行构建它们)?

相关文章:

1 个答案:

答案 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中。

从二进制文件的原始位置获取二进制文件可能比在周围复制源代码树更容易。