Go Wiki: GccgoCrossCompilation

はじめに

標準のGoコンパイラであるgcがサポートしていないプラットフォームでGoプログラムを実行したい場合、GCCはより多くのプラットフォームをサポートしているため、目的のターゲットプラットフォームを対象とするGCCコンパイラのバージョンを構築できます。これは、GCCにはgccgoというGoフロントエンドがあるため可能です。

詳細

定義

  • ビルド クロスコンパイラをビルドするコンピュータです。
  • ホスト クロスコンパイラがビルドされた後に実行されるコンピュータです。これは通常、ビルドと同じです。
  • ターゲット クロスコンパイルされたプログラムを実行したい最終システムです。

より詳細な定義と複雑なクロスコンパイルの状況については、Wikipediaの記事を参照してください。

Goツールとgccgo

後でGoツールのソースコードが必要になるため、混乱を避けるためにパッケージマネージャーからインストールしたバージョンをアンインストールしておくと良いでしょう(ただし完全に任意です)。また、ホストをターゲットとするgccgoをビルド&インストールします(!、そうです、ターゲットだけでなくホスト用のgccgoも必要です)。

クロスコンパイラのビルド

ビルド

まず、クロスコンパイルバージョンのGCCをビルドする必要があります。これは、GCCとlibcの実装の間に相互依存関係があるため、ブートストラップを伴ういくつかのステージを必要とする複雑なプロセスです。eglibc(glibcでも動作します)でGCCクロスツールチェーンをビルドする方法に関する非常に優れたチュートリアルがJim Blandyによって書かれ、eglibcのメーリングリストpatches Cross-building instructionsに投稿されています。完全なGCCがビルドされる最終ステージでは、単に--enable-languages=c,c++,goでスクリプトを設定します(公式Goドキュメントを参照)。

開始点としてewxb_gcc_cross-compiler_builderスクリプトを使用できます。このスクリプトがそのまま動作するとは期待せず、x-ツールチェーンをビルドする際に取る可能性のある手順のヒントとして考えてください。

運が良く、最新のGo機能を使いたいわけではない(ただし最新のGo機能が必要な場合もあるでしょう)古いバージョンのGCCが欲しい場合は、クロスコンパイラビルダーを使用して設定を容易にすることができます。例えば、シンプルなTUIメニューでGCCを設定できるcrosstool-NGなどです。

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の共有オブジェクトをコンパイルしていない場合、Goプログラムを静的にコンパイルしたいかもしれません。これはgcが行うように、プログラムの実行に必要なものすべてを含めるためです。これを行うには、gccgoに-staticスイッチを追加します。生成されたELFファイルがどのようにリンクされているか不明な場合は、readelf -d <elf>またはobjdump -T <elf>で検査してください。

クロス-gccgo対応バージョンのGoツールのビルド

前提

  • ソースからのGoのインストールの手順に従ったと仮定すると、`$GOROOT`にGoソースのチェックアウトバージョンがあるはずです。
  • 環境変数`$GOROOT`が設定されています。
  • 環境変数`$GOARCH`と`$GOOS`はターゲットアーキテクチャとオペレーティングシステムを表します。これらを特定し、クロスコンパイルしたいときにこれらの値に設定してください。

ビルド

Goツールでビルドする際に使用するコンパイラは、`go build -compiler gccgo `で指定できます。しかし、これだけでは不十分です。`$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] `$GOROOT`外のディレクトリにGoソースをクローンします。これは、これからコンパイルする`cmd/go`が特別に扱われるため必要です。
  • [1] ここでは、ホストをターゲットとするgccgoを使用する必要があり、クロスコンパイル用のgccgoではありません。このために$PATHが正しく設定されていることを確認してください。
  • [2] 既存のGoバイナリと区別するために、xgoという名前のバイナリが生成されます。例えば、ターゲットがMIPSであればmgoのように、適切な名前に変更してください。
  • [3] コンパイルステップ(go build)は、gccgoがGoプロジェクトに遅れをとっているため(少なくともgo mercurial tip 7f2863716967時点では)、いくつかのコンパイルエラーで失敗する可能性があります。これらのエラーは、コメントアウトするか、より巧妙な方法で修正し、再コンパイルしてください。

Goプログラムのクロスコンパイル

_xgo_とクロスコンパイル版の_gccgo_を見つけるように`$PATH`を設定し、`$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ページは、「[golang-nuts] MIPSクロスコンパイルの簡素化?」からの教訓にインスパイアされました。https://groups.google.com/forum/#!topic/golang-nuts/PgyS2yoO2jM


このコンテンツはGo Wikiの一部です。