Go1.5はクロスコンパイルがより簡単

Go言語の良さの一つにあらゆるOS/Archに対するクロスコンパイルがとても簡単に行えることが挙げられる.今まで(Go1.4以前)も十分に便利だったがGo 1.5ではさらに良くなる.

今までの問題を敢えて挙げるとターゲットとするプラットフォーム向けのビルドtool-chain準備する必要があるのが煩雑であった(cf. Go のクロスコンパイル環境構築 - Qiita

$ cd $(go env GOROOT)/src
$ GOOS=${TARGET_OS} GOARCH=${TARGET_ARCH} ./make.bash --no-clean 
$ gox -build-toolchain 

この作業は1つの環境で一度だけ行えばよいのでそれほど煩雑ではない.しかし,例えばDockerなどでクロスコンパイル環境を提供すると(e.g., tcnksm/dockerfile-gox),ビルドに時間がかかったりイメージが無駄に重くなったりという問題がおこる.初めてクロスコンパイルをしようとするひとにとってもつまづいてしまうポイントだったと思う.

Go1.5ではコンパイラがGoで書き直された(cf. Go in Go)ため,この準備作業が不要になる.goはコンパイル前に必要な標準パッケージを検出しそれらをターゲットのプラットフォーム向けにビルドしてくれる.

使ってみる

Go1.5を準備する.Go1.5のビルドにはGo1.4が必要.

$ git clone https://go.googlesource.com/go $HOME/go1.5
$ cd $HOME/go1.5 && git checkout -b 1.5 refs/tags/go1.5beta2
$ cd $HOME/go1.5/src && GOROOT_BOOTSTRAP=$HOME/go1.4/ ./make.bash
$ export PATH=$HOME/go1.5/bin:$PATH

mitchellh/goxを使ってみる.toolchainの準備なしにすぐに使える.

$ go get github.com/mitchellh/gox
$ cd $GOPATH/src/github.com/tcnksm/hello
$ gox
Number of parallel builds: 4

-->       linux/arm: github.com/tcnksm/hello
-->      darwin/386: github.com/tcnksm/hello
-->       linux/386: github.com/tcnksm/hello
-->       plan9/386: github.com/tcnksm/hello
-->     freebsd/386: github.com/tcnksm/hello
-->   freebsd/amd64: github.com/tcnksm/hello
-->     openbsd/386: github.com/tcnksm/hello
-->   openbsd/amd64: github.com/tcnksm/hello
-->     windows/386: github.com/tcnksm/hello
-->   windows/amd64: github.com/tcnksm/hello
-->     freebsd/arm: github.com/tcnksm/hello
-->      netbsd/386: github.com/tcnksm/hello
-->    netbsd/amd64: github.com/tcnksm/hello
-->      netbsd/arm: github.com/tcnksm/hello
-->     linux/amd64: github.com/tcnksm/hello
-->    darwin/amd64: github.com/tcnksm/hello

ちなみに上の例はcgoが必要ない場合,cgoが必要な場合はCCCXX環境変数でCとC++のコンパイラを指定することができる(cf. Go 1.5: Cross compilation).

$ CGO_ENABLED=1 CC=android-armeabi-gcc CXX=android-armeabi-g++ GOOS=android GOARCH=arm GOARM=7 go build .

留意事項

(2015年8月7日追記)

-v オプションをつけてクロスコンパイルをするとわかるが毎回ターゲットプラットホーム向けに標準ライブラリをビルドするためコンパイル時間は長くなる(cf “https://twitter.com/upthecyberpunks/status/629092265391095809”).同じ環境で使い回すならば今まで通り標準パッケージを事前にビルドしておくと良い.

$ env GOOS=linux GOARCH=amd64 go install std