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

Go 如何快速构建/安装交叉编译的嵌套包?,go,Go,我有一个包含一组嵌套go包的存储库,其组织如下: $GOPATH/src/ - mypackage/common/utils.go - mypackage/app1/main.go - mypackage/app2/main.go ... 它编译成少量二进制文件。对于发布,我正在为多种平台/架构进行交叉编译(我使用不同的GOOS和GOARCH重复部署)。我试图将编译结果写入我选择的目录,但我正在使用工具链 我可以: 在为我自己的体系结构编译时,将GOBIN和go install

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

$GOPATH/src/
  - mypackage/common/utils.go
  - mypackage/app1/main.go
  - mypackage/app2/main.go
  ...
它编译成少量二进制文件。对于发布,我正在为多种平台/架构进行交叉编译(我使用不同的
GOOS
GOARCH
重复部署)。我试图将编译结果写入我选择的目录,但我正在使用工具链

我可以:

  • 在为我自己的体系结构编译时,将
    GOBIN
    go install
    结合起来 (即不交叉编译):

    但不幸的是,
    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

    go build
    被赋予多个包时,它不再发出二进制文件——它只是检查代码是否编译。要发出所有二进制文件,似乎我必须为每个子包运行一次
    go build
    ,因此需要更长的时间,尤其是使用
    -a
    构建时

    像这样使用
    go build
    的另一个可能问题是,它可能会在同一个工作区中跨多个体系结构混合二进制文件和中间结果。但也许这只是品味的问题。希望该工具链能够为不同的体系结构保持缓存结果的独立性

  • 这在实践中是如何处理的?我是否应该将每个子包视为一个单独的包,而不考虑它们共享的公共代码(然后并行构建它们是否安全)

    相关文章:

    • go build vs go install:(关于交叉编译或多包设置的少量信息)

    • 使用go 1.5进行交叉编译。:(并没有专门针对多包/通用代码编译。而且,据我所知,关于必须将标准库重新编译到/usr/local/go/pkg中的声明似乎不再适用于1.9.1)

    • 转到生成多个嵌套包:。(接受的答案,
      go build./…
      的行为与在一个build命令中传递多个包相同,因此不输出二进制文件。该线程也不涉及交叉编译)


    我将要提出的建议充其量只是一种黑客行为,但如果您在容器或独立构建环境中交叉编译内容,它可能对您有用

    您可以从install命令中删除GOBIN:

    # I'm not on this platform, so this is a cross compile
    GOOS=darwin GOARCH=amd64 go install mypackage/app1 mypackage/app2
    
    假设您的包位于
    $GOPATH/src/mypackage
    中,上述命令将把两个二进制文件安装到:

    $GOPATH/bin/darwin_amd64/{app1, app2}
    
    以及.a在中编译依赖项文件:

    $GOPATH/pkg/darwin_amd64/mypackage/{app1,app2,common}
    
    如果对所有计划支持的平台都在for循环中运行此过程,那么此过程的一个麻烦是,当您传递与本地架构匹配的
    GOOS=x GOARCH=y
    时(即,不交叉编译),那么可执行文件将直接放在
    $GOPATH/bin/
    而不是
    $GOPATH/bin/x_y/

    (另一方面,包总是以
    $GOPATH/pkg/x_y/
    结束,不管是否交叉编译)

    要确定您的本地体系结构,您可以按照以下回答中的步骤进行操作:

    模拟
    GOBIN=/foo/bin-GOOS=x GOARCH=y安装mypackage/app{1,2,3}

    更改
    $GOPATH
    对where-go-install写入输出几乎没有影响。使用一些go命令,如
    go-get
    ,可以通过在
    $GOPATH
    前面添加新组件来调整软件包的安装位置。但是在go 1.9中,
    go install
    将始终复制
    bin/
    文件夹中的二进制文件,该文件夹是包含要安装的软件包的
    src/
    的同级文件夹

    您可以假装源文件位于
    /foo/src/mypackage
    (您可以使用符号链接),然后执行
    GOPATH=/foo-GOOS=x GOARCH=y安装mypackage/app{1,2,3}
    ,而不是使用
    GOBIN=/foo/bin
    。这将把二进制文件放入
    /foo/bin
    ,因为我在上一段中描述了这种行为


    不过,从您期望的位置获取二进制文件可能比到处复制源代码树更简单。

    您不应该在
    GOROOT
    中安装任何东西(甚至不应该设置该变量),您的意思是
    GOPATH
    ?如果要将输出放置在特定位置,也可以使用
    go build-o
    。Woops。我是说GOPATH。由于某种原因,我的容器有GOPATH=/usr/local/go,它会干扰一些事情。更新了答案
    go build-o
    无法处理多个子包,因此出现了这个问题。
    $GOPATH/bin/darwin_amd64/{app1, app2}
    
    $GOPATH/pkg/darwin_amd64/mypackage/{app1,app2,common}