【お知らせ】プログラミング記事の投稿はQiitaに移行しました。

クロス開発環境構築

FreeBSD上でNetWalker(Ubuntu 9.04 ARM)のアプリをクロス開発するため、クロス開発環境を構築しました。手順は以下の通りです。

  1. binutils-2.20
  2. ヘッダ・ライブラリ (id:n7shi:20091210より)
  3. gcc-4.4.2

FreeBSDに依存していないため、他のUNIX系OSでも同じ手順が使えるはずです。id:n7shi:20091115の手順と比較すると、glibcは既存のパッケージから流用しているため簡単です。

準備

以下のportsをインストールします。pkg_add -rでリモートインストールすると簡単です。

  • gmake
  • bison
  • texinfo
  • libgmp
  • mpfr
  • xz

ヘッダやライブラリが見えるように環境変数を設定します。

setenv CPPFLAGS -I/usr/local/include
setenv LDFLAGS -L/usr/local/lib

arm-linux-gnueabi

Ubuntu 9.04はarmelというARMの新しいABIを採用しています。armelはarm-gnueabiと指定するため、OSまで含めるとarm-linux-gnueabiとなります。

1. binutils-2.20

アセンブラやリンカなどコンパイラの下請けをするツール群です。

ソースをダウンロードして展開します。

fetch ftp://ftp.gnu.org/gnu/binutils/binutils-2.20.tar.bz2
tar xvjf binutils-2.20.tar.bz2

以下のパッチを当てます。中括弧を追加するだけの簡単な修正なので、手動で編集できます。

--- gas/config/tc-arm.c.orig
+++ gas/config/tc-arm.c
@@ -2486,7 +2486,7 @@
       frag->tc_frag_data.first_map = symbolP;
     }
   if (frag->tc_frag_data.last_map != NULL)
-    know (S_GET_VALUE (frag->tc_frag_data.last_map) < S_GET_VALUE (symbolP));
+    {know (S_GET_VALUE (frag->tc_frag_data.last_map) < S_GET_VALUE (symbolP));}
   frag->tc_frag_data.last_map = symbolP;
 }
 

binutilsgccはサブディレクトリで作業するのが流儀のようです。強制ではないようですが、ソースが膨大なため、色々な環境向けにビルドする際に使い回すのが目的のようです。

cd binutils-2.20
mkdir build
cd build
../configure --target=arm-linux-gnueabi
gmake
gmake install

2. ヘッダ・ライブラリ

id:n7shi:20091210のアーカイブをダウンロードします。

クロス開発環境から認識されるパスに展開します。

xz -dc ubuntu-jaunty-araneo-armel-dev.tar.xz | tar xvf - -C /usr/local/arm-linux-gnueabi

3. gcc-4.4.2

ソースをダウンロードして展開します。

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
fetch ftp://ftp.gnu.org/gnu/gcc/gcc-4.4.2/gcc-objc-4.4.2.tar.bz2
tar xvjf gcc-core-4.4.2.tar.bz2
tar xvjf gcc-g++-4.4.2.tar.bz2
tar xvjf gcc-objc-4.4.2.tar.bz2

binutilsと同じようにサブディレクトリで作業します。

cd gcc-4.4.2
mkdir build
cd build
../configure --target=arm-linux-gnueabi
gmake
gmake install

テスト

a.c

#include <stdio.h>

int main() {
    printf("Hello, World!\n");
    return 0;
}

上のソースをコンパイルします。

% arm-linux-gnueabi-gcc a.c
% file a.out
a.out: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (use
s shared libs), for GNU/Linux 2.6.16, not stripped

このa.outはARMバイナリのためx86上では実行できません。

% ./a.out
./a.out: Exec format error. Binary file not executable.

QEMUユーザーモードエミュレーションを使用すればx86上でもARMバイナリを実行できますが、OSが同じである必要があります。FreeBSDLinux互換環境での動作を試みましたが、うまくいきませんでした。

QEMUのARMシステムエミュレータでOSごと動かす方法もありますが、未確認です。