クロスコンパイラ

**クロスコンパイラ**（）は、コンパイラが動作している環境以外のプラットフォーム向けに実行ファイルを生成する機能を持つコンパイラである。クロスコンパイラは主に組み込みシステム向けのコンパイラや、マルチプラットフォーム対応のコンパイラとして使われる。

必要最小限のメモリしか搭載していないことが多いマイクロコントローラを使った組み込みシステムや、セキュリティのためアプリケーションソフトウェアのインストールや動作形態に制限のあるモバイルオペレーティングシステム環境など、実行ファイルを動作させたいプラットフォームがコンパイル環境としては不適切な場合にはクロスコンパイラは必須である。
システムが複数のプラットフォームをサポートする場合に、準仮想化のためのツールとしてクロスコンパイラを利用することが一般化しつつある。

## 使用法
クロスコンパイラの基本的使用法は、ビルド環境をターゲット環境から分離することである。これは以下のような場合に便利である。
* リソースが極めて限られている組み込みシステム。例えば電子レンジに組み込まれたコンピュータは非常に小型で、入力として操作パネルとドアの開閉センサ、出力としてディスプレイとスピーカーがあり、調理用機械を制御する。このコンピュータ上で、コンパイラやファイルシステムや開発環境を動作させるのには無理がある。デバッグやテストには組み込みシステムが備えている以上のリソースが必要とされるため、クロスコンパイルは通常のコンパイルよりもエラーを多めに検出する傾向がある。
* 複数マシン向けのコンパイル。例えば、企業が1つのオペレーティングシステム (OS) の複数バージョンをサポートする場合や、複数のOSをサポートする場合。クロスコンパイラを使えば、1つのビルド環境でそれら複数のターゲットのコンパイルが可能となる。
* サーバファームでのコンパイル。複数マシン向けのコンパイルと似ているが、サーバファーム上の比較的暇なマシン上で任意のサーバ向けのビルドを行う。
* 新たなプラットフォーム向けのブートストラッピング。新しいプラットフォーム向けにソフトウェアを開発する場合や将来のプラットフォームのエミュレータについて、クロスコンパイラでOSやネイティブのコンパイラといった必要なツールをコンパイルする。

JavaのJava仮想マシン (JVM) のような仮想マシンを使うことで、クロスコンパイラを開発する動機となっている問題の一部は解決される。仮想マシンは、1つのコンパイラの出力を複数の異なるシステムで利用可能にする。

典型的にはアーキテクチャが異なればクロスコンパイラを利用することになる（例えば、MIPSアーキテクチャ向けのプログラムをx86上でコンパイルするなど）。しかしそれだけでなく、OS環境が違うだけであってもクロスコンパイラが使われ、例えばLinux上でFreeBSD用の実行ファイルを作るといった利用が考えられる。さらには、システムライブラリが違う環境向けのクロスコンパイルもある（glibcホスト上でuClibcを使ったコンパイルをするなど）。

## GCCとクロスコンパイル
GCCは、コンパイラ群を集約した自由ソフトウェアであり、クロスコンパイル向けの設定も可能である。GCCは様々なプラットフォームや言語をサポートしている。しかし、手が足りないためにクロスコンパイラの保守がなされていない場合があり、多くのリリースでクロスコンパイラが機能していない。

GCCには、ターゲットプラットフォームごとにbinutilsのコンパイルされたコピーが必要である。その中でも GNUアセンブラ が重要である。従って、binutils をまず `--target=some-target` スイッチ付きでコンパイルしなければならない。GCC も同じ `--target` オプション付きで設定しなければならない。GCCはパスで指定されたbinutilsを使って普通に動作する。パスは（シェルとしてBashを使う場合には）以下のように指定する。

 PATH=/path/to/binutils/bin:$PATH; make

クロスコンパイルを行うGCCでは、ターゲットプラットフォームの標準Cライブラリがホストプラットフォームで利用可能になっている必要がある。少なくとも、crt0というライブラリの一部は必須である。標準Cライブラリ全体をコンパイルした場合、プラットフォームによっては大きすぎることもある。代替として、標準CライブラリのうちC言語のソースコードのコンパイルに必須な部分だけを抽出したnewlibを使う方法もある。GCCでnewlibを使うには `--with-newlib` スイッチを使う。

GNU autotoolsパッケージでは、ビルドプラットフォーム (build platform)、ホストプラットフォーム (host platform)、ターゲットプラットフォーム (target platform) という用語を使う。ビルドプラットフォームとは、コードが実際にコンパイルされる場所を指す。ホストプラットフォームとは、コンパイルされたコードが実行される場所を指す。ターゲットプラットフォームとは、コンパイラを含め実行ファイルを作成するパッケージにのみ適用され、パッケージ自身が生成するオブジェクトコードのタイプを表す（例えば、クロスコンパイラをクロスコンパイルする場合など。カナディアンクロスも参照のこと）。それ以外の場合はターゲットプラットフォームの設定は不適切である。例えば、ドリームキャストで動作するビデオゲームのクロスコンパイルを考えると、コンパイルを行うマシンがビルドプラットフォームで、ドリームキャストがホストプラットフォームとなる。

## カナディアンクロス
カナディアンクロス (Canadian Cross) とは、他のマシンで動作するクロスコンパイラを作成する技法である。三種類のマシンA、B、Cがあるとき、Bで動作してC向けの実行ファイルを生成するクロスコンパイラをA上で作ることをいう。GCCのコンフィグではAをbuild、Bをhost、Cをtargetと言う。buildについては明示的に指定しなくても普通はスクリプトで情報を収集できるが、hostとtargetは当然ながら指定しなければならない。

GCCでカナディアンクロスを行う場合、4つのコンパイラが関わってくる。各GCCクロスコンパイラの後の括弧書きは、ビルド、ホスト、ターゲットの各マシン。

# マシンAのネイティブのプロプライエタリなコンパイラ。これを使ってマシンA上で次のコンパイラを構築する。
# マシンAのGCCネイティブコンパイラ（A-A-A）。これを使ってマシンA上で次のコンパイラを構築する。
# マシンA上でマシンBのコードを生成するGCCクロスコンパイラ（A-A-B）。これを使ってマシンA上で次のコンパイラを構築する。
# マシンB上でマシンCのコードを生成するGCCクロスコンパイラ（A-B-C）。

最後のクロスコンパイラはビルドを行っているマシンA上では動作できないが、マシンB上でそれを使えば、マシンC上で動作する実行ファイルを生成できる。

例えば、NetBSDにはPOSIXシェルスクリプト `build.sh` があり、これを使ってホストコンパイラで自前のツールチェーンを構築でき、さらにそこからクロスコンパイラを構築していくことができる。

このようなクロスコンパイラはそれ以前からもあったが、「カナディアンクロス」という呼称はGCCの開発において命名されたもので、当時のカナダに3つの大きな政党があったことに由来する。

GCCにおいてカナディアンクロスが必要となるのは、GCCおよびbinutilsがconfigure実行時に指定したターゲットプラットフォーム向けのビルドしかできない制約に起因する。LLVMはバックエンドを実行時に指定することにより、サポートされている任意のプラットフォーム向けのビルドが可能なことからカナディアンクロスは必須でなく、ビルドおよびホストプラットフォームのみを指定した通常の意味でのクロスコンパイルが一般的である。

## 関連項目
*コンパイラ

## 脚注

## 外部リンク
* Cross Compilation Tools GNUクロスコンパイルツールについて
* Building Cross Toolchains with gcc GCCクロスコンパイルについてのウィキ
* Scratchbox ARMとx86をターゲットとしたLinux用クロスコンパイル・ツールキット
* Crosstool Linuxで各種クロスコンパイル環境を作るためのスクリプト群
* buildroot 組み込みシステム向けのuClibcベースの環境構築のためのスクリプト群
* T2 SDE 各種標準Cライブラリを使ったLinux上のクロスコンパイル環境を作るスクリプト群
* Cross Linux from Scratch Project