FreeBSD上のLinux互換環境で動かすバイナリをビルドするため、クロス開発環境を構築しました。手順は以下の通りです。gccとglibcが相互依存しているため行ったり来たりします。途中でエラーを無視して進めますが、最終的にはすべて解消します。
- binutils-2.20
- gcc-4.4.2 (1回目): ランタイムなし (glibc用)
- カーネルヘッダ
- glibc-2.11 (1回目): ヘッダ, スタティック(libc.aなど), crt
- gcc (2回目): libgcc.a
- glibc (2回目): ダイナミック (libc.soなど)
- gcc (3回目): ランタイム (libstdc++等)
準備
以下のportsをインストールします。pkg_add -rでリモートインストールすると簡単です。
- gmake
- bison
- texinfo
- libgmp
- mpfr
- rpm2cpio
ヘッダやライブラリが見えるように環境変数を設定します。
setenv CPPFLAGS -I/usr/local/include setenv LDFLAGS -L/usr/local/lib
環境指定
クロス環境の構築ではビルド環境と実行環境が異なります。configureで環境を指定します。指定する環境は以下の三種類があります。
1. binutils-2.20
アセンブラやリンカなどコンパイラの下請けをするツール群です。
ソースをダウンロードして展開します。
fetch ftp://ftp.gnu.org/gnu/binutils/binutils-2.20.tar.bz2 tar xvjf binutils-2.20.tar.bz2
binutilsやgccはサブディレクトリで作業するのが流儀のようです。強制ではないようですが、ソースが膨大なため、色々な環境向けにビルドする際に使い回すのが目的のようです。
cd binutils-2.20 mkdir build cd build ../configure --target=i686-linux gmake gmake install
2. gcc-4.4.2 (1回目): ランタイムなし (glibc用)
最初はglibcのビルドに必要なコンパイラ本体だけをビルドします。ランタイムはglibcに依存するため後回しとなります。
ソースをダウンロードして展開します。
fetch ftp://ftp.gnu.org/gnu/gcc/gcc-4.4.2/gcc-core-4.4.2.tar.bz2 fetch ftp://ftp.gnu.org/gnu/gcc/gcc-4.4.2/gcc-g++-4.4.2.tar.bz2 tar xvjf gcc-core-4.4.2.tar.bz2 tar xvjf gcc-g++-4.4.2.tar.bz2
cd gcc-4.4.2 mkdir build cd build ../configure --target=i686-linux gmake all-gcc gmake install-gcc
3. カーネルヘッダ
FreeBSDのLinux互換環境はFedora Core 4相当らしいので、Fedora Core 4からカーネルヘッダを取って来ます。
fetch http://ftp.riken.jp/Linux/fedora/core/4/i386/os/Fedora/RPMS/glibc-kernheaders-2.4-9.1.94.i386.rpm
ファイルが想定外の場所に展開されないように、念のためディレクトリを作って展開します。
mkdir kernheaders cd kernheaders/ rpm2cpio.pl ../glibc-kernheaders-2.4-9.1.94.i386.rpm | cpio -ivd mkdir -p /usr/local/i686-linux/include cp -r usr/include/* /usr/local/i686-linux/include
4. glibc-2.11 (1回目): ヘッダ, スタティック(libc.aなど), crt
ソースをダウンロードして展開します。
fetch ftp://ftp.gnu.org/gnu/glibc/glibc-2.11.tar.bz2 tar xvjf glibc-2.11.tar.bz2
古いカーネルヘッダではエラーが出るため、gentooのパッチを当てます。
fetch -o glibc-gentoo.diff "http://bugs.gentoo.org/attachment.cgi?id=209781" cd glibc-2.11 patch -p1 < ../glibc-gentoo.diff
サブディレクトリを作って作業します。glibcでは強制です。configureでエラーにならないように色々と細工します。libc.soはlibgcc(まだ存在しない)依存でエラーになるため-kで無視します。
mkdir build cd build env CFLAGS="-O2 -march=i686" libc_cv_forced_unwind=yes libc_cv_c_cleanup=yes \ ../configure --prefix=/usr/local/i686-linux --host=i686-linux --disable-sanity-checks gmake -k gmake -k install
エラー回避のため、空のスタブヘッダを追加します。
touch /usr/local/i686-linux/include/gnu/stubs-32.h
手順6で正規のstubs-32.hがインストールされるまでの一時的な措置です。
5. gcc (2回目): libgcc.a
環境を構築し直さずに続きからビルドします。libgcc.soを作ろうとしてエラーになるため-kで無視します。
cd gcc-4.4.2/build gmake -k all-target-libgcc gmake -k install-target-libgcc
libgcc.soはglibcの完成後に作ります。もしlibgcc.aでエラーになる場合は前の手順のスタブヘッダを確認してください。
6. glibc (2回目): ダイナミック (libc.soなど)
環境を構築し直さずに続きからビルドします。
cd glibc-2.11/build gmake gmake install
エラーなく最後まで行くはずです。これでglibcは完成です。
7. gcc (3回目): ランタイム (libstdc++等)
環境を構築し直さずに続きからビルドします。
cd gcc-4.4.2/build gmake gmake install
エラーなく最後まで行くはずです。これでgcc/g++は完成です。
テスト
a.c
#include <stdio.h> int main() { printf("Hello, World!\n"); return 0; }
実行結果
% i686-linux-gcc a.c % ./a.out Hello, World! % file a.out a.out: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2 .0.0, dynamically linked (uses shared libs), not stripped
Linuxバイナリを生成して、互換環境で実行しています。