Go Wiki: Gccgoクロスコンパイル
はじめに
標準のGoコンパイラ *gc* でサポートされていないプラットフォームでGoプログラムを実行したい場合、GCCがより多くのプラットフォームをサポートしているため、目的のターゲットプラットフォームをターゲットとするGCCコンパイラのバージョンをビルドできます。これは、GCCにgccgoというGoフロントエンドがあるため可能です。
詳細
定義
- ビルド これはクロスコンパイラをビルドしているコンピュータです。
- ホスト ビルドされたクロスコンパイラを実行するコンピュータ。これは通常、ビルドと同じです。
- ターゲット これは、クロスコンパイルされたプログラムを実行する先のシステムです。
より多くの定義と複雑なクロス状況については、Wikipediaの記事をご覧ください。
Goツールとgccgo
後でGoツールのソースコードが必要になるので、混乱を避けるためにパッケージマネージャーからインストールしたバージョンをアンインストールしても構いません(完全にオプションです)。また、ホストをターゲットとするgccgoをビルド&インストールします(そうです、ターゲットだけでなくホスト用のgccoも必要です)。
クロスコンパイラのビルド
ビルド
まず、クロスコンパイルバージョンのGCCをビルドする必要があります。GCCとlibc実装の間に相互依存関係があるため、ブートストラップによる複数の段階が必要となる複雑なプロセスです。eglic(glibcでも動作します)を使用してGCCクロツールチェーンをビルドする方法に関する非常に優れたチュートリアルは、Jim Blandyによって書かれ、eglibcのメーリングリストに投稿されました patches Cross-building instructions。完全なGCCがビルドされる最終段階では、単に*–enable-languages=c,c++,go*でスクリプトを設定します(Go公式ドキュメントを参照)。
ewxb_gcc_cross-compiler_builder スクリプトを開始点として使用できます。このスクリプトがそのまま動作することを期待するのではなく、x-toolchainをビルドする際の手順のヒントとして使用してください。
最新版である必要がなく(最新のGo機能が必要な場合があります)、幸運にもGCCのバージョンが必要な場合は、クロスコンパイラビルダーを使用して設定を容易にすることができます。たとえば、crosstool-NGを使用すると、シンプルなTUIメニューでGCCを設定できます。
crosstool-NGの新しいバージョンでは、`CT_EXPERIMENTAL`と`CT_CC_SUPPORT_GOLANG`を有効にすることで、Go言語をビルドできます。これにより、`--enable-languages`に自動的に`go`が追加されます。
シンボリックリンク
これで、「`<target`>-gcc」、「`<target`>-gnu-gccgo」などの名前のファイルを含むbinディレクトリが作成されます。Goビルドツールでは、使用するコンパイラのファイル名を指定できないため(文字列「gc」と「gccgo」のみを静的にサポート)、$PATH環境変数で「gccgo」と「gcc」という名前の最初のファイルを検索します。したがって、クロスコンパイラを使用する場合、システム上の通常のgccバイナリではなく、このディレクトリをオーバーレイとして追加し、$PATHの最初に設定する必要があります。Goツールは*gccgo*という名前のバイナリを検索するため、ツールが見つけるためのシンボリックリンクを作成する必要があります。
$ cd path/to/cross-comp-gcc/bin
$ ln -s <arch>-<os>-gnu-gcc gcc
$ ln -s <arch>-<os>-gnu-gccgo gccgo
$ ln -s <arch>-<os>-gnu-ar ar
$ export PATH="path/to/crosscomp-gcc/bin:$PATH" # Do this whenever you want to use the cross-compilers targeting your target instead of the system default targeting host.
など
$TARGETをターゲットアーキテクチャに、$PREFIXをビルドされたファイルの出力先に設定すると、シンボリックリンクを作成できます
##!/usr/bin/env bash
cd $PREFIX/bin
for file in $(find . -type f); do
tool_name=$(echo $file | sed -e "s/${TARGET}-\(.*\)$/\1/")
ln -sf "$file" "$tool_name"
done
テスト
クロスコンパイラのビルドが完了したら、簡単なCプログラムと簡単なGoプログラムの両方で動作することをテストする必要があります。
$ gccgo -Wall -o helloworld helloworld.go
$ file helloworld # verify that the architecture of the binary is the desired target and not a binary that can run on your host machine.
$ <upload-command-to-target> helloworld
$ <ssh/telnet etc. to target and test run>
注意点
ターゲット用にGoライブラリ*libgo*の共有オブジェクトをコンパイルしていない場合は、*gc*と同様に、Goプログラムを静的にコンパイルして、プログラムの実行に必要なすべてを含めることができます。これを行うには、gccgoに*-static*スイッチを追加します。生成されたELFファイルのリンク方法がわからない場合は、*readelf -d `<elf>`*または*objdump -T `<elf>`*で検査します。
クロスgccgo対応バージョンのGoツールのビルド
前提条件
- ソースからのGoのインストールの手順に従っていることを前提として、*$GOROOT*にGoソースのチェックアウトバージョンがあるはずです。
- 環境変数*$GOROOT*が設定されています。
- 環境変数*$GOARCH*と*$GOOS*は、**ターゲット**アーキテクチャとオペレーティングシステムを表します。クロスコンパイルを行う場合は、これらを理解してこれらの値に設定してください。
ビルド
*go build -compiler gccgo `<go-package,files>`*を使用して、Goツールでビルドするときに使用するコンパイラを指定できます。ただし、これだけでは十分ではありません。*$GOARCH*と*$GOOS*を*gc*ではサポートされていないが*gccgo*ではサポートされている値に設定した場合、これらの追加アーキテクチャを理解する特別なバージョンのGoツールをビルドする必要があります。Goツールで別のバージョンのGoツールをコンパイルしますが、ホストをターゲットとするgccgoを使用するように指定すると、結果のGoツールはgccgoでサポートされているすべてのアーキテクチャでプログラムをコンパイルできます。
$ cd ~/tmp
$ hg clone ~/src/go # [0]
$ cd go/src/cmd/go
$ go build -o xgo -compiler gccgo . # [1] [2] [3]
$ cp xgo ~/bin/ # Or any directory that is in your $PATH
- `[0]` Goソースを$GOROOT以外のディレクトリにクローンします。これからコンパイルするcmd/goは特別に処理されるため、これは必要です。
- `[1]` ここでは、クロスコンパイルgccgoではなく、**ホスト**をターゲットとする*gccgo*を使用する必要があります。*$PATH*がこれに対して正しく設定されていることを確認してください。
- `[2]` 既存のgoバイナリと区別するためにxgoという名前のバイナリが生成されます。適切な名前に変更してください。たとえば、ターゲットがMIPSの場合はmgoにします。
- `[3]` コンパイル手順(go build)は、gccgoがgoプロジェクト(少なくともgo mercurial tip 7f2863716967)より遅れているため、いくつかのコンパイルエラーで失敗する可能性があります。コメントアウトするなど、より巧妙な方法でこれらのエラーを修正し、再コンパイルしてください。
Goプログラムのクロスコンパイル。
*$PATH*を_xgo_とクロスコンパイルバージョンの_gccgoを見つけ、*$GOARCH*を適切に設定すると、Goツール(xgoという名前)を使用してクロスコンパイルできるようになりました。
$ export PATH="path/to/xgo/:path/to/crosscomp-gccgo/:$PATH"
$ export GOARCH="<you-target's-arch>"
$ export GOOS="<you-target's-OS>"
$ xgo build -compiler gccgo <go-package/files>
TODO
「C」をインポートするGoプログラムは、xgoを使用して動作しないようです。現在、Go issue#7398によってブロックされています
このWikiページは、https://groups.google.com/forum/#!topic/golang-nuts/PgyS2yoO2jMの "[golang-nuts] MIPSクロスコンパイルの簡素化?"から得られた教訓に触発されています。
このコンテンツはGo Wikiの一部です。