154

我正在尝试在 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-cleanENV vars 设置为 386/windows,它确实构建了 go,但是它为我的安装构建了 go,它darwin/amd64完全忽略了 ENV 中设置的假设构建不同编译器的内容。

任何建议如何完成(如果可以完成的话)?

4

8 回答 8

199

在 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技巧,它让你只为那个命令设置环境变量,完全免费。

于 2016-03-08T21:43:53.413 回答
142

感谢 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 参数来对希望交叉编译的每个操作系统和架构重复此步骤。

如果您像我一样在用户模式下工作,则需要 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 开关指示 Go 生成类似于 c/c++ 的旧编译器的输出文件,因此上面使用的 appname.linux 可以是任何其他扩展名。

于 2012-08-30T18:05:11.187 回答
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安装,请使用。

于 2015-02-10T02:46:21.403 回答
25

您可以使用 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

于 2015-07-08T20:52:49.587 回答
10

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

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

于 2018-12-02T19:27:06.943 回答
7

对于需要启用CGO并从 OSX 目标窗口进行交叉编译的人

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

/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 编译器工具链中。编译一个编译器需要一个编译器(奇怪的句子)编译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
于 2017-02-17T13:38:23.137 回答
2

从 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

于 2021-09-28T12:17:30.633 回答
1

适用于需要启用 CGO 并从另一个系统进行交叉编译的人

有一个 docker 解决方案golang-crossbuild

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

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"
于 2021-08-20T11:48:36.050 回答