在OSX上交叉编译Go?

huangapple go评论93阅读模式
英文:

Cross compile Go on OSX?

问题

我正在尝试在OSX上交叉编译一个Go应用程序,以构建适用于Windows和Linux的二进制文件。我已经阅读了我能找到的所有内容。我找到的最接近的例子是在(除了go-nuts邮件列表上的许多未完成的讨论之外)发布的:

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

但是在我的安装中它不起作用。我有go 1.0.2版本。由于1.0.2版本相当新,我觉得上述所有例子都不适用于这个版本。

尝试使用设置为386/windows的环境变量运行./make.bash --no-clean,它确实构建了go,但是它构建的是适用于我的安装的go,完全忽略了在环境变量中设置的应该构建不同编译器的内容。

有什么建议吗(如果有可能的话)?

英文:

I am trying to cross-compile a go app on OSX to build binaries for windows and linux. I have read everything what I could find on the net. Closest example that I have found has been published on (apart from many unfinished discussions on go-nuts mailing list):

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

yet it does not work on my installation. I have go 1.0.2. As 1.0.2 is quite recent it looks to me that all above examples do not apply to this version.

Tried to do ./make.bash --no-clean with ENV vars set to 386/windows, it does build go, however it builds go for my installation which is darwin/amd64 and completely ignores what is set in ENV that suppose to build different compiler.

Any advises how it can be done (if it can be done at all)?

答案1

得分: 210

使用Go 1.5,他们似乎改进了交叉编译过程,这意味着现在内置了。不需要./make.bash或者brew。该过程在这里有描述,但对于那些只想看简要说明的人(比如我):你只需设置GOOSGOARCH环境变量,然后运行go build。

对于那些更懒的复制粘贴者(比如我),如果你在*nix系统上,可以这样做:

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

你甚至学会了env技巧,它可以让你仅为该命令设置环境变量,完全免费。

英文:

With Go 1.5 they seem to have improved the cross compilation process, meaning it is built in now. No ./make.bash-ing or brew-ing required. The process is described here but for the TLDR-ers (like me) out there: you just set the GOOS and the GOARCH environment variables and run the go build.

For the even lazier copy-pasters (like me) out there, do something like this if you're on a *nix system:

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

You even learned the env trick, which let you set environment variables for that command only, completely free of charge.

答案2

得分: 143

感谢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可以是任何其他扩展名。

英文:

Thanks to kind and patient help from golang-nuts, recipe is the following:

  1. One needs to compile Go compiler for different target platforms and architectures. This is done from src folder in go installation. In my case Go installation is located in /usr/local/go thus to compile a compiler you need to issue make utility. Before doing this you need to know some caveats.

There is an issue about CGO library when cross compiling so it is needed to disable CGO library.

Compiling is done by changing location to source dir, since compiling has to be done in that folder

cd /usr/local/go/src

then compile the Go compiler:

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

You need to repeat this step for each OS and Architecture you wish to cross compile by changing the GOOS and GOARCH parameters.

If you are working in user mode as I do, sudo is needed because Go compiler is in the system dir. Otherwise you need to be logged in as super user. On Mac you may need to enable/configure SU access (it is not available by default), but if you have managed to install Go you possibly already have root access.

  1. Once you have all cross compilers built, you can happily cross compile your application by using the following settings for example:

    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

Change the GOOS and GOARCH to targets you wish to build.

If you encounter problems with CGO include CGO_ENABLED=0 in the command line. Also note that binaries for linux and mac have no extension so you may add extension for the sake of having different files. -o switch instructs Go to make output file similar to old compilers for c/c++ thus above used appname.linux can be any other extension.

答案3

得分: 63

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

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

或者..

$ brew install go --with-cc-all # 所有交叉编译器

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

英文:

If you use Homebrew on OS X, then you have a simpler solution:

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

or..

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

Use reinstall if you already have go installed.

答案4

得分: 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

英文:

You can do this pretty easily using Docker, so no extra libs required. Just run this command:

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
'

You can find more details in this post:
https://medium.com/iron-io-blog/how-to-cross-compile-go-programs-using-docker-beaa102a316d

答案5

得分: 11

创建适用于多个平台的可执行文件的过程可能有点繁琐,所以我建议使用一个脚本:

#!/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上测试了这个脚本。

英文:

The process of creating executables for many platforms can be a little tedious, so I suggest to use a script:

#!/usr/bin/env bash

package=$1
if [[ -z &quot;$package&quot; ]]; then
  echo &quot;usage: $0 &lt;package-name&gt;&quot;
  exit 1
fi
package_name=$package

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

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

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

I checked this script on OSX only

gist - go-executable-build.sh

答案6

得分: 9

我需要在我的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来编译我们的go文件,以启用CGO并针对Windows进行目标编译:

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
英文:

> for people who need CGO enabled and cross compile from OSX targeting
> windows

I needed CGO enabled while compiling for windows from my mac since I had imported the https://github.com/mattn/go-sqlite3 and it needed it.
Compiling according to other answers gave me and error:

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

If you're like me and you have to compile with CGO. This is what I did:

1.We're going to cross compile for windows with a CGO dependent library. First we need a cross compiler installed like mingw-w64

brew install mingw-w64

This will probably install it here /usr/local/opt/mingw-w64/bin/.

2.Just like other answers we first need to add our windows arch to our go compiler toolchain now. Compiling a compiler needs a compiler (weird sentence) compiling go compiler needs a separate pre-built compiler. We can download a prebuilt binary or build from source in a folder eg: ~/Documents/go
now we can improve our Go compiler, according to top answer but this time with CGO_ENABLED=1 and our separate prebuilt compiler GOROOT_BOOTSTRAP(Pooya is my username):

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.Now while compiling our Go code use mingw to compile our go file targeting windows with CGO enabled:

GOOS=&quot;windows&quot; GOARCH=&quot;386&quot; CGO_ENABLED=&quot;1&quot; CC=&quot;/usr/local/opt/mingw-w64/bin/i686-w64-mingw32-gcc&quot; go build hello.go
GOOS=&quot;windows&quot; GOARCH=&quot;amd64&quot; CGO_ENABLED=&quot;1&quot; CC=&quot;/usr/local/opt/mingw-w64/bin/x86_64-w64-mingw32-gcc&quot; go build hello.go

答案7

得分: 2

自从go 1.17.1版本以后,你必须显式地设置go环境变量。

我已经在一个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

英文:

Since go 1.17.1 you must explicitly set go env variables.

I've done it in a shell script

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

答案8

得分: 1

对于需要启用CGO并从另一个系统进行交叉编译的人来说,有一个名为golang-crossbuild的Docker解决方案。

以下是在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"
英文:

> for people who need CGO enabled and cross-compile from another system

There is one docker solution golang-crossbuild

Here is one example to build linux/armv7 on 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 &quot;make build&quot; \
  -p &quot;linux/armv7&quot;

huangapple
  • 本文由 发表于 2012年8月29日 07:16:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/12168873.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定