[[Gentoo Linuxな生活/サーバ設定関連]] *説明の前に [#ld9d5e6c] **クロスコンパイルとは何ぞや?? [#k14720aa] そもそも、パソコンと言うのは、理解できる言語と言うのが限られています。何で区別されているかと言うと、パソコンの前頭葉とも言うべきCPU。このCPUのアーキテクチャというもので、既に生まれた瞬間から理解できる言葉が分かれています。Pentium4,PowerPC,SPARCなどなどなど。Pentum4で解釈できる言葉(実行プログラム)をPowerPCで分かってもらおう(実行させよう)としても無理。PowerPCならばPowerPC用に解釈できる言葉で書いてあげないといけません。 さて、ところでこのPentium4だの、PowerPCだのが理解できる言葉は、果たして人間様が理解できる言葉か?というと、到底理解できる言葉ではありません(まれに理解できる人も居るけど)。で、この人間様に理解できる言葉(プログラム言語)をCPUが分かる言葉(マシン語)に変換してあげるのがコンパイラ。コンパイラを動かす作業がコンパイル。 で、クロスとは、何がクロスするんじゃい?と。 あるCPUで動作する、別のCPUの言葉に変換するコンパイラの事をクロスコンパイラと言いますねん。例えばPentium4とか積んでるAT互換機上で動作する、プログラム言語をMacなんかのPowerPC上で動く言葉に変換してくれるコンパイラの事ですね。 **んなことして何がうれしいノン? [#h733a81d] 普通は、組み込み開発なんかで使います。例えば、新しいエアコンを開発したとしましょう。最近のエアコンは、コンピュータとか搭載してるので、結構賢いソフトが動作します。さて。このエアコン上で動くソフトってどーやって開発するの?まさかエアコンのコンピュータ上で開発する?わけは~ない。パソコンとか使ってプログラムを書き書きします。で、このエアコンで理解できる言語に変換してやろーとするときに、パソコンで動くエアコン言語向けコンパイラを動かして、エアコン上で動作するプログラムを作り、エアコンにインストールして動作させるのですねー。 で、おいちゃんは何に使用するか。 玄箱はPowerPC。だけどこの玄箱君はPowerPC266MHzととっても遅い。どれぐらい遅いかと言うと、10年前のパソコンと同じくらいの遅さ(10年前なら超高速だったんだけどね…)。Gentooのコンパイルは異様に時間がかかってたまらない。さて、傍らには、Pentium4 3GHzとかの、現在では十分早いパソコンがおるではないですか。どーにかしてこいつにコンパイル作業をやらせられないか…となると、おお!クロスコンパイルだ!!と言うわけですね。 *クロスコンパイル環境の準備 [#hf89586e] 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の為の準備 [#u0c301f8] 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を使ってみる [#v39e29b5] # 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を実施すると、ちゃんとコンパイルが通るようになると、思いますよぅ~。 *distccの設定 [#s7056ec4] さて、玄箱君とクロスコンパイル母艦マシンにそれぞれdistccをインストールします # emerge distcc **玄箱君側 [#p071846e] で、玄箱君側で、他所の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というコマンドで実行され、コンパイル母艦側で意図的にクロスコンパイラが使えるようになるという寸法。 **コンパイル母艦側 [#idb029a0] /etc/conf.d/distccdでコンパイルを受け付けるホストとかを適切に設定しておいてやりましょう。で # /etc/init.d/distccd でdistccデーモンを立ち上げておいてやります。 *パッケージコンパイルの準備 [#g3a5b512] 玄箱君のmake.confに FEATURES="distcc" MAKEOPTS="-j4" など、適切に入れておいてやりましょう。おいちゃんちでは、x86_64でHTなPentium4マシンをコンパイル母艦に使用しているので、並列コンパイル数を4に指定しております。 *コンパイルしてみよう [#q025c123] # emerge -uD world でパッケージのコンパイルとかをすると、パッケージの展開、configure実行あたりは玄箱君で実施するので猛烈に遅いのですが、コンパイルを開始すると、嵐のような勢いでコンパイルを実施して行きます。 対してコンパイル母艦側では、依頼されたコンパイルを裏でこなしているので、時々CPU負荷が上下動します。ん~やったね~♪これで玄箱君でのコンパイル運用はかなーり楽になるはずですよう。 *さらなる活用法 [#j2f343f7] 組み込み開発を行ってる御仁は、オープンソースパッケージを組み込むのに、かなり重宝すると思うデス。例えばARMで動作するネイティブマシンを作っておき、Linuxを駆動させておく。オープンソースパッケージはconfigureだけはネイティブで行わないとまともに通らなかったりします。なのでネイティブCPUでパッケージのコンパイルを実施しているふりして、強力な外部CPUでクロスコンパイルを実施させると言う活用が出来て、開発効率が飛躍的に増大すると思うだな~。試してみてちょ~~
(This host) = https://femt.ddo.jp