buildrootは組込み向けのLinuxを作成できるビルドシステムである。オープン ソースのビルドシステムは各種あるが、最も手軽に触れることができるものの ひとつである。今回はqemu-systemu-i386で利用する手順を記載する。また、 busyboxのinitをGDBでデバッグする。
1. メリット
1.1. 小サイズ
Ubuntu等のLinuxディストリビューションは最小構成でインストールしても数 GByteのルートファイルシステムとなるが、buildrootの場合は数MByteのルー トファイルシステムを作成できる。メインのパッケージとしてbusyboxと uClibcが使われている。以下はbuildrootでデフォルトで用意されている設定 のqemu_x86_defconfigを用いて作成した場合のサイズである。
-rw-rw-r-- 1 <me> <me> 2.0M 1月 16 19:05 bzImage -rw-rw-r-- 1 <me> <me> 2.4M 1月 16 19:05 rootfs.ext2
1.2. 幅広い対応アーキテクチャ
x86向けのみではなく、ARM等の各種CPU向けのバイナリを作成できる。
2. ダウンロード
安定板は以下から取得できる。
http://buildroot.uclibc.org/downloads/buildroot-2013.11.tar.gz
リポジトリは以下。
git clone git://git.buildroot.net/buildroot
3. 構成
自分が把握している構成は以下の通り。
3.1. dlディレクトリ
buildrootはmakeを実行する段階でパッケージのアーカイブを開発元サイトか らダウンロードする仕組みになっており、そのアーカイブが本ディレクトリに 格納される。make distcleanを実行するとdlディレクトリまで削除されてしま うので、パッケージの再ビルドを実行したい場合はmake cleanを使用した方が 良い。make cleanはoutputディレクトリを削除するに留まる為である。
3.2. outputディレクトリ
output/imagesにルートファイルシステムとカーネルのイメージが作成される。 output/targetはoutput/images/root.ext2とは別であるらしい。起動用のルー トファイルシステムとしてoutput/targetを使用すると上手く起動しない場合 がある。output/buildディレクトリにルートファイルシステムに格納されるパッ ケージとそのパッケージのビルドに必要なパッケージが置かれてビルドされる。
3.3. packageディレクトリ
各種パッケージのパッチとコンフィグが置かれている。uClibc-0.9.33.2のコ ンフィグを変えたい場合はpackage/uclibc/uClibc-0.9.33.configに反映させ、 パッチを当てたい場合はpackage/uclibc/0.9.33.2/に置けば良い。
3.4. boardディレクトリ
カーネルのコンフィグが置かれている。カーネルコンフィグを変え、それを恒 久的に反映させたい場合はboardディレクトリ配下に反映させる必要がある。
4. 設定
4.1 buildrootの設定
configsディレクトリ配下にqemu_x86_defconfigがあるので利用する。
$ make qemu_x86_defconfig $ make menuconfig
GCCのバージョンを4.6.xにする。4.4. GCCのバージョンを4.6.xにする理由を 参照。
Symbol: BR2_GCC_VERSION_4_6_X [=y]
Type : boolean
Prompt: gcc 4.6.x
Location:
-> Toolchain
-> GCC compiler Version (<choice> [=y])
Defined at package/gcc/Config.in.host:41
Depends on: <choice> && !BR2_microblaze [=n] && !BR2_arc [=n] &&
!BR2_avr32 [=n] && !BR2_bfin [=n] && !BR2_cortex_a7 [=n] &&
BR2_sparc_sparchfleon [=n] && !BR2_sparc_sparchfleonv8 [=n] &&
!BR2_sparc_sparcsfleon [=n] && !BR2_sparc_sparcsfleonv8 [=n] &&
BR2_pj4 [=n]
Selects: BR2_GCC_NEEDS_MPC [=y]
QEMUで-nographicオプションを利用する為、コンソールをtty1からttyS0にす る。-nographicを使用せず、GUIウィンドウを利用する場合はtty1で良い。
Symbol: BR2_TARGET_GENERIC_GETTY_PORT [=ttyS0]
Type : string
Prompt: TTY port
Location:
-> System configuration
-> Run a getty (login prompt) after boot (BR2_TARGET_GENERIC_GETTY [=y])
-> getty options
Defined at system/Config.in:217
Depends on: BR2_ROOTFS_SKELETON_DEFAULT [=y] && BR2_TARGET_GENERIC_GETTY [=y]
4.2. busyboxの設定
busyboxの設定を変える場合は以下を使用。
make busybox-menuconfig
デバッグシンボルを有効にする。
Symbol: DEBUG [=y]
Prompt: Build BusyBox with extra Debugging symbols
Defined at Config.in:652
Location:
-> Busybox Settings
-> Debugging Options
最適化を無効にする。なくても良いだろうけど、ステップ実行が飛び飛びにな るのが嫌なので。
Symbol: DEBUG_PESSIMIZE [=y]
Prompt: Disable compiler optimizations
Defined at Config.in:663
Depends on: DEBUG
Location:
-> Busybox Settings
-> Debugging Options
-> Build BusyBox with extra Debugging symbols (DEBUG [=y])
4.3. その他の設定
uClibcの設定を変える場合は以下を使用。
$ make uclibc-menuconfig
Linuxカーネルの設定を変える場合は以下を使用。
$ make linux-menuconfig
4.4. GCCのバージョンを4.6.xにする理由
GCC-4.7.x以降でuClibcをビルドするとundefined referenceな関数がいくつか 存在し、stripコマンドを用いない場合にエラーとなってしまう。buildrootで はuClibcの修正待ちというステータスである。
http://buildroot-busybox.2317881.n4.nabble.com/ucilbc-0-9-33-2-fails-to-build-on-buildroot-2013-11-internal-toolchain-td56650.html
uClibcのパッチを持ってくるこ とでx86では問題が解消されるが、ARMでは完全に解消されないようである。 本書ではこの問題を避ける為に4.6.xを使用している。
commit 8d31a6e50db423b89082b64a3250eec1b94a7456
Author: Bernhard Reutner-Fischer <...>
Date: Wed Jan 16 13:36:40 2013 +0100
buildsys: link libgcc_eh if DODEBUG
with -O0 we (e.g. lockf) might end up with references to
_Unwind_Resume, so pull in gcc_eh in this case..
Signed-off-by: Bernhard Reutner-Fischer <...>
5. ビルド
$ make
パッケージをビルドし直すには<package name>-rebuildを実行する。busybox の場合は以下となる。
$ make busybox-rebuild
6. 実行例
output/images/rootfs.ext2にルートファイルシステムのイメージが作成され る。GDBから参照できるようにループバックでバイスとしてマウントする。
$ mkdir mnt $ sudo mount -t ext2 -o loop,rw output/images/rootfs.ext2 mnt/
QEMUを以下の設定で起動する。-hdaオプションで指定したルートファイルシス テムのイメージはパーティションを設定していないのでroot=/dev/sdaでマウ ント先を指定している。
$ qemu-system-i386 --kernel output/images/bzImage \
-hda output/images/rootfs.ext2 \
-gdb tcp::10000 -S \
-nographic \
-append "console=ttyS0,115200 root=/dev/sda rw"
GDBを以下の設定で起動する。
$ cat gdb.scr target remote localhost:10000 symbol-file output/build/busybox-1.22.0/busybox source output/build/busybox-1.22.0 b main la src c $ gdb -x gdb.scr
以下はbusyboxへのシンボリックリンクの/sbin/initからbusyboxが呼び出され、 busyboxのmain関数でbreakした所である。busyboxは複数のコマンド群から形 成されており、シンボリックリンク経由あるいは第一引数にコマンド名を指定 して各コマンドを実行する。