在 OSX 上进行交叉编译? ?

我试图在 OSX 上交叉编译一个 go 应用程序,为 Windows 和 Linux 构建二进制文件。我把网上能找到的都看了。我发现的最接近的例子已经发表在(除了许多未完成的讨论关于疯狂的邮件列表) :

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

但是它在我的安装上不起作用。我已经去1.0。2。由于1.0.2是最新的版本,所以在我看来上面的所有例子都不适用于这个版本。

试着用设置为386/windows 的 ENV vars 来做 ./make.bash --no-clean,它确实构建了,但是它为我的安装构建了 darwin/amd64,完全忽略了在 ENV 中设置的那些假设构建不同编译器的内容。

有什么建议可以做到这一点(如果可以做到的话) ?

153723 次浏览

感谢果仁仁仁和耐心的帮助,食谱如下:

1)需要为不同的目标平台和架构编译 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 指示转到使输出文件类似于 c/c + + 的旧编译器,因此上面使用的 appname.linux 可以是任何其他扩展。

如果你在 OS X 上使用 自酿的,那么你有一个更简单的解决方案:

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

或者。

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

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

使用 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

在 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技巧,它允许您仅为该命令设置环境变量,完全免费。

为人们谁需要 政府总部启用和交叉编译从 OSX 的目标 窗户

我需要启用 政府总部编译窗口从我的 Mac,因为我已经导入了 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 arch 添加到 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

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

#!/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

为那些需要启用 CGO 并从另一个系统交叉编译的人

有一个码头解决方案 Golang-Crossbuild

下面是在 Windows/MacOS 上构建 linux/armv7的一个示例

docker run -it --rm \
-v $GOPATH/src/github.com/user/go-project:/go/src/github.com/user/go-project \
-w /go/src/github.com/user/go-project \
-e CGO_ENABLED=1 \
docker.elastic.co/beats-dev/golang-crossbuild:1.16.4-armhf \
--build-cmd "make build" \
-p "linux/armv7"

自从 go 1.17.1以来,您必须显式地设置 go env 变量。

我用的是 shell 脚本

#!/bin/bash


GOOS=linux
GOARCH=amd64
go.exe get -d -v ./...
go.exe env -w GOOS=$GOOS
go.exe env -w GOARCH=$GOARCH
go.exe build -v ./cmd/tecnoalarm/main.go