クロスコンパイルとは何ぞや??
そもそも、パソコンと言うのは、理解できる言語と言うのが限られています。何で区別されているかと言うと、パソコンの前頭葉とも言うべきCPU。このCPUのアーキテクチャというもので、既に生まれた瞬間から理解できる言葉が分かれています。Pentium4,PowerPC,SPARCなどなどなど。Pentum4で解釈できる言葉(実行プログラム)をPowerPCで分かってもらおう(実行させよう)としても無理。PowerPCならばPowerPC用に解釈できる言葉で書いてあげないといけません。
さて、ところでこのPentium4だの、PowerPCだのが理解できる言葉は、果たして人間様が理解できる言葉か?というと、到底理解できる言葉ではありません(まれに理解できる人も居るけど)。で、この人間様に理解できる言葉(プログラム言語)をCPUが分かる言葉(マシン語)に変換してあげるのがコンパイラ。コンパイラを動かす作業がコンパイル。
で、クロスとは、何がクロスするんじゃい?と。
あるCPUで動作する、別のCPUの言葉に変換するコンパイラの事をクロスコンパイラと言いますねん。例えばPentium4とか積んでるAT互換機上で動作する、プログラム言語をMacなんかのPowerPC上で動く言葉に変換してくれるコンパイラの事ですね。
んなことして何がうれしいノン?
普通は、組み込み開発なんかで使います。例えば、新しいエアコンを開発したとしましょう。最近のエアコンは、コンピュータとか搭載してるので、結構賢いソフトが動作します。さて。このエアコン上で動くソフトってどーやって開発するの?まさかエアコンのコンピュータ上で開発する?わけは~ない。パソコンとか使ってプログラムを書き書きします。で、このエアコンで理解できる言語に変換してやろーとするときに、パソコンで動くエアコン言語向けコンパイラを動かして、エアコン上で動作するプログラムを作り、エアコンにインストールして動作させるのですねー。
で、おいちゃんは何に使用するか。
玄箱はPowerPC。だけどこの玄箱君はPowerPC266MHzととっても遅い。どれぐらい遅いかと言うと、10年前のパソコンと同じくらいの遅さ(10年前なら超高速だったんだけどね…)。Gentooのコンパイルは異様に時間がかかってたまらない。さて、傍らには、Pentium4 3GHzとかの、現在では十分早いパソコンがおるではないですか。どーにかしてこいつにコンパイル作業をやらせられないか…となると、おお!クロスコンパイルだ!!と言うわけですね。
クロスコンパイル環境の準備
Gentooの場合はチョー簡単。
# emerge crossdev
と打つと、crossdevというツールをインストールしてくださります。crossdevとただ打つと
Usage: crossdev [options] --target TARGET Options: --b, --binutils ver Specify version of binutils to use --g, --gcc ver Specify version of gcc to use --k, --kernel ver Specify version of kernel headers to use --l, --libc ver Specify version of libc to use -C, --clean target Uninstall specified target -b, -d, -p, -v, -q Options to pass to emerge (see emerge(1)) Stage Options: -s0, --stage0 Build just binutils -s1, --stage1 Also build a C compiler (no libc/C++) -s2, --stage2 Also build kernel headers -s3, --stage3 Also build the C library (no C++) -s4, --stage4 Also build a C++ compiler [default] Extra Fun (must be run after above stages): --ex-only Skip the stage steps above --ex-gcc Build extra gcc targets (gcj/ada/etc...) --ex-gdb Build a cross gdb Target (-t): takes the form: ARCH-VENDOR-OS-LIBC Run 'crossdev -t help' for examples
どべべーっとヘルプが出てきます。このツールを使って作業していくですよ…
その前に、準備が必要。
crossdevの為の準備
crossdevには、環境変数PORTAGE_OVERLAYが必要です。 仮に/usr/local/portageとしましょうか。ここに、クロスコンパイルを実施するパッケージを追加していきます。
# cd /usr/local/portage # mkdir cross-<CPU名>-<サフィックス>-<OS名>-<libcタイプ>
ここで、CPU名はi686とか、armとか。サフィックスは何でも良い。OS名はlinux,libcタイプはglibcならばgnu,uclibcならばuclibcを指定します。但し、distccで玄箱からクロスコンパイルを実施させる都合上、玄箱君の側のgccのCHOSTとあわせる必要があります。なので、玄箱君の中のmake.confのCHOST項を参照してください。うちだと
# mkdir cross-powerpc-unknown-linux-gnu
になりますです。さらにその配下にクロスコンパイルに必要なbinutils,gcc,linux-headers.glibcをシンボリックリンクで作っておきます。
# cd cross-powerpc-unknown-linux-gnu # ln -s /usr/portage/sys-devel/binutils # ln -s /usr/portage/sys-devel/gcc # ln -s /usr/portage/sys-libs/glibc # ln -s /usr/portage/sys-kernel/linux-headers
で、さらに/etc/make.confに
PORTDIR_OVERLAY="/usr/local/portage"
を追加してあげましょう。するってーと
# emerge cross-powerpc-unknown-linux-gnu/gcc
と打つと、PowerPCクロスコンパイラ用のgccがパッケージとして管理される仕組み。ああー便利♪
crossdevを使ってみる
# crossdev --b <binutilsのバージョン> \ --g <gccのバージョン> \ --k <linuxheadersのバージョン>\ --l <glibcのバージョン> \ -t powerpc-unknown-linux-gnu
ここで、各バージョンは、玄箱君が使用しているバージョンとあわせる必要あり。-t の後ろは玄箱君のCHOSTと合わせる必要あり、です。気をつけて!!
さらに、crossdevを実施していると、途中でエラー終了すると思いますです。gccの第2コンパイル中にlibstdc++をコンパイルしているときに、「/usr/powerpc-unknown-linux-gnu/usr/lib/libc.so.6が見つからん!」といわれて止まってしまうと思われます。これに対処するために
# cd /usr/powerpc-unknown-linux-gnu/ # ln -s . usr
とやっておきましょう。でもう一度crossdevを実施すると、ちゃんとコンパイルが通るようになると、思いますよぅ~。
玄箱君側
で、玄箱君側で、他所のPCにコンパイルを依頼するように設定します
# distcc-config --set-hosts <コンパイル母艦のIPアドレス>
必要であれば、/etc/distcc/hostsを編集して、依頼するジョブの数とかを最適化してやりましょう。ここでもう一工夫。ふつーにdistccをインストールすると/usr/lib/distcc/binの下が
c++ -> /usr/bin/distcc cc -> /usr/bin/distcc g++ -> /usr/bin/distcc gcc -> /usr/bin/distcc powerpc-unknown-linux-gnu-c++ -> /usr/bin/distcc powerpc-unknown-linux-gnu-g++ -> /usr/bin/distcc powerpc-unknown-linux-gnu-gcc -> /usr/bin/distcc
こんな風にシンボリックリンクが張られます。これだと、distccが分散コンパイルを呼び出すときに、g++とかgccでコンパイルを呼び出すと、対向側でも普通にg++とかgccが呼ばれます。CPUが同じ場合にはなんの問題もないのですが、CPUが異なるホストでコンパイルする場合は、意図的にクロスコンパイラの方を呼んでくれないと困ります。なので、c++,cc,g++,gccでコンパイルを実行するパッケージのために、powerpc-unknown-linux-gnu-XXXというコマンドに化かすシェルを作ってやります。例えばpowerpc-unknown-linux-gnu-wrapperというシェル。中身は
#!/bin/bash exec /usr/lib/distcc/bin/powerpc-unknown-linux-gnu-${0##*/} "$@"
こんな感じ。で、/usr/lib/distcc/binの中は
c++ -> powerpc-unknown-linux-gnu-wrapper cc -> powerpc-unknown-linux-gnu-gcc g++ -> powerpc-unknown-linux-gnu-wrapper gcc -> powerpc-unknown-linux-gnu-wrapper powerpc-unknown-linux-gnu-c++ -> /usr/bin/distcc powerpc-unknown-linux-gnu-g++ -> /usr/bin/distcc powerpc-unknown-linux-gnu-gcc -> /usr/bin/distcc powerpc-unknown-linux-gnu-wrapper
こんな風にしておいてやる。すると、実行コマンドがgccでコンパイルされても、distccにはpowerpc-unknown-linux-gnu-gccというコマンドで実行され、コンパイル母艦側で意図的にクロスコンパイラが使えるようになるという寸法。
コンパイル母艦側
/etc/conf.d/distccdでコンパイルを受け付けるホストとかを適切に設定しておいてやりましょう。で
# /etc/init.d/distccd
でdistccデーモンを立ち上げておいてやります。
パッケージコンパイルの準備
玄箱君のmake.confに
FEATURES="distcc" MAKEOPTS="-j4"
など、適切に入れておいてやりましょう。おいちゃんちでは、x86_64でHTなPentium4マシンをコンパイル母艦に使用しているので、並列コンパイル数を4に指定しております。
Page Info | |
---|---|
Page Name : | GentooLinuxな生活/分散クロスコンパイルで悩む |
Page aliases : | None |
Page owner : | maruo |
Can Read | |
Groups : | All visitors |
Users : | All visitors |
Can Edit | |
Groups : | No one |
Users : | No one |