今の gcc だとすごく簡単にクロス環境を作ることができます。 特に、ライブラリなしの C 言語コンパイラなら何も考えずに configure + make で 作ることができます。
しかしながら、ライブラリがないのはさみしいので、 ここでは Cygnus の newlib による標準 C ライブラリ実装を 使えるようにする方法を説明します。 これと同じことを実現しているものに、DevKitAdvance という 定番環境がありますが、
ベースとなっている binutils, gcc, newlib のバージョンが若干古い
Linux 版は Windows 版よりも古い
Linux 版は微妙におかしい
という事情があるので、ここでは
gcc-3.4.1
binutils-2.15
newlib-1.12.0
という(この文書執筆時点での)最新環境に、 Windows 版 DevKitAdvance の最新のランタイムライブラリ環境を 組み合わせた環境を UNIX で構築します。
binutils と gcc は、GNU のミラーから適当に持ってきてください。 newlib は RedHat から落とせます。
これらに加えて、私の作ったパッチが ここ にあるので、適当に一番新しそうな奴を持ってきておいてください。
(2003-12-10 以前のパッチを使う場合には、cube さんによる このような修正 もしておいたほうが良いかもしれません。 2004-07-15 以降のパッチには含まれていますし、 2003-12-10 以前のパッチを使う必要はほとんどないと思いますが。 あえて旧バージョンのツールを使いたい場合でも、 binutils 以外はオフセットが出るだけでそのままパッチが当たるような気もします)
物がそろったら、以下のような作業を行います。 パスは適宜読み替えてください。
展開とパッチ当て:
% tar zxf binutils-2.15.tar.bz2 % tar zxf gcc-3.4.1.tar.bz2 % tar zxf newlib-1.12.0.tar.gz % patch -p0 < patches-devgba-2004-07-15/binutils-2.15.patch % patch -p0 < patches-devgba-2004-07-15/gcc-3.4.1.patch % patch -p0 < patches-devgba-2004-07-15/newlib-1.12.0.patch
gcc と一緒に newlib をコンパイルするための symlink:
% cd gcc-3.4.1 % ln -s ../newlib-1.12.0/newlib ../newlib-1.12.0/libgloss \ ../newlib-1.12.0/COPYING.NEWLIB .
binutils のビルドとインストール:
% cd ../binutils-2.15 % mkdir _build_ % cd _build_ % ../configure --prefix=/usr/local/apps/cross-arm-agb-elf \ --target=arm-agb-elf --disable-nls --with-cpu=arm7tdmi \ --enable-targets=arm-elf,arm-coff,arm-aout % gmake % sudo gmake install
gcc / newlib のビルドとインストール:
% cd ../../gcc-3.4.1 % mkdir _build_ % cd _build_ % PATH=/usr/local/apps/cross-arm-agb-elf/bin:$PATH ../configure \ --prefix=/usr/local/apps/cross-arm-agb-elf --target=arm-agb-elf \ --disable-nls --with-cpu=arm7tdmi \ --enable-targets=arm-elf,arm-coff,arm-aout --with-newlib \ --with-headers=`pwd`/../newlib/libc/include/ --with-gc=simple \ --enable-multilib --enable-interwork --enable-languages=c,c++ \ --disable-threads --disable-shared % PATH=/usr/local/apps/cross-arm-agb-elf/bin:$PATH gmake % PATH=/usr/local/apps/cross-arm-agb-elf/bin:$PATH sudo gmake install
C++ の利用もできます。 しかしながら、libstdc++ のコンパイルにすごく時間がかかります。 コンパイルに時間がかかっているのは主に locale や iostream 系といった 組み込みプログラムではまず使われない部分なので、多少馬鹿馬鹿しいですね。
C++ が必要なければ gcc の configure における引数 --enable-languages から c++ を外してください。
私のパッチに含まれている crt0 および ldscript は、 Windows 版の DevKitAdvance の R5beta3 から持ってきたものです。 デフォルトで使われる crt0.o は、
結果のバイナリが ROM に配置されると仮定
任天堂シグネチャなし
割り込みハンドラなし(*)
という設定になっていますので、 これ以外の場合には自前で crt0.o を用意してやる必要があります。
(*) 「これがないと割り込みが使えない」というわけではなくて、 単に isr.S を入れてないだけです。自前で ISR を用意すれば使えます。 たとえば、 GBAプログラミング研究所 さんのサンプル(後述「テスト」を参照)に IRQ_devkit というのがありますが、 これは自前でハンドラを用意しているので isr.S を組み込んだ crt0.o を 別途用意する必要はありません。
上のような設定で build された gcc は ELF イメージを吐くので、 実際に GBA で使えるようにするには objcopy で raw image を吐かせます:
% arm-agb-elf-gcc -o hoge.elf hoge.c % arm-agb-elf-objcopy -O binary hoge.elf hoge.bin
GBAプログラミング研究所 さんの GCCコンパイラ利用法 DevKitAdvance編 というページから適当なサンプルを拾ってきて、
rm *.gba として、すでにあるバイナリを消す
Makefile に CC=arm-agb-elf-gcc を追加
objcopy を arm-agb-elf-objcopy と書き換え
とした上で、適当に PATH を設定して make を走らせるとコンパイルできるはずです。
IRQ_devkit だけは Makefile がないので、
% arm-agb-elf-gcc -o test.elf main.c spprint/nums.c % arm-agb-elf-objcopy -O binary test.elf test.gba
とすると良いでしょう。
出来上がったバイナリは、シグネチャがないので実機では動きませんが、 VisualBoyAdvance ならば元気に動きます: