Mountain Lionユーザのためのクロスコンパイラビルド

OSを開発する上で@liva_jyくんに勧められてGCCのクロスコンパイラをMacでビルドすることにした。
ロスコンパイラを使わなくてもLinuxでOS自体はビルドできるけど、確かに面倒だし。
Macで直接ビルドして、そのままデバッグしたいのは確か。
が、前途多難でmakeが通らない。
Mountain Lionでやってるために、古い情報が追いついてない模様。
以下、悪戦苦闘の記録。

【環境】
マシン: Macbooc Pro Retina (13 inch)
OS:Mac OS X 10.8.4 (Mountain Lion)
プロセッサ: Intel Core i5 2.5 GHz
メモリ: 8GB

OSDev.orgのBuilding GCC Cross Compilerのページを見ながら進めてみる。

ビルドしなくちゃいけないもの

まずは依存関係から

これからビルドするツールのインストール先を$HOME/optということにしておきます。

export PREFIX="$HOME/opt"

GMP -> MPFR -> MPC
の順にインストールしなきゃいけなかったはず。
ダウンロードは上記のリンクから。
インストールはすべてソースコードのディレクトリで

mkdir build
cd build
../configure --prefix=$PREFIX
make 
make install

で。失敗したらbuildの中身を消して、sudoでもつけてもう一回やってみよう。
(ビルド時にbuildディレクトリを作る習慣がなかったので、今考えるといろいろとヤバかった)

binutilsのインストール

binutilsをインストールします。
binutilsって確かバイナリ系のツールセットだったっけかな…)
これもダウンロードして

./configure --prefix=$PREFIX --disable-nls
make
make install

でインストール。(以下buildディレクトリを作るコマンドは省略するが、作った方が安心)
特に難しいことはない。
ちなみに、--disable-nlsオプションはNative Language Supportを切るためのオプションらしく、今回はいらないからこれを切ればビルドが速くなる程度のことらしい。

確かbinutilsと次のlibiconv辺りはmake時にエラーっぽいのが出てもインストールはできてしまったはず。

最新版libiconvのインストール

Preparing for the build:For Mac OS X Usersの項を見てみると、OS Xではlibiconvというライブラリがめっちゃ古いらしい。
てなわけでlibiconvをインストールしよう。
ダウンロードしたら

./configure -prefix=/usr/local
make
make install

でインストール。
最新版のlibiconvはGCCのビルドで必要になるらしいので、GCCのビルド時(configure時)には忘れずに--with-libiconv-prefix=/usr/localオプションをつけておくこと。

llvm版のgccのインストール

さらにPreparing for the build:For Mac OS X Usersの項をよーく見てみると、脚注に「Lionよりも新しいバージョンのOSを使ってる人はllvmを使わないgccが入ってないから、非llvmgccを頑張ってビルドしてね☆」と書いてある(意訳)。
LLVMは本筋ではないので知らなかったらググってもらうことにする。
これからどうするかというと、

llvmgccをビルド->非llvm-gccでクロスコンパイラをビルド

という二段構えのビルドを行うことになる。
今、どっちのgccをビルドしているかを混乱しないように、明確に区別しよう。

んで、こちらのサイトを参照せよとのこと。
しかーし!親切にスクリプトを置いてくれているが、僕はMacPortsを入れてるのでHomebrewを入れ直すのが面倒くさい!
ので、まあ一からコマンドを手打ちする。
最新版のGCCはとりあえずダウンロードしておく。
注意するのは以下の通り。
ややこしいので、クロスコンパイラをビルドするコンパイラ(今からビルドするやつ)をformer-gcc、クロスコンパイラをlater-gccとする。
基本的に(former-gccのバージョン)>=(later-gccのバージョン)じゃないと安定しにくいらしいとのことなので、それに注意しつつできるだけ新しいバージョンをビルドしよう。

ちなみに、Lion以上ではOSDev.orgのリンク先にある以下のようなオプションをconfigureでつけてやる必要がある模様。
【参考】http://apple.stackexchange.com/questions/38222/how-do-i-install-gcc-via-homebrew/38247#38247

ちなみに、ビルド前にgmp,mpfr,mpc,libiconvのソースをgccのソースディレクトリに入れておかないといけないとか。

mv gmp-x.y.z gcc-x.y.z/gmp
mv mpfr-x.y.z gcc-x.y.z/mpfr
mv mpc-x.y.z gcc-x.y.z/mpc
mv libiconv-x.y.z gcc-x.y.z/libiconv

./configure \
   --prefix=$HOME/opt/gcc-x.y.z \
   --with-gmp=$TOOL_DIR \
   --with-mpfr=$TOOL_DIR \
   --with-mpc=$TOOL_DIR \
   --program-suffix=x.y.z \
   --enable-languages=c,c++ \
   --with-system-zlib \
   --enable-stage1-checking \
   --enable-plugin \
   --enable-lto \
   --disable-multilib \
   --with-libiconv-prefix=/usr/local

sudo make bootstrap
sudo make install

$TOOL_DIRは、さっきGMP、MPFR、MPCをインストールしたディレクトリ。x.y.zはビルドするgccのバージョン。
ちなみに、このビルドにはむっさ時間がかかるので、4コア使える場合はmake -j4しよう。というかそれでも時間がかかるので、時間に余裕を持ってビルドしよう。(1時間くらいは覚悟すること)

それと、こんなビルド時にこんなエラーが出るかもしれない。僕は出た。

checking LIBRARY_PATH variable... contains current directory
configure: error:
*** LIBRARY_PATH shouldn't contain the current directory when
*** building gcc. Please change the environment variable
*** and run configure again.

これは$LIBRARY_PATHにセットされている値を変えればいいらしい。
たぶんLIBRARY_PATH=/opt/local/lib:となってるだろうから、

export $LIBRARY_PATH=/opt/local/lib

とする(コロンをとってやる)。

それでもgccに怒られてビルドが通らないときは、sudoとかつけてみるとうまくいったりする。
buildディレクトリを作ってるから、失敗しても消せる。

ロスコンパイラのビルド

さあ、いよいよお待ちかねのクロスコンパイラのビルド。
さっきビルドしたGCCをこれから使って、クロスコンパイラを作ろう。
まずはそのために、環境変数にさっき作ったツールを設定しておこう。

export CC=$PREFIX/gcc-x.y.z/bin/gccx.y.z
export CXX=$PREFIX/gcc-x.y.z/bin/g++x.y.z
export CPP=$PREFIX/gcc-x.y.z/bin/cppx.y.z
export LD=$PREFIX/gcc-x.y.z/bin/gccx.y.z

そして、クロスコンパイラのビルド先を設定しよう。

mkdir ~/opt/cross/
export PREFIX=$HOME/opt/cross/

で、クロスコンパイラのサポートアーキテクチャと、パスをちょこっと設定。
僕はi686-elf用のコンパイラを作るので以下の通り。

export TARGET=i686-elf
export PATH="$PREFIX/bin/:$PATH"

環境変数関連の設定は終わり。次はbinutilsのビルド。
同様にbinutilsのソースディレクトリに入って、ビルドしよう。

mkdir build
cd build
../configure --target=$TARGET --prefix=$PREFIX --disable-nls
make
make install

そして、最後にGCCをビルド。

mv gmp-x.y.z gcc-x.y.z/gmp
mv mpfr-x.y.z gcc-x.y.z/mpfr
mv mpc-x.y.z gcc-x.y.z/mpc
mv libiconv-x.y.z gcc-x.y.z/libiconv

cd gcc-x.y.z
mkdir build
cd build
../configure --target=$TARGET --prefix=$PREFIX --disable-nls --enable-languages=c,c++ --without-headers --with-libiconv-prefix=/usr/local
make all-gcc
make all-target-libgcc
make install-gcc
make install-target-libgcc

これで完了!
ちなみに、僕はlibiconv,binutils,gccはsudoをつけないとビルドが通らなかった覚え。