準備
- Ubuntu環境がない場合は、WSL もしくは VMWare WorkStation / Player のようなものに Ubuntu24.04 LTSを入れます。(入れ方の詳細は割愛。ぐぐってね)
- Ubuntu環境がある場合は、そのまま以下をどうぞ。
sh4用の gccを入れます。
# apt install gcc-13-sh4-linux-gnu
もしかしたら環境によっては gcc-sh4-linux-gnu でも入るかも。
(gccのVersionは 13もしくは14の好きなほうで。)
sh4 CPUのエミュレータを入れます。
# apt install qemu-user-static
- これはsh4 のみならず、以下のCPUエミュレータを全部含みます。
arm64/32
alpha
cris
hexagon
hppa
loongarch64
m68k
mips64/32
microblaze
ppc
riscv64/32
s390x
sh4/sh4eb
sparc
xtensa
適当なソースコードを用意します。
#include <stdio.h>
int main(){
printf("hello \n");return 0;
}
コンパイルと実行
$ sh4-linux-gnu-gcc hello.c -static
$ ./a.out
hello
- Linux上でsh4のelfがそのまま実行できるのか、というと、実はbinfmt_misc のおかげなんですね。
- 実際には qemu-sh4-static (ビッグエンディアンの場合は、qemu-sh4eb-static) というエミュレータが sh4 elfを読み込んでエミュレートしています。
- つまり、実際には、Linux側で、 ./a.out のELFヘッダーを解釈したのち、
$ qemu-sh4-static ./a.out
もしくは
$ qemu-sh4eb-static ./a.out (ビッグエンディアンの場合)
が実行されているわけです。
(PythonやPerlで書かれたスクリプトが、先頭の #! の後ろに書かれたインタプリタを起動して間接的に実行可能になるのに少し似ていますが、ELFヘッダーを解釈して判別している、というのが肝です。)
-
実行ファイルのファイル名は、gccの出力オプションを省略した場合 a.out というファイル名になりますが、中身は sh4 elf32 形式です。
-
QEMUは、バイナリートランスレータ方式とは言え、一種のエミュレータなので、実行速度は遅いです。(簡単なベンチマークで、おおよそ 1:12 程度でした。)
:別解:頑張ってビルドする。
-
実は、ここで終わりではないんですね。
-
上記の方法では、まったくビルドせずに sh4-gccを取得しましたが、落とし穴があります。
-
BigEndianのバイナリーや sh4以外のCPUバリアントのオプションは全て封じられているのでした Orz...
-
しかたがないので、cross-gccをビルドします。
-
七誌さんのgithubからスクリプトを借用しました。
準備
-
同じく、Ubuntu24.04 LTS (x64) でいきます。
-
作業ディレクトリは /build/
-
インストール先は /opt/cross/ としますが、両方とも ユーザー権限でr/w できるようにしてから始めます。
#!/bin/bash
make_dir()
{
sudo mkdir /build
sudo chown $USER: /build
sudo mkdir /opt
sudo mkdir /opt/cross
sudo chown $USER: /opt/cross
}
download_gcc()
{
sudo apt update
sudo apt install build-essential
sudo apt install libgmp-dev libmpc-dev libmpfr-dev
sudo apt install flex bison texinfo
cd /build ; apt source gcc-13
cd /build ; apt source binutils
tar xf gcc-13-13.3.0/gcc-13.3.0.tar.xz
tar xf binutils-2.42.tar.xz
}
- make_dir でディレクトリを掘って、download_gcc でtarball を /build/ の下に展開します。
#!/usr/bin/env bash
prefix=/opt/cross
cpu=4
build-binutils ()
{
arch=$1
shift
if [ -f $prefix/bin/$arch-as ]; then return; fi
mkdir -p $arch/binutils
cd $arch/binutils
if [ ! -f Makefile ]; then
../../binutils-2.42/configure --prefix=$prefix $@
fi
if [ -f Makefile ]; then
make -j$cpu && make install
fi
cd ../..
}
build-gcc ()
{
arch=$1
shift
if [ -f $prefix/bin/$arch-gcc ]; then return; fi
mkdir -p $arch/gcc
cd $arch/gcc
if [ ! -f Makefile ]; then
../../gcc-13.3.0/configure --prefix=$prefix $@
fi
if [ -f Makefile ]; then
make -j$cpu all-gcc && make install-gcc
fi
cd ../..
}
build ()
{
build-binutils $1 --target=$1
build-gcc $1 --target=$@
}
sh_elf()
{
build sh-elf
}
sh_elf
-
こんな感じで、 ./cross.sh を起動して、sh-gccをビルドします
-
出来上がったら、 /opt/cross/bin にPATHを通します。
( .bash_profile 等に記述 ) -
sh-elf-gcc でクロスgcc が使えます。が、ライブラリ等が皆無なので、次回、newlib のビルド!