交叉编译在OSX上运行?


142

我正在尝试在OSX上交叉编译go应用程序,以为Windows和Linux构建二进制文件。我已经阅读了所有可以在网上找到的东西。我发现的最接近的示例已发布(除了有关go-nuts邮件列表的许多未完成的讨论之外):

http://solovyov.net/en/2012/03/09/cross-compiling-go/

但它不适用于我的安装。我去了1.0.2。由于1.0.2是最近的版本,因此在我看来上述所有示例均不适用于该版本。

试图./make.bash --no-clean与ENV vars设置为386 / windows一起使用,它确实构建了go,但是它为我的安装构建了go,darwin/amd64并且完全忽略了ENV中假设构建其他编译器的设置。

有没有人建议如何做到(如果可以做到的话)?


与此平行的是,我在golang-nuts邮件列表上提出了相同的问题,并在人们的耐心帮助和耐心下完成了最终食谱……这是讨论主题: groups.google.com/forum/?fromgroups=# !topic / golang-nuts / ... 有几个步骤和结论,我在途中弄错了,但是现在配方似乎很简单-3个步骤和一些迭代。
ljgww 2012年

现在,我要回顾一下,我徘徊于为什么ENV变量未触发正确的编译-也许是因为我这样做了sudo(很可能我在sudo-ing时会得到不同的unix ENV,所以如果不做的话,GOOS和GOARCH将不可用内联)
ljgww 2012年

回复:jdi-我只是试图编译我的“ mockup” go应用程序以在Mac上赢/林二进制文件,但是,要做到这一点,我必须为每种平台/处理器组合自行构建。(尚无法回答我自己的问题-这里的声望不足)
ljgww 2012年

1
您是否键入了示例中的确切说明?CGO_ENABLED=0 GOOS=windows GOARCH=amd64 ./make.bash-如果您尝试将其拆分成多行,则不会导出符合症状的环境变量
Nick Craig-Wood

确保您不会混淆主机和目标体系结构。您应该看到以下输出:“#为主机darwin / amd64构建编译器和Go引导程序工具。” “#为主机darwin / amd64构建软件包和命令。” “#为Windows / 386构建软件包和命令。
山姆

Answers:


157

使用Go 1.5,他们似乎改善了交叉编译过程,这意味着它已内置。不需要./make.bash-ing或brew-ing。这里描述该过程但是对于那里的TLDR-ers(像我一样):您只需设置GOOSGOARCH环境变量并运行go build。

对于甚至更懒惰的复制粘贴器(例如我),如果您使用的是* nix系统,请执行以下操作:

env GOOS=linux GOARCH=arm go build -v github.com/path/to/your/app

您甚至学到了env技巧,它使您可以完全免费地为该命令设置环境变量。


4
env命令仅在自定义环境中运行该调用,并在完成后对其进行“重置”。例如run export GOOS=windows,然后是带有或不带有envand 的命令echo $GOOS。随着envGOOS没有改变。
leondepeon

3
没有,也是如此(至少在Bash中)env。我跑了export GOOS=windows那么GOOS=linux bash -c 'echo "GOOS: $GOOS"'那么echo "GOOS: $GOOS"。是否env提供与其他Shell方言或其他平台的更大兼容性?如果不是,这里似乎是多余的。
davidchambers

2
@davidchambers在BASH中是等效的。在其他某些Shell中(例如FISH shell),它不支持FOO=bar cmd,因此您必须使用env FOO=bar cmd。因此,我认为使用的最大优势env FOO=bar cmd是兼容性。
PickBoy '16

1
令人难以置信的答案就在这里。您解决了我的问题,教给我一个新的把戏,并使我对自己发笑。
T空白

1
好答案,谢谢!为了在heroku(intel x86)上使用进行编译,我对该行进行了少许修改env GOOS=linux GOARCH=386 go build -v github.com/path/to/your/app,使其像冠军一样
Ira Herman

136

感谢golang-nuts的善良和耐心帮助,配方如下:

1)需要针对不同的目标平台和体系结构编译Go编译器。这是通过go安装中的src文件夹完成的。在我的情况下,Go安装位于其中,/usr/local/go因此您需要发布make实用程序才能编译编译器。在执行此操作之前,您需要了解一些警告。

交叉编译时有关CGO库的问题,因此需要禁用CGO库。

通过将位置更改为源目录来完成编译,因为必须在该文件夹中完成编译

cd /usr/local/go/src

然后编译Go编译器:

sudo GOOS=windows GOARCH=386 CGO_ENABLED=0 ./make.bash --no-clean

您需要通过更改GOOS和GOARCH参数,为希望交叉编译的每个OS和体系结构重复此步骤。

如果您像我一样在用户模式下工作,则需要sudo,因为Go编译器位于系统目录中。否则,您需要以超级用户身份登录。在Mac上,您可能需要启用/配置SU访问(默认情况下不可用),但是如果您已成功安装Go,则可能已经具有root访问权限。

2)构建完所有交叉编译器后,可以使用以下设置来愉快地交叉编译应用程序:

GOOS=windows GOARCH=386 go build -o appname.exe appname.go

GOOS=linux GOARCH=386 CGO_ENABLED=0 go build -o appname.linux appname.go

将GOOS和GOARCH更改为要构建的目标。

如果您遇到CGO问题,请在命令行中包含CGO_ENABLED = 0。另请注意,用于Linux和Mac的二​​进制文件没有扩展名,因此,为了拥有不同的文件,您可以添加扩展名。-o switch指示Go使输出文件类似于c / c ++的旧编译器,因此上面使用的appname.linux可以是任何其他扩展名。


最初让我感到困惑的是,在编译的第一部分中make会说:# Building compilers and Go bootstrap tool for host, darwin/amd64但后来它实际上变成了:--- Installed Go for windows/386 in /usr/local/go Installed commands in /usr/local/go/bin因此,人们应该观察到编译的结束而不是开始。
ljgww 2012年

一切都始于尝试做:$ GOARCH=386 GOOS=linux go build app.go并得到错误 # runtime /usr/local/go/src/pkg/runtime/extern.go:137: undefined: theGoos /usr/local/go/src/pkg/runtime/extern.go:137: cannot use theGoos as type string in const initializer
ljgww 2012年

30
Homebrew中Go的软件包有一个选项“ --cross-compile-all”,它将自动构建所有交叉编译器。
nimrodm 2014年

8
大提示@nimrodm!要重新编译go安装,您需要运行brew reinstall go --cross-compile-all
linqu 2015年

1
@ljgww'sudo'没有配置ENV。我最终在/ usr / local / go / pkg / linux_amd64 /上使用chown
Nuno Silva,

63

如果在OS X上使用Homebrew,则有一个更简单的解决方案:

$ brew install go --with-cc-common # Linux, Darwin, and Windows

要么..

$ brew install go --with-cc-all # All the cross-compilers

reinstall如果已经go安装,请使用。


3
注意更新的开关有:--cross-compile-all为所有支持的平台构建交叉编译器和运行时支持--cross-compile-common为darwin,linux和Windows构建交叉编译器和运行时支持
Chip Tol

3
--cross-compile-all现在--with-cc-all
gianebao

@ sheeks06-修复。谢谢!
docwhat 2015年

1
据我所知,这些标志不再存在。我看到的唯一相关选项是--without-cgo :(
rdegges 2015年

5
从Go 1.5开始,没有单独的交叉编译器,您现在只需使用标志tip.golang.org/doc/go1.5#compiler_and_tools
chuckus

24

您可以使用Docker轻松完成此操作,因此不需要额外的库。只需运行以下命令:

docker run --rm -it -v "$GOPATH":/go -w /go/src/github.com/iron-io/ironcli golang:1.4.2-cross sh -c '
for GOOS in darwin linux windows; do
  for GOARCH in 386 amd64; do
    echo "Building $GOOS-$GOARCH"
    export GOOS=$GOOS
    export GOARCH=$GOARCH
    go build -o bin/ironcli-$GOOS-$GOARCH
  done
done
'

您可以在这篇文章中找到更多详细信息:https : //medium.com/iron-io-blog/how-to-cross-compile-go-programs-using-docker-beaa102a316d


1
为什么只要有人可以进行Shell循环env GOOS=x GOARCH=y go install something/...并以$GOPATH/bin/$GOOS_$GOARCH?? 下的适当二进制文件结尾,为什么有人想要安装Docker来做到这一点?顺便说一句,Go不仅支持您列出的三个操作系统,为什么还不喜欢BSD?
Dave C

8
您不会仅仅为了做到这一点而安装Docker,但是如果有的话,它比替代方案更容易,更干净。
Travis Reeder

7

为许多平台创建可执行文件的过程可能有点乏味,因此我建议使用脚本:

#!/usr/bin/env bash

package=$1
if [[ -z "$package" ]]; then
  echo "usage: $0 <package-name>"
  exit 1
fi
package_name=$package

#the full list of the platforms: https://golang.org/doc/install/source#environment
platforms=(
"darwin/386"
"dragonfly/amd64"
"freebsd/386"
"freebsd/amd64"
"freebsd/arm"
"linux/386"
"linux/amd64"
"linux/arm"
"linux/arm64"
"netbsd/386"
"netbsd/amd64"
"netbsd/arm"
"openbsd/386"
"openbsd/amd64"
"openbsd/arm"
"plan9/386"
"plan9/amd64"
"solaris/amd64"
"windows/amd64"
"windows/386" )

for platform in "${platforms[@]}"
do
    platform_split=(${platform//\// })
    GOOS=${platform_split[0]}
    GOARCH=${platform_split[1]}
    output_name=$package_name'-'$GOOS'-'$GOARCH
    if [ $GOOS = "windows" ]; then
        output_name+='.exe'
    fi

    env GOOS=$GOOS GOARCH=$GOARCH go build -o $output_name $package
    if [ $? -ne 0 ]; then
        echo 'An error has occurred! Aborting the script execution...'
        exit 1
    fi
done

我仅在OSX上检查了此脚本

要点-go-executable-build.sh


正是我一直在寻找的...我dockerized吧:) gist.github.com/marcellodesales/...
马塞罗德销售

6

适用于需要启用CGO并从OSX定位窗口交叉编译的用户

从我的Mac编译Windows时,我需要启用CGO,因为我已经导入了https://github.com/mattn/go-sqlite3,并且需要它。根据其他答案进行编译给了我和错误:

/usr/local/go/src/runtime/cgo/gcc_windows_amd64.c:8:10: fatal error: 'windows.h' file not found

如果您像我,则必须与CGO一起编译。这是我所做的:

1.我们将使用依赖于CGO的库对Windows进行交叉编译。首先,我们需要安装一个交叉编译器,例如mingw-w64

brew install mingw-w64

这可能会在这里安装它/usr/local/opt/mingw-w64/bin/

2.就像其他答案一样,我们首先需要现在将Windows架构添加到go编译器工具链中。编译编译器需要编译器(很奇怪的一句话)编译go编译器需要单独的预编译器。我们可以下载预构建的二进制文件,~/Documents/go 也可以从文件夹中的源代码进行构建,例如:现在,根据最佳答案,我们可以改进Go编译器,但是这次使用CGO_ENABLED=1和我们单独的预构建编译器GOROOT_BOOTSTRAP(Pooya是我的用户名):

cd /usr/local/go/src
sudo GOOS=windows GOARCH=amd64 CGO_ENABLED=1 GOROOT_BOOTSTRAP=/Users/Pooya/Documents/go ./make.bash --no-clean
sudo GOOS=windows GOARCH=386 CGO_ENABLED=1 GOROOT_BOOTSTRAP=/Users/Pooya/Documents/go ./make.bash --no-clean

3,现在在编译我们的Go代码时,使用mingw启用CGO来编译我们的go文件定位窗口:

GOOS="windows" GOARCH="386" CGO_ENABLED="1" CC="/usr/local/opt/mingw-w64/bin/i686-w64-mingw32-gcc" go build hello.go
GOOS="windows" GOARCH="amd64" CGO_ENABLED="1" CC="/usr/local/opt/mingw-w64/bin/x86_64-w64-mingw32-gcc" go build hello.go
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.