Olimex CS-E9302日記 - ボードに lrzsz をインストールする

hello プログラムを転送するのに、ルートファイルシステムを作って、RedBoot 経由で転送という手順だと10分くらいかかる。 RedBoot経由せずに、ボードのLinuxと開発PCとの間で直接ファイル転送できると作業が効率的である。

そこで、ボードに xmodem 転送コマンドを導入することにする。ソースは、lrzsz パッケージを使う。(というか、これしかない)

まずこちらから↓ lrzsz のソースをダウンロードする。
lrzsz-0.12.20.tar.gz

これを uClibc の環境でコンパイルする。

解凍してコンフィグ

$ tar zxf lrzsz-0.12.20.tar.gz
$ cd lrzsz-0.12.20
$ CC=arm-linux-gcc ./configure --prfix=/bin
creating cache ./config.cache
checking for a BSD comptatible install... /usr/bin/install -c
...

CC=arm-linux-gccとしているが、わたしの環境では、これが glibc ではなく uClibc をリンクするようにしている。(普通の環境だと、arm-linux-uclibc-gcc のこと)

コンパイル

$ make
make all-recursive
make[1]: ...
...
make[2]: ディレクトリ `/home/homerun/arm-dev/lrzsz-0.12.20/src' に入ります
arm-linux-gcc -g -O2  -o lrz  lrz.o timing.o zperr.o zreadline.o crctab.o rbsb.o zm.o
 protname.o tcp.o lsyslog.o canit.o ../lib/libzmodem.a ../intl/libintl.a -lnsl
lrz.o(.text+0x264): In function `wcgetsec':
/usr/local/arm/3.4.1/lib/gcc/arm-linux/3.4.1/../../../../arm-linux/sys-include/bits/stdio.h:68:
 undefined reference to `_IO_putc'
lrz.o(.text+0x49c):/usr/local/arm/3.4.1/lib/gcc/arm-linux/3.4.1/../../../../arm-linux/sys-include/bits/stdio.h:68:
 undefined reference to `_IO_putc'
...
collect2: ld returned 1 exit status
make[2]: *** [lrz] エラー 1
make[2]: ディレクトリ `/home/homerun/arm-dev/lrzsz-0.12.20/src' から出ます
make[1]: *** [all-recursive] エラー 1
make[1]: ディレクトリ `/home/homerun/arm-dev/lrzsz-0.12.20' から出ます
make: *** [all-recursive-am] エラー 2

なんかエラーになった。 _IO_putc がないというエラーが延々と出ている。
uClibc のincludeディレクトリ /usr/local/arm/3.4.1/arm-linux/include を確認したが、_IO_putc は定義されていない。grep で探すと /usr/local/arm/3.4.1/arm-linux/sys-include/stdio.h で使用されている。

どうやら arm-linux-gcc のデフォルトインクルードパスがおかしいらしい。

デフォルトインクルードパスを確認する。

$ arm-linux-cpp -v  ← gcc でなく cpp
...
#include "..." search starts here:
#include <...> search starts here:
 /usr/local/arm/3.4.1/lib/gcc/arm-linux/3.4.1/include
 /usr/local/arm/3.4.1/lib/gcc/arm-linux/3.4.1/../../../../arm-linux/sys-include ← ここの順番が不味い
 /usr/local/arm/3.4.1/lib/gcc/arm-linux/3.4.1/../../../../arm-linux/include ← ここの順番が不味い
End of search list.
^C

.../arm-linux/sys-include が先になっている。ほんとうは、uClibc をインストールした .../arm-linux/include を先に見て欲しいのである。もう少し確認してみよう。

$ arm-linux-gcc -H hello.c
. /usr/local/arm/3.4.1/lib/gcc/arm-linux/3.4.1/../../../../arm-linux/sys-include/stdio.h ← NG
...

完全にsys-include/stdio.h を見に行っている。

回避方法は、-isystem オプションを使って以下のようにすればよい。

$ arm-linux-gcc -H -isystem /usr/local/arm/3.4.1/arm-linux/include hello.c
. /usr/local/arm/3.4.1/arm-linux/include/stdio.h ← OK
...

なお -I オプションではうまくいかない。.../arm-linux/include が元々デフォルトのインクルードパスに含まれているので -I オプションでは順番が変わらないからだ。 (因みに-nostdinc を使うとデフォルトインクルードをなしにもできる)
参考 Cプリプロセッサのman

lrzsz のコンフィグではこうする

$ CC=arm-linux-gcc CFLAGS="-isystem /usr/local/arm/3.4.1/arm-linux/include" ./configure --prfix=/bin
...

この後 make すると正常に終了することを確認した。

しかし、コンパイルの度に -isystem を指定するのは面倒なので、今後のことも考えて、arm-linux-gcc の specs を変更しておく。

 
$ su
# vi /usr/local/arm/3.4.1/lib/gcc/arm-linux/3.4.1/specs
...
*cpp:
%(cpp_cpu_arch) %(subtarget_cpp_spec) 			← これらの行は1行です
%{mapcs-32:%{mapcs-26:							← これらの行は1行です
%e-mapcs-26 and -mapcs-32 may not be used together}}		← これらの行は1行です
%{msoft-float:%{mhard-float:							← これらの行は1行です
%e-msoft-float and -mhard_float may not be used together}}	← これらの行は1行です
%{mbig-endian:%{mlittle-endian:							← これらの行は1行です
%e-mbig-endian and -mlittle-endian may not be used together}} ← これらの行は1行です
-isystem /usr/local/arm/3.4.1/arm-linux/include ← これらの行は1行です
...

表示のために改行しているが、実際は1行です。-isystem xxx オプションを cpp に追加した。

インクルードパスが変わっていることの確認。

$ arm-linux-cpp -v
...
#include "..." search starts here:
#include <...> search starts here:
 /usr/local/arm/3.4.1/arm-linux/include ← 先頭に追加されている。OK
 /usr/local/arm/3.4.1/lib/gcc/arm-linux/3.4.1/include
 /usr/local/arm/3.4.1/lib/gcc/arm-linux/3.4.1/../../../../arm-linux/sys-include
 /usr/local/arm/3.4.1/lib/gcc/arm-linux/3.4.1/../../../../arm-linux/include
End of search list.

うまくいっている。

あらためて、lrzsz のコンフィグ&コンパイル

$ CC=arm-linux-gcc ./configure --prfix=/bin
...
$ make
...
make[1]: ディレクトリ `/home/homerun/arm-dev/lrzsz-0.12.20`から出ます

うまくコンパイルできた。

ボードへのインストール

コンパイルしてできた lsz, lrz コマンドをボードのルートファイルシステムにコピーする。ルートファイルシステムの作り方は前回と同じ。再掲する。

$ cp /mnt/cdrom/linux-2.6\ images/ramdisk.gz .   ← 付属CDのルートファイルシステムを流用
$ gunzip ramdisk.gz
$ mkdir initrd
$ su
# mount -o loop ramdisk initrd  ← ループバックでマウント
# rm initrd/Noise.wav  ← 不要ファイル消す
# rm initrd/funcky.mp3
# cp lrzsz-0.12.20/src/lsz initrd/bin/.  ← lsz のコピー
# cp lrzsz-0.12.20/src/lrz initrd/bin/.  ← lrz のコピー
# cd initrd/bin/.
# ln lsz lsx  ← ハードリンク作成
# ln lrz lrx
# ln lsz lsy
# ln lrz lry
# ln -s lsz sz ← ソフトリンク作成
# ln -s lrz rz
# ln -s lsx sx
# ln -s lrx rx
# ln -s lsy sy
# ln -s lry ry
# cd ../..
# umount initrd
# gzip ramdisk

ramdisk.gz をRedBoot経由でボードに転送して、FLASHに書き込む。やり方は前回と同じ。

ここでは、lrzsz を使ったが、gkermit という転送コマンドも便利である。(ただしKermitとしか通信できない)