SH4用クロス環境の作り方 (2015年版)

Debian 8 (jessie)で SH4 用のクロス環境を作ったので,手順をメモします.この記事は http://d.hatena.ne.jp/pyopyopyo/20141120 をベースに,最新の情報を加筆したものです.

概要

  • hostは amd64
  • targetは sh4

です

大まかな手順は

  • 手順1) hostに target用のヘッダファイルやライブラリをインストール
  • 手順2) hostに target用のbinutilsをインストール
  • 手順3) hostに target用のgccをインストール

となります

target がARMであればdebianが正式にサポートしているため作業は簡単です.しかし sh4は正式にサポートされていないので,以下の手順で少々強引に作業しました

手順1) target用のライブラリ類のインストール

sh4 アーキテクチャdebian では正式にサポートされていないので,少々面倒くさい手順が必要です.

まず sh4 を追加します

$ sudo dpkg --add-architecture sh4

次に /etc/apt/sources.list に下記の2行を追加します

deb  [arch=sh4]     http://ftp.debian-ports.org/debian unstable   main
deb  [arch=sh4]     http://ftp.debian-ports.org/debian unreleased main

[arch=hoge] と書いておくと,アーキテクチャhogeの場合だけ,設定が有効になります


一度情報を更新します

sudo apt-get update

続けて,debian-ports.org の署名をインストール

sudo apt-get install debian-ports-archive-keyring
sudo apt-get update

これでftp.debian-ports.orgで配布されているsh4のバイナリが流用できるようになります.たとえば

apt-get download libc6:sh4

などとすると, sh4 用のdebパッケージがダウンロードできます.

次に dpkg-cross というツールをインストールします

$ sudo apt-get install dpkg-cross

dpkg-cross は debパッケージをクロス環境用のパッケージに変換するツールです

たとえば sh4 用の libc6のパッケージ libc6_2.19-19_sh4.deb

$ apt-get download libc6:sh4
$ dpkg-cross -A -M -a sh4 -b libc6_2.19-19_sh4.deb 

で libc6-sh4-cross_2.19-19_all.deb に変換できます.変換後は

$ sudo dpkg -i  libc6-sh4-cross_2.19-19_all.deb

で,インストールできます

この手順で,GCCのビルドに必要なパッケージ

  • libc6
  • libc6-dev
  • libc-dev-bin
  • linux-libc-dev
  • gcc-5-base
  • multiarch-support

をインストールします

Debian 7以前は apt-cross, xapt で変換&インストール作業が自動化できたのですが, debian 8 でapt-crossなどが obsolete になったため,地道に手動インストールします.

手順2) target用のライブラリ類の確認

sh4-corssが提供するファイルは /usr/sh4-linux-gnu ディレクトリ以下に配置されます

重要なファイルは,以下のディレクトリに配置されるヘッダファイルとライブラリです

fileコマンドを使って,バイナリのヘッダを確認すると

$ file /usr/sh4-linux-gnu/lib/crt1.o 
/usr/sh4-linux-gnu/lib/crt1.o: ELF 32-bit LSB relocatable, Renesas SH, version 1 (SYSV), for GNU/Linux 2.6.32, not stripped

という感じで ターゲットの sh4 用のバイナリであることが確認できます

手順3) target用のbinutilsをインストール

$ sudo apt-get build-dep --no-install-recommends binutils

$ apt-get source binutils

$ cd binutils-*
$ TARGET=sh4 fakeroot dpkg-buildpackage -b -us -uc
$ cd ..

出来上がったdebパッケージの内容を確認してみます

$ dpkg --contents binutils-sh4-linux*.deb

例えば リンカ(ld)は /usr/bin/sh4-linux-gnu-ld,asは/usr/bin/sh4-linux-gnu-asと言う感じでコマンドの頭に sh4-linux-gnu- が付与されていれば成功です.

問題なければインストールします

$ sudo dpkg -i  binutils-sh4-linux*.deb

手順4) target用のGCCをインストール

sh4 用のGCC をインストールします

ここで

  • debianでは sh4 はあまりメンテされていない
  • 今回,私が必要とするのは Cコンパイラだけで, gcjやobjc++等は不要

という理由から GCCdebパッケージを用いず,自前でビルドすることにしました

インストール先は念の為 /opt とします.つまりGCCのconfigure 時には --prefix=/opt をつけ,
アンイストール時は /opt 以下を消せばOK,ということになります

$ sudo mkdir -p /opt

MultiArch のルールでは クロスコンパイル用のライブラリやヘッダは /usr/sh4-linux-gnu 以下に配置します. --prefix=/opt をつけたGCCは /opt/sh4-linux-gnu を見ることになるので,シンボリックリンクを貼ります

$ sudo ln -s /usr/sh4-linux-gnu /opt

次に GCCソースコードをダウンロードします.GCC 5.2.0 を使いました

$ wget http://ftp.tsukuba.wide.ad.jp/software/gcc/releases/gcc-5.2.0/gcc-5.2.0.tar.bz2
$ tar xfj gcc-5.2.0tar.bz2
$ cd gcc-5.2.0

作業用ディレクトリを作成します

$ mkdir gccbuild
$ cd  gccbuild

念の為,不具合を起こしそうな環境変数達をリセットします

unset CC
unset CXX
unset FC
unset CCACHE_DIR

ライブラリをインストール

sudo apt-get install libgmp-dev libmpfr-dev libmpc-dev
../gcc-5.2.0/configure --prefix=/opt --enable-languages=c  --target=sh4-linux-gnu --disable-libssp --disable-libgomp --disable-nls --disable-libatomic --disable-libquadmath --with-cpu=sh4 --with-multilib-list=m4,m4-nofpu --disable-threads 

オプションはそれぞれ

  • --enable-languages=c Cのコンパイラだけビルド
  • --target=sh4-linux-gnu
  • --with-cpu=sh4 ターゲットを sh4 に
  • --with-multilib-list=m4,m4-nofpu FPU有と無版のSH4に対応させるため
  • --disable-??? 不要なものは無効にする

という感じです

ビルドして,インストールします

$ make -j16
$ sudo make install

Cのコンパイラだけなので,ビルドはすぐに終わります.手元のマシンでは 3分程度で終わりました

step5) 動作確認

まずバージョン等を確認しましょう

$ export PATH=/opt/bin:$PATH
$ sh4-linux-gnu-gcc -v

次に簡単なコードをコンパイルしてみます

$ cat hoge.c
int main() { return 123; }
$ sh4-linux-gnu-gcc  hoge.c
$ file ./a.out
./a.out: ELF 32-bit LSB executable, Renesas SH, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, not stripped

ターゲットに a.out をコピーして,実行してみます.

$ ./a.out
$ echo $?
123

問題なければ,次の段階で printf を試してみます

$ cat hoge.c
#include <stdio.h>
int main() { printf("Hello C\n"); return 0; }
$ sh4-linux-gnu-gcc  hoge.c

ついでに strip コマンドも試してみます

$ sh4-linux-gnu-strip a.out 

sh4-linux-gnu- をつけるのを忘れずに.

以上で,クロス環境のセットアップは完了です