体験!マイコンボードで組込みLinux

第15回マイコンボードで動くgcc環境の移植

クロスコンパイラの新規生成

なぜ新規に生成するのか

すでにSH3用のクロスコンパイラが公開されており、基本的にはこれを使えば問題はありません。しかし、今回はSH7706ボード上で動作する組込み向けセルフコンパイラを生成するので、クロスコンパイラとセルフコンパイラのバージョンを一致させなければなりません。

そのために準備としてセルフコンパイラと同じバージョンのgccのクロスコンパイラを生成します。バージョンは任意でいいですが、あまり古過ぎるのも、あまり新しいもので枯れていないものも問題なので、それなりに枯れていてかつ新しいものを選択します。今回は、gcc-4.1.2を対象にします。

crosstoolの取得

クロスコンパイラは通常の方法ではコンパイルがうまくいかないので、クロスコンパイラ構築でのエラーを回避するテクニックが必要となります。クロスコンパイラ構築のエラー回避テクニックを含めたツールはいくつかの有志によって公開されていますが、今回はその中のcrosstoolでクロスコンパイラを構築してみます。

crosstool
URL:http://kegel.com/crosstool/

crosstoolのダウンロードは上記のページからたどれる以下のURLとなります。

crosstoolの構築

crosstoolの構築は一般ユーザでなければいけません。まず、一般ユーザで以下のように展開します。

$ tar xvzf crosstool-0.43.tar.gz
$ cd crosstool-0.43

いくつかの設定ファイルを変更してから構築をします。SH3用クロスコンパイラの設定はsh3.datで、リスト1のように変更します。

リスト1 sh3.dat
01  KERNELCONFIG=`pwd`/sh3.config
02  TARGET=sh3-linux
03  TARGET_CFLAGS="-O -ml -m3"
04  GLIBC_CONFIGPARMS="no-z-defs=yes"

クロスコンパイラの構築のスクリプトはdemo-sh3.shで、リスト2のように変更します。

リスト2 demo-sh3.sh
01  #!/bin/sh
02  # This script has one line for each known working toolchain
03  # for this architecture.  Uncomment the one you want.
04  # Generated by generate-demo.pl from buildlogs/all.dats.txt
05  
06  set -ex
07  TARBALLS_DIR=$HOME/downloads
08  RESULT_TOP=$HOME/crosstool
09  export TARBALLS_DIR RESULT_TOP
10  GCC_LANGUAGES="c,c++"
11  export GCC_LANGUAGES
12  
13  # Really, you should do the mkdir before running this,
14  # and chown /opt/crosstool to yourself so you don't need to run as root.
15  mkdir -p $RESULT_TOP
16  
17  #eval `cat sh3.dat gcc-3.4.5-glibc-2.3.2.dat` sh all.sh --notest
18  #eval `cat sh3.dat gcc-3.4.5-glibc-2.3.2-tls.dat` sh all.sh --notest
19  #eval `cat sh3.dat gcc-3.4.5-glibc-2.3.5.dat` sh all.sh --notest
20  #eval `cat sh3.dat gcc-3.4.5-glibc-2.3.6.dat` sh all.sh --notestko
21  #eval `cat sh3.dat gcc-4.0.2-glibc-2.3.2.dat` sh all.sh --notest
22  #eval `cat sh3.dat gcc-4.0.2-glibc-2.3.2-tls.dat` sh all.sh --notest
23  #eval `cat sh3.dat gcc-4.0.2-glibc-2.3.5.dat` sh all.sh --notest
24  #eval `cat sh3.dat gcc-4.0.2-glibc-2.3.6.dat` sh all.sh --notest
25  #eval `cat sh3.dat gcc-4.1.0-glibc-2.3.2.dat` sh all.sh --notest
26  #eval `cat sh3.dat gcc-4.1.0-glibc-2.3.2-tls.dat` sh all.sh --notest
27  #eval `cat sh3.dat gcc-4.1.0-glibc-2.3.5.dat` sh all.sh --notest
28  eval `cat sh3.dat gcc-4.1.2-glibc-2.3.6.dat` sh all.sh --notest
29  
30  echo Done.

リスト2の7行目ではツール類のソースパッケージをダウンロードするフォルダを指定します。場所は任意でかまいません。

リスト2の8行目では生成されたクロスコンパイラをインストールする先のフォルダを指定します。こちらも場所は任意です。

リスト2の28行目でコンパイラとCライブラリの組み合わせ定義ファイルを記述します。定義ファイルが既存のもので用意されている場合はそれを使えばいいですが、そうでない場合はコンパイラとCライブラリの組み合わせ定義ファイルを新規作成する必要があります。

今回はgcc-4.1.2とglibc-2.3.6の組み合わせなので、gcc-4.1.2-glibc-2.3.6.datファイルを新規作成します。これに近いものとしては、gcc-4.1.1-glibc-2.3.6.datという既存のファイルがあるので、それをリスト3のように変更します。変更箇所はリスト3の3行目となります。

リスト3 gcc-4.1.1-glibc-2.3.6.datを変更
01  BINUTILS_DIR=binutils-2.16.1
02  GCC_CORE_DIR=gcc-3.3.6
03  GCC_DIR=gcc-4.1.2
04  GLIBC_DIR=glibc-2.3.6
05  LINUX_DIR=linux-2.6.15.4
06  LINUX_SANITIZED_HEADER_DIR=linux-libc-headers-2.6.12.0
07  GLIBCTHREADS_FILENAME=glibc-linuxthreads-2.3.6
08  GDB_DIR=gdb-6.5

これらの変更が済んだら、以下のように構築を実行します。

$ ./demo-sh3.sh

このスクリプトは必要なファイルをダウンロードしてから構築しようとしますが、現在ではうまくソースパッケージを検索できなくなっていますので、そのような場合は、gcc-4.1.1-glibc-2.3.6.datの中を見れば必要なソースパッケージがわかるので、自分でネットでソースパッケージを検索してから前述のダウンロードのフォルダに格納します。

参考のために必要なファイルは以下のとおりです。

  • binutils-2.16.1.tar.bz2
  • gcc-3.3.6.tar.bz2
  • gcc-4.1.2.tar.bz2
  • glibc-2.3.6.tar.bz2
  • linux-2.6.15.4.tar.gz
  • linux-libc-headers-2.6.12.0.tar.bz2
  • glibc-linuxthreads-2.3.6.tar.bz2
  • gdb-6.5.tar.bz2

クロスコンパイラのインストール

クロスコンパイラはシステム領域にあるので、作業はスーパーユーザで行わなければなりません。

まず、以下のように既存のクロスコンパイラをアンインストールします。

# cd /usr
# rm -rf sh3-linux

次に新規のクロスコンパイラを以下のようにインストールします。

# cd /usr
# cp -a [インストール先フォルダ]/gcc-4.1.2-glibc-2.3.6/sh3-linux .

binutilsの構築

gccにはbinutilsが必要なので、先にbinutilsを構築する必要があります。

binutilsのコンパイル

クロスコンパイラと同じく,binutils-2.16.1.tar.bz2を以下のように展開します。

$ tar xvjf binutils-2.16.1.tar.bz2
$ cd binutils-2.16.1

以下のように構築をするフォルダを作成します。

$ mkdir build
$ cd build

configureでは、ターゲットとなる組込みボードのアーキテクチャと構築を行うPCのアーキテクチャの両方を指定する必要があります。PCのアーキテクチャはディストリビューションによって異なりますが、たとえばVine Linux 6.0では「i686-vine-gnu」というアーキテクチャになります。

その場合は以下のようにconfigureのオプションを指定し、コンパイルを実行します。

$ ../configure  --prefix=/usr --host=sh3-linux --build=i686-vine-gnu
$ make

binutilsのインストール

configureで指定したインストール先の/usrは組込みボードのフォルダなので、PC上では任意のフォルダを作成して、これをインストール先にします。

ここでは~/shlinuxとしますので、以下のようにインストールします。

$ mkdir ~/shlinux
$ make install prefix=~/shlinux

gccの構築

gccのコンパイル

クロスコンパイラと同じgcc-4.1.2.tar.bz2を以下のように展開します。

$ tar xvjf gcc-4.1.2.tar.bz2
$ cd gcc-4.1.2

以下のように構築をするフォルダを作成します。

$ mkdir build
$ cd build

binutilsと同じく、configureではターゲットとなる組込みボードのアーキテクチャと構築を行うPCのアーキテクチャの両方を指定する必要があります。また、構築する言語も指定しなければなりませんが、C言語とC++言語を指定します。

以下のようにconfigureのオプションを指定し、コンパイルを実行します。

$ ../configure  --prefix=/usr --host=sh3-linux --build=i686-vine-gnu --enable-languages=c,c++
$ make

コンパイルは成功したかのようにエラーも出ませんが、実はCコンパイラの構築には失敗しています。一番はCコンパイラの構築を成功させるようにgccを内部解析して改造することが望ましいですが、Cコンパイラの構築が失敗したとしても何とかなりますので、ここではこのまま強行突破します。

gccの不完全インストール

configureで指定したインストール先の/usrは組み込みボードのフォルダなので、PC上では先に構築したbinutilsのフォルダをインストール先にします。

$ make install prefix=~/shlinux

前述のとおりCコンパイラの構築が失敗しているので、インストールの途中で以下のようにエラーとなります。

/usr/bin/install: 宛先の `/home/general/shlinux/libexec/gcc/sh3-linux/4.1.2/install-tools/mkinstalldirs' はディレクトリではありません
/usr/bin/install: `build/fix-header' を stat できません: そのようなファイルやディレクトリはありません
make[2]: *** [install-mkheaders] Error 1
make[2]: Leaving directory `/home/general/gcc-4.1.2/build/gcc'
make[1]: *** [install-gcc] Error 2
make[1]: Leaving directory `/home/general/gcc-4.1.2/build'
make: *** [install] Error 2

何やらインストールでのトラブルのような感じがしますが、Cコンパイラそのものの構築に失敗していることがエラーの起因なので、対策はあきらめなければなりません。救いとしてC++コンパイラの構築には成功していますので、C++コンパイラは正常にインストールされています。

インストール内容の完成

不完全インストールの補完

組み込み用のSH3セルフコンパイラは、最終的には組み込みボードの/usrにインストールされますが、PC上では ~/shlinuxにインストールしています。

この段階では不完全インストールの状態なので、インストールの補完をしなけばなりません。問題はどこから補完するかということですが、先にインストールしたクロスコンパイラの内容の一部の持ってきて補完をします。

不完全なセルフコンパイラを補完するためにクロスコンパイラの内容の一部の持ってきて補完をする条件としては、両者の元となるソースパッケージが一致していなければなりません。そのため、今回はgccのコンパイル失敗を見越して、わざわざクロスコンパイラを新規生成したわけです。

ヘッダファイルの補完

Cコンパイラの構築に失敗しているので、Cコンパイラによるコンパイルで必要となるヘッダファイルがインストールされていません。そのため、以下のようにクロスコンパイラからヘッダファイルを持ってきます。

$ cd ~/shlinux
$ cp -a /usr/sh3-linux/sh3-linux/include .

gccライブラリの補完

Cコンパイラの構築に失敗しているので、Cコンパイラによるコンパイルで必要となるgccライブラリがインストールされていません。以下のようにクロスコンパイラからgccライブラリを持ってきます。

$ cd ~/shlinux/lib/gcc/sh3-linux/4.1.2
$ cp -a /usr/sh3-linux/lib/gcc/sh3-linux/4.1.2/lib*.a .

Cライブラリの補完

本来はglibc-2.3.6を構築すべきところですが、Cコンパイラの構築に失敗している状態なので、今回はクロスコンパイラからCライブラリを持ってきます。以下のようにコピーします。

$ cd ~/shlinux/lib
$ cp -a /usr/sh3-linux/sh3-linux/lib/*crt* .
$ cp -a /usr/sh3-linux/sh3-linux/lib/ld*so* .
$ cp -a /usr/sh3-linux/sh3-linux/lib/lib*.a .
$ cp -a /usr/sh3-linux/sh3-linux/lib/lib*so* .

その他の補完

C++コンパイラではC++言語ソースのコンパイルだけでなくC言語ソースのコンパイルもできるようにCコンパイラを兼ねています。前述のとおりC++コンパイラの構築には成功しているので、以下のようにソフトリンクによりC++コンパイラをCコンパイラに見せかけるようにします。

$ cd ~/shlinux/bin
$ ln -s c++ cc
$ ln -s g++ gcc
$ ln -s sh3-linux-c++ sh3-linux-cc
$ ln -s sh3-linux-g++ sh3-linux-gcc

SH7706ボードへのインストール

ルートファイルシステム再構築

SH7706ボードではルートファイルがSDカード上にあり、とりあえず、従来とおりにルートファイルシステムを構築します。今回はCコンパイラとCライブラリのバージョンが変更になったので、できれば、LinuxカーネルとBusyBoxは新しいクロスコンパイラで再構築することをお勧めします。

従来とおりにルートファイルシステムでの/lib以下のファイル群は古いクロスコンパイラ由来のファイルなので、/libフォルダをフォルダごと削除します。

そして、PC上の~/shlinux以下のファイルはルートファイルシステムの/usr以下にあるべきなので、それらを丸ごと/usr以下にコピーします。

ただ、その状態ではLinuxが起動しないので、SDカード上のルートファイルシステムに対し、改めてBusyBoxを上書きインストールしなければなりません。

セルフコンパイルの実行

ルートファイルシステム再構築されたSDカードをSH7706ボードに差し込んでからSH7706ボードからLinuxを起動します。

たとえば、hello.cというファイル名をつけたリスト4のソースファイルだと、以下のようにコンパイルします。

# gcc -o hello hello.c
# ./hello
hello C
#
リスト4 hello.c
#include <stdio.h>

int main() {
	printf("hello C\n");
}

コンパイルや実行では初回はやや時間がかかりますが、2回目以降はキャッシュが効くので反応は早くなります。

次回は

次回はGNUの標準パッケージをSH3セルフコンパイルするために整備をします。

おすすめ記事

記事・ニュース一覧