Go でクロスコンパイル
Go の特徴であるクロスコンパイルの便利さと、その方法はよく語られますが、意外に「そのための準備工程」が知られてない気がしたので、ここで再度クロスコンパイル自体の便利さと、クロスコンパイル方法、そしてその準備方法を書いておきます。
クロスコンパイルの旨味
Go は、 1 つのソースコードから様々な OS 向けのバイナリを生成するクロスコンパイルをサポートしています。しかも、対象の OS が無いとビルドできないわけではなく、例えば Mac で Windows 用、 Linux 用、 Plan9 用のバイナリを一気に生成するといったことができます。
しかも、 32bit マシンで 64bit 用のバイナリを生成することもできます。
"Write Once Run Anywhere" でお馴染みの Java との違いは、 Java の場合は Class ファイルという形式で生成し、環境ごとに VM (Java VM) を入れることで、その上で動かすことができるようになっています。プラットフォームごとの違いは Java VM が吸収するため、生成し配布するファイルは Class ファイルだけで良いという特徴があります。
一方 Go の場合は、生成するのが各環境で直接実行できるファイルなので、実行する人が何かを準備する必要(Java でいう JRE のインストールにあたる作業)がありません。
Mac で .exe ファイルを生成して Windows ユーザにそれを渡せば、受け取った瞬間にすぐに実行できるという点が非常に便利なため、コマンドラインツールのようなものをクロスコンパイルして配布するなどといった用途で、 Go が導入される場面も目立ってきました。(heroku の hk コマンドなど)
クロスコンパイルサポート範囲
現在 Go 1.3 では、以下の組み合わせの OS と CPU アーキテクチャに対して、クロスコンパイルがサポートされています。(1.3 から NaCL もサポートされました。もちろん、試してませんが。。)
$GOOS $GOARCH
darwin 386
darwin amd64
freebsd 386
freebsd amd64
freebsd arm
linux 386
linux amd64
linux arm
netbsd 386
netbsd amd64
netbsd arm
openbsd 386
openbsd amd64
plan9 386
plan9 amd64
windows 386
windows amd64
nacl amd64
nacl 386
クロスコンパイル方法
実行する環境用のバイナリは、 go build コマンドを使って以下のように行います。
$ go build hello.go
環境を指定したい場合は、 GOOS と GOARCH という環境変数を先ほどのリストにある組み合わせで指定します。
$ GOOS=linux GOARCH=amd64 go build hello.go
これだけです!
クロスコンパイルの準備
これだけです!というところまでは語られますが、実際は Go をインストールすればすぐにクロスコンパイルができるというわけではありません。
コンパイルしたい対象の環境ごとに、準備が必要です。ドキュメントはこちら
例えば、先ほどの Mac で Linux の 64bit 環境のバイナリを生成する先ほどのビルドをしたいなら、 Go をインストールしたディレクトリの src 以下にある、 make.bash というスクリプトに、 GOOS と GOARCH をつけて実行します。
$ cd $(go env GOROOT) # go をインストールしたディレクトリに移動
$ cd src # その下の src
$ GOOS=linux GOARCH=amd64 ./make.bash
ちょっと時間がかかります。が、これを必要な環境ごとにやる必要があります。
最低で linux, darwin, windows の 64bit くらいはやっておくとしても 3 回。
全部サポートすれば 19 回変数を変えてコレをやります。地味に時間がかかる。
まあ、自動化しますよね。
シェルなりなんなり書けばよいのですが、そういうツールもいくつかあります。
ビルド環境構築もろもろ
homebrew
まず、 Mac で homebrew をつかっているなら オプションがあるので それをつけます。
-
--cross-compile-all
: 全部 -
--cross-compile-common
: Darwin, Linux, Windows だけ
ということでこんな感じです。
$ brew install go --cross-compile-all
golang-crosscompile
homebrew とか使っていなければ、 bash で書かれたスクリプトが公開されています。
使いかたは こちらのブログ にある通りです。
$ git clone git://github.com/davecheney/golang-crosscompile.git
$ source golang-crosscompile/crosscompile.bash
$ go-crosscompile-build-all
ちなみに、このスクリプトは build をするための shell の関数を作ってくれるのですが、 zsh となんか相性が悪いので使ってません。環境変数だけなんで、適当に自分で shell を書く程度で間に合いそうです。
Windows
よく知りません。情報求む。
追記
そうえば、こういうの公式にサポートしないの? っていう話を GoCon 2013 で来日してた Andrew と飲み会でして、 ML に投稿したら issue 立った。
気がついたら Label が Maybe から Repo-Main になってるし、もしかしたら何か入るかも。
(そして、ここにも mattn 先生の姿がw)
追記2
コメントに @nikuyoshi さんが sh で全環境のビルド環境を構築するスクリプトを貼ってくださったので、掲載させていただきます。
素晴らしいエントリーありがとうございます。 非常に参考になりました。
私はhomebrewを使っておらず、Zsh使いなので簡単なスクリプトを自作してみました。
上記の $ GOOS=linux GOARCH=amd64 ./make.bash を19回分回してるだけです。
https://gist.github.com/nikuyoshi/a6c92119c59144d472ef
Jxckさんは既に不要かと思いますが、誰かのお役に立てれば幸いです。
@nikuyoshi さんありがとうございました!