前回 uClibc を開発ツールチェーンにインストールしたので、これを使って hello をコンパイルする。
$ vi hello.c #include <stdio.h> int main(){ printf("hello\n"); return 1; } $ arm-linux-gcc -o hello hello.c homerun@homerun-laptop:~/arm-dev$ arm-linux-gcc -o hello hello.c /usr/local/arm/3.4.1/lib/gcc/arm-linux/3.4.1/../../../../arm-linux/bin/ld: warning: libc.so.6, needed by /usr/local/arm/3.4.1/lib/gcc/arm-linux/3.4.1/../../../../arm-linux/lib/libgcc_s.so, may conflict with libc.so.0
なにか警告が出ている。 リンカのデフォルトライブラリがおかしいらしい。 回避方法は2つ
(回避1) libgcc_s.soのリンク先を変える
$ su # cd /usr/local/arm/3.4.1/arm-linux/lib # rm libgcc_s.so # ln -s libuClibc-0.9.28.so libgcc_s.so
これでもうまくいくことは確認した。
(回避2) specs というファイルでデフォルトライブラリを変更する。
specs ファイルの場所の確認。
$ arm-linux-gcc -v Reading specs from /usr/local/arm/3.4.1/lib/gcc/arm-linux/3.4.1/specs Configured with: 云々...
次のように変更する。
$ su # vi /usr/local/arm/3.4.1/lib/gcc/arm-linux/3.4.1/specs ... *libgcc: %{msoft-float:-lfloat} %{static|static-libgcc:-lgcc -lgcc_eh} ← この3行は本来1行です %{!static:%{!static-libgcc:%{!shared-libgcc:-lgcc} ← この3行は本来1行です %{shared-libgcc:%{!shared: -lgcc}}}} ← この3行は本来1行です ...
表示のため改行しているが、上の3行は1行である。元々あった -lgcc_s の指定を全部消した。
再度 hello をコンパイル
$ arm-linux-gcc -o hello hello.c $
今度はOK。中身を確認する
$ arm-linux-readelf -a hello ELF Header: ... [Requesting program interpreter: /lib/ld-linux.so.2] ← これは不味い ... 0x00000001 (NEEDED) Shared library: [libc.so.0] ← uClibcである ... 8: 000083a4 496 FUNC GLOBAL DEFAULT UND __uClibc_main
共有ライブラリはuClibc が指定されている。これはOK。
しかし、ローダの指定が/lib/ld-linux.so.2 になっている。これは /lib/ld-uClibc.so.0 になってて欲しい。
回避策は2つ
(回避1) ルートファイルシステムで ld-linux.so.2 のリンク先をld-uClibc-0.9.28.soにする。
# cd ...../lib ← ボード用のルートファイルシステムの下の lib に移動する # ln -s ld-uClibc-0.9.28.so ld-linux.so.2 ← ローダの調整
これでもうまくいくことを確認した。
(回避2) 若しくは specs ファイルを変更する。
$ su # vi /usr/local/arm/3.4.1/lib/gcc/arm-linux/3.4.1/specs *link: %{!static:--eh-frame-hdr} %{h*} %{version:-v} ← 元々1行です %{b} %{Wl,*:%*} %{static:-Bstatic} %{shared:-shared} ← 元々1行です %{symbolic:-Bsymbolic} %{rdynamic:-export-dynamic} ← 元々1行です %{!dynamic-linker:-dynamic-linker /lib/ld-uClibc.so.0}← 元々1行です -X %{mbig-endian:-EB} -m armelf_linux -p← 元々1行です
表示のため改行しているが、上の5行は元々1行のもの。ローダを ld-uClibc.so.0 に変えた。
(メモ:リンカオプション --dynamic-linker も使える?リンカのman)
再々度 hello をコンパイル
$ arm-linux-gcc -o hello hello.c
中身を確認する
$ arm-linux-readelf -a hello ELF Header: ... [Requesting program interpreter: /lib/ld-uClibc.so.0] ...
ローダの指定もOK。
helloコマンドをルートファイルシステムにコピーする。やり方は前回と同じ。
上の(回避1)を採用した場合はローダのリンクも行う。
なお、ルートファイルシステムの libuClibc-0.9.28.so や ld-uClibc-0.9.28.so はプレインストールのままにしておく。本当はリコンパイルした uClibc で入れ替えるべきだが、既存のBusyBoxが動かなくなる恐れが大なので止めておく。このテストではhelloがちらっと動いてくれればOKなので、、、
出来た ramdisk.gz をボードへ転送する。方法は前回と全く同じ。
転送して、再起動して、ログインする。
~ # ls -al /bin/hello -rwxr-xr-x 1 root root 4730 Jul 15 2008 /bin/hello ~ # hello hello
ということで、uClibc にリンクした hello も動く。
ユーザプログラムは、この uClibc 環境でコンパイルすることにする。
カーネル、ドライバについては、uClibc なしのノーマルgcc 環境を別途用意し、そこでコンパイルする予定。
c++, java は使わない方向で。(もし使うなら、 glibc を入れて、uClibc, BusyBox は放棄する)