FreeBSDでOpenBlockS


あなたは 人目のお客様です.

ぷらっとほーむ OpenBlockS を購入しました.OpenBlockS は Linux が乗っていて, アプリケーションプログラムをコンパイルして乗せて動かすことができます.

例えば,cgi での日本語処理用に nkf などをコンパイルしてインストールして 使用することが可能,ということです.

ふつうは Macintosh 用の LinuxPPC 上でアプリケーションをコンパイルして, ftpでOpenBlockSに持って行って使うようです. また,OpenBlockS 上でコンパイルを行うためのセルフコンパイル環境 (現実的には HDD が必要)が試用版として, ぷらっとほーむオープンラボラトリー で配布されています.つまり,基本的には開発はセルフ開発で行います.

しかし,ぼくは Macintosh を持ってないので,なんとか PC/AT 互換機上で, それもなるべくなら普段使っている FreeBSD でクロス開発できないか, と思っていました.(そもそも,あまりいろんなマシンを使うのは好きではない) で,いろいろやってようやく成功したので,ここに環境構築の方法をまとめて おきます.今回ぼくがやったのは FreeBSD/i386 → Linux/ppc のクロス環境構築 ですが,同様にして,Linux/i386 → Linux/ppc もできるでしょう. (むしろこっちのほうがうれしい人が多いかもね)

ただ,うろおぼえなので,抜けや間違いが一部あるかもしれません.もしも うまくいかなかったらメールで教えてください.できる限り思い出すようにします. また,当然ですが,ここに書いてある内容は全て無保証です.

1.クロス開発用の binutils のインストール

まずはクロス開発用に binutils (ar, as, ld などです)をインストールします. これは,簡単です. GNUのftpサイトあたりから最新版の binutils を入手して,
# ./configure --target=ppc-linux-gnu
# make
# make install
するだけです.
/usr/local/ppc-linux-gnu/bin 以下に,クロス用の as や ar がインストールされます.

注意として,binutils の古いバージョンでは,ppc-linux-gnu に対応していないかも しれません. ちなみにぼくが使用しているのは,binutils-2.10.1 です.

2.クロス開発用の gcc のインストール

gcc のインストールは,ちょっと面倒です.まずはヘッダファイルが必要なので, ぷらっとほーむのopenlabから,usrinc.tgz と usrsrc.tgzを ダウンロードします.で,
# mkdir /usr/local/ppc-linux-gnu/include (すでにディレクトリがあるかもしれない.忘れた)
# cd /usr/local/ppc-linux-gnu/include
# tar xvzf ~/usrinc.tgz
します.

さらに,このままでは,

asm -> /sys/es0/usr/src/linux/include/asm
linux -> /sys/es0/usr/src/linux/include/linux
のようなリンクが張られているので,
# rm asm linux
# tar xvzf ~/usrsrc.tgz
のようにして,asm と linux のリンクを消してから usrsrc.tgz を解凍します. (注: リンクが張られたままだと,usrsrc.tgz を解凍するときに,ディレクトリ linux 以下を解凍することができなくなります)

準備ができたら, GNUのftpサイトあたりから最新版の gcc を入手して,

# ./configure --target=ppc-linux-gnu --enable-languages=c
# make
# make install
のようにします.

注意として,

3.ライブラリのインストール

ディレクトリ /usr/local/ppc-linux-gnu/lib を作成(すでにあったかもしれない)し, とりあえず,OpenBlockS の /lib と /usr/lib 以下にあるライブラリを, ぜんぶ ftp で /usr/local/ppc-linux-gnu/lib に持ってくる.

また,スタートアップルーチンが必要なので, ぷらっとほーむのopenlabから,crt.tgzをダウンロードして展開し, /usr/local/ppc-linux-gnu/lib にコピーする.

さらに, ぷらっとほーむのopenlabから,セルフ開発用の es1h_plat_1.03h_20010116-1.tar.gz という巨大なファイルをダウンロードして,解凍して,lib 以下にある ライブラリをぜんぶ /usr/local/ppc-linux-gnu/lib にコピーする.

4.make の準備

以下のようなシェルスクリプトを obsmake.sh とかいう名前で準備する.
#!/bin/sh -x

# ディレクトリの指定
LOCAL=/usr/local
TARGET=ppc-linux-gnu
TARGETDIR=$LOCAL/$TARGET

PATH=$TARGETDIR/bin:$PATH:$BINDIR export PATH

# gcc がコンパイル時に as や ld を探すディレクトリを指定
# (gcc の -B オプションと等価)
GCC_EXEC_PREFIX=$TARGETDIR/bin export GCC_EXEC_PREFIX

AR=$TARGETDIR/bin/ar export AR
AS=$TARGETDIR/bin/as export AS
CC="$TARGETDIR/bin/gcc -DLINUX -D_LINUX_ -D__LINUX__" export CC
#CC="$TARGETDIR/bin/gcc -B$TARGETDIR/bin" export CC
#CC="$TARGETDIR/bin/gcc -B$TARGETDIR/bin -D__NetBSD__" export CC
CPP=`$TARGETDIR/bin/gcc -print-prog-name=cpp` export CPP
CXX=$CC export CXX
FC=$TARGETDIR/bin/f77 export FC
LD=$TARGETDIR/bin/ld export LD
NM=$TARGETDIR/bin/nm export NM
RANLIB=$TARGETDIR/bin/ranlib export RANLIB
SIZE=$TARGETDIR/bin/size export SIZE
ADDR2LINE=$TARGETDIR/bin/addr2line export ADDR2LINE
GASP=$TARGETDIR/bin/gasp export GASP
OBJCOPY=$TARGETDIR/bin/objcopy export OBJCOPY
OBJDUMP=$TARGETDIR/bin/objdump export OBJDUMP
STRINGS=$TARGETDIR/bin/strings export STRINGS
STRIP=$TARGETDIR/bin/strip export STRIP

HOSTED_CC=/usr/bin/cc export HOSTED_CC
NOGCCERROR=yes export NOGCCERROR
OBJECT_FMT=ELF export OBJECT_FMT

#COPTS="-O2 -DLINUX -D_LINUX_ -D__LINUX__" export COPTS
#COPTS="-O2 -D__NetBSD__ -D__STDC__=1" export COPTS
#CFLAGS="-D__NetBSD__" export CFLAGS

#CPPFLAGS="-I$TARGETDIR/include -I$TARGETDIR/include/sys -I$TARGETDIR/include/machine" export CPPFLAGS

#MAKE=make
MAKE="/usr/bin/make -f Makefile"; export MAKE
#MAKE="/usr/local/bin/gmake -f Makefile"; export MAKE

set -x
exec $MAKE "$@"

5.アプリケーションのコンパイル

ここまででコンパイルの準備は完了なのだが,実際にアプリケーションを コンパイルするときには,そのまま make すればいい,というわけにはいかない. 基本的には obsmake.sh を make のかわりに使って make すればいいのだが, 実際のコンパイルでは,Makefile をあるていど修正したり,不要な部分は コンパイルしなかったり,手動でコンパイルしたりというケースバイケースの 対応が必要になってくる.

たとえば,Makefile で,

CC=gcc

.c.o :
		$(CC) $(CFLAGS) $(INCLUDEDIR) -c $< -o $@
のようにしているアプリケーションのばあいには,
#CC=gcc
のようにコメントアウトして,make のかわりに obsmake.sh を使って make すれば よい.obsmake.sh が環境変数 CC を /usr/local/ppc-linux-gnu/bin/gcc に 設定してくれるので,クロスコンパイラが自動的に使われる.

しかし,Makefile の中で,

.c.o :
		gcc $(CFLAGS) $(INCLUDEDIR) -c $< -o $@
のようにして,gcc を直接指定しているようなとんでもないアプリケーションの 場合だと,ちょっと違ってくる. まあ,obsmake.sh が /usr/local/ppc-linux-gnu/bin に優先的に PATH を通している ので,クロスコンパイラが使われる可能性は高いのだが,make 時のメッセージを よく参照して,クロスコンパイラがちゃんと使われていることのチェックなどが 必要になってくる.

また,Makefile で,

INCDIR=-I/usr/include
とか,
LIBDIR=-L/usr/lib
のようなことをやっているばあいには,これらも
INCDIR=-I/usr/local/ppc-linux-gnu/include
とか,
LIBDIR=-L/usr/local/ppc-linux-gnu/lib
のように修正する必要があります.

6. ./configure が必要な場合

./configure
するようなアプリケーションの場合には,ふつうに ./configure してから, 作成された Makefile 中の,
CC=cc
とか,
LD=ld
とか,
AS=as
とかを手で修正して obsmake.sh で make するとうまくいくようです. 基本的には /usr/local/ppc-linux-gnu/bin 以下のコマンドは全部修正する必要が あります.

7.ライブラリが必要なアプリケーションの場合

なにかライブラリが必要な場合には,まずライブラリを obsmake.sh で make して, ヘッダファイルを /usr/local/ppc-linux-gnu/include に, 作成されたライブラリを /usr/local/ppc-linux-gnu/lib にコピーしてから, 目的のアプリケーションを obsmake.sh で make することになります.

ただ,ぼくは面倒なので,アプリケーションのコンパイル時に,「xxx.h が無い」 とか,「xxx.a が無い」などと言われたら,まずは FreeBSD の ports の Makefile を見て必要なライブラリを調べてライブラリを 作成して,アプリケーションのソースディレクトリに必要なインクルードファイルと ライブラリを直接コピーしてコンパイルし直す,というようにやってます.

8.OpenBlockSでの動作

実際に OpenBlockS で動作させる場合には,OpenBlockS に ftp でバイナリを 持っていって実行することになります.また,ライブラリが無いと言われた 場合には,必要なライブラリ(openlabのセルフ開発環境に含まれていたりする) を OpenBlockS に持っていって適当なところに置いて,
ln -s /mnt/ide0/lib/libm.so.6 /lib/libm.so.6
とかを /etc/rc.d/rc.sysinst の最後に追加しておく,というようにぼくはしてます.

最後に

最終的にはアプリケーションごとに Makefile を修正するなどしなければならないの ですが,ひとつ,解決策があります.それは FreeBSD の ports コレクションか NetBSD の pkgsrc のシステムを使用することです.

これらのパッケージシステムでは,アプリケーションの Makefile で CC=cc のように 設定することはせずに,/usr/share/mk 以下にある Makefile の雛型を参照する ようになっています.Makefile の雛型では,環境変数で CC が設定されている 場合にはそれを使用して,設定されていない場合には,CC=cc のようにデフォルトを 設定するようになっています.アプリケーションの Makefile のほうは, CC=cc は CC=?cc にするようなパッチが当てられます. (パッケージの作成時には,このように適切なパッチを作成しなければいけないことに なっているので,ports の配布物の多くは,ちゃんとパッチングされるはずである)

つまり,FreeBSD の ports や NetBSD の pkgsrc システムを使うならば, 基本的には obsmake.sh に多少の環境変数を追加するだけで,すべて obsmake.sh で make できるはずです.

ためしにやってみたところ,FreeBSD の ports ではうまくいきませんでした. しかし,NetBSD は移植を重要に考えられているので,NetBSD の pkgsrc なら, うまくいくかもしれません.(うまくいったらまた書きます)

参考までに,ぼくが StrongArm/NetBSD 用のアプリケーションを作成するときに 使用している make スクリプトを添付しておきます.NetBSD の /usr/share/mk 以下を /usr/local/ppc-linux-gnu/share あたりにコピーして,NetBSD の pkgsrc を使用することにより,うまく make できるかもしれません.

#!/bin/sh -x

# アーキテクチャの指定(必須)
MACHINE=hpcarm export MACHINE
MACHINE_ARCH=arm export MACHINE_ARCH
OBJECT_FMT=ELF export OBJECT_FMT

# ディレクトリの指定
LOCAL=/usr/local
TARGET=arm-elf
TARGETDIR=$LOCAL/$TARGET
MKFDIR=$TARGETDIR/share/mk

# アプリケーションのビルド時の、ターゲット環境の構築先
DESTDIR=/usr/tmp/dist export DESTDIR

# ターゲットのインクルードファイルのインストール先
# ($DESTDIR/$INCSDIR にインストールされる)
# デフォルトは /usr/include
#INCSDIR=$TARGETDIR/include export INCSDIR
#INCSDIR=$DESTDIR/include export INCSDIR
#INCSDIR=/usr/include export INCSDIR

# ターゲットのライブラリのインストール先
# ($DESTDIR/$LIBDIR にインストールされる)
# デフォルトは /usr/lib
#LIBDIR=/usr/lib export LIBDIR

# インストール時のユーザとグループ
LIBOWN=`whoami` export LIBOWN
LIBGRP=user export LIBGRP
DOCOWN=`whoami` export DOCOWN
DOCGRP=user export DOCGRP
MANOWN=`whoami` export MANOWN
MANGRP=user export MANGRP
BINOWN=`whoami` export BINOWN
BINGRP=user export BINGRP
NLSOWN=`whoami` export NLSOWN
NLSGRP=user export NLSGRP
KMODOWN=`whoami` export KMODOWN
KMODGRP=user export KMODGRP

BINDIR=$LOCAL/bin
PATH=$TARGETDIR/bin:$PATH:$BINDIR export PATH

# gcc がコンパイル時に as や ld を探すディレクトリを指定
# (gcc の -B オプションと等価)
GCC_EXEC_PREFIX=$TARGETDIR/bin export GCC_EXEC_PREFIX

AR=$TARGETDIR/bin/ar export AR
AS=$TARGETDIR/bin/as export AS
CC=$TARGETDIR/bin/gcc export CC
#CC="$TARGETDIR/bin/gcc -B$TARGETDIR/bin" export CC
#CC="$TARGETDIR/bin/gcc -B$TARGETDIR/bin -D__NetBSD__" export CC
CPP=`$CC -print-prog-name=cpp` export CPP
CXX=$CC export CXX
FC=$TARGETDIR/bin/f77 export FC
LD=$TARGETDIR/bin/ld export LD
NM=$TARGETDIR/bin/nm export NM
RANLIB=$TARGETDIR/bin/ranlib export RANLIB
SIZE=$TARGETDIR/bin/size export SIZE
ADDR2LINE=$TARGETDIR/bin/addr2line export ADDR2LINE
GASP=$TARGETDIR/bin/gasp export GASP
OBJCOPY=$TARGETDIR/bin/objcopy export OBJCOPY
OBJDUMP=$TARGETDIR/bin/objdump export OBJDUMP
STRINGS=$TARGETDIR/bin/strings export STRINGS
STRIP=$TARGETDIR/bin/strip export STRIP

MKPROFILE=no export MKPROFILE
#MKMAN=no export MKMAN
MKLINT=no export MKLINT

HOSTED_CC=/usr/bin/cc export HOSTED_CC
NOGCCERROR=yes export NOGCCERROR
OBJECT_FMT=ELF export OBJECT_FMT

# mkdep コマンド
#MKDEP="$BINDIR/netbsd_mkdep -I$TARGETDIR/include -I$TARGETDIR/include/sys -I$TARGETDIR/include/machine" export MKDEP
MKDEP="$BINDIR/netbsd_mkdep" export MKDEP

# install コマンド
INSTALL="$BINDIR/netbsd_install" export INSTALL

COPTS="-O2 -D__NetBSD__" export COPTS
#COPTS="-O2 -D__NetBSD__ -D__STDC__=1" export COPTS
#CFLAGS="-D__NetBSD__" export CFLAGS

#CPPFLAGS="-I$TARGETDIR/include -I$TARGETDIR/include/sys -I$TARGETDIR/include/machine" export CPPFLAGS

#MAKE=make
MAKE="$BINDIR/netbsd_make -m $MKFDIR -I $MKFDIR/sys.mk -f Makefile"; export MAKE

set -x
exec $MAKE "$@"

メールは kozos(アットマーク)kozos.jp まで