初めに
最近、FPGAやCPUの勉強をしておりその過程でクロスコンパイラを導入する機会があったので、その手順などをまとめました。
本記事は、inaz2様の記事をベースにしております。
http://inaz2.hatenablog.com/entry/2015/12/01/204201
今回のクロスコンパイラ構築は、debian:jessieコンテナ内で実行しています。
各種依存関係のダウンロード
今回、クロスコンパイラを構築するうえで下記のパッケージを利用します。
- GCC
- コンパイラー
- BINUTILS
- オブジェクトファイルを取り扱うツール類(リンカ・アセンブラ等)を提供
- GMP
- 任意精度算術演算ライブラリ
- MPFR
- 任意精度の浮動小数点数演算ライブラリ
- MPC
- 複素数演算ライブラリ
ダウンロードスクリプト
今回ダウンロードするものが多いので、スクリプト化しています。
※ダウンロード先はリンク切れを起こす可能性があるので、404エラーでたらリンクを修正してください。
※バージョンの組み合わせによっては次ステップのビルド時にエラーでこける場合があります。
#!/bin/bash
# download.sh
set -e
BINUTILS_VERSION=binutils-2.25
GCC_VERSION=gcc-5.2.0
LINUX_KERNEL_VERSION=linux-3.16
GLIBC_VERSION=glibc-2.22
GMP_VERSION=gmp-6.1.2
MPFR_VERSION=mpfr-4.0.1
MPC_VERSION=mpc-1.1.0
wget -nc http://ftpmirror.gnu.org/binutils/${BINUTILS_VERSION}.tar.gz
wget -nc http://ftpmirror.gnu.org/gcc/${GCC_VERSION}/${GCC_VERSION}.tar.gz
wget -nc https://www.kernel.org/pub/linux/kernel/v3.x/$LINUX_KERNEL_VERSION.tar.xz
wget -nc http://ftpmirror.gnu.org/glibc/$GLIBC_VERSION.tar.xz
wget -nc ftp://ftp.gnu.org/gnu/gmp/${GMP_VERSION}.tar.xz
wget -nc https://www.mpfr.org/mpfr-current/${MPFR_VERSION}.tar.xz
wget -nc https://ftp.gnu.org/gnu/mpc/${MPC_VERSION}.tar.gz
for f in *.tar*; do
bsdtar xfk $f
done
mv ${GMP_VERSION} ${GCC_VERSION}/gmp
mv ${MPFR_VERSION} ${GCC_VERSION}/mpfr
mv ${MPC_VERSION} ${GCC_VERSION}/mpc
gccフォルダ以下に、gmp mpfr mpcフォルダがあるとgccビルド時のconfigureでよしなにやってくれるっぽいです。
クロスコンパイラのビルド
今回は、x86,arm,arm64,powerpc, mips向けのクロスコンパイラをビルドします。
かなりの時間がかかるので、忍耐が必要です。(筆者環境で数時間かかりました)
#!/bin/bash
# build.sh
set -e
PREFIX=/usr/local
PARALLEL_MAKE=-j4
CONFIGURATION_OPTIONS="--disable-multilib --disable-nls"
BINUTILS_VERSION=binutils-2.25
GCC_VERSION=gcc-5.2.0
LINUX_KERNEL_VERSION=linux-3.16
GLIBC_VERSION=glibc-2.22
build() {
local TARGET="$1"
local LINUX_ARCH="$2"
# Step 1. Binutils
mkdir -p build-binutils-$TARGET
cd build-binutils-$TARGET
../$BINUTILS_VERSION/configure --prefix=$PREFIX --target=$TARGET $CONFIGURATION_OPTIONS
make $PARALLEL_MAKE
make install
cd ..
# Step 2. Linux Kernel Headers
cd $LINUX_KERNEL_VERSION
make ARCH=$LINUX_ARCH INSTALL_HDR_PATH=$PREFIX/$TARGET headers_install
cd ..
# Step 3. C/C++ Compilers
mkdir -p build-gcc-$TARGET
cd build-gcc-$TARGET
../$GCC_VERSION/configure --prefix=$PREFIX --target=$TARGET --enable-languages=c,c++ $CONFIGURATION_OPTIONS
make $PARALLEL_MAKE gcc_cv_libc_provides_ssp=yes all-gcc
make install-gcc
cd ..
# Step 4. Standard C Library Headers and Startup Files
mkdir -p build-glibc-$TARGET
cd build-glibc-$TARGET
../$GLIBC_VERSION/configure --prefix=$PREFIX/$TARGET --build=$MACHTYPE --host=$TARGET --target=$TARGET --with-headers=$PREFIX/$TARGET/include $CONFIGURATION_OPTIONS libc_cv_forced_unwind=yes
make install-bootstrap-headers=yes install-headers
make $PARALLEL_MAKE csu/subdir_lib
install csu/crt1.o csu/crti.o csu/crtn.o $PREFIX/$TARGET/lib
$TARGET-gcc -nostdlib -nostartfiles -shared -x c /dev/null -o $PREFIX/$TARGET/lib/libc.so
touch $PREFIX/$TARGET/include/gnu/stubs.h
cd ..
# Step 5. Compiler Support Library
cd build-gcc-$TARGET
make $PARALLEL_MAKE all-target-libgcc
make install-target-libgcc
cd ..
# Step 6. Standard C Library & the rest of Glibc
cd build-glibc-$TARGET
make $PARALLEL_MAKE
make install
cd ..
# Step 7. Standard C++ Library & the rest of GCC
cd build-gcc-$TARGET
make $PARALLEL_MAKE all
make install
cd ..
rm -rf build-binutils-$TARGET build-gcc-$TARGET build-glibc-$TARGET
}
build i686-linux-gnu x86
build arm-linux-gnueabi arm
build arm-linux-gnueabihf arm
build aarch64-linux-gnu arm64
build powerpc-linux-gnu powerpc
build powerpc64le-linux-gnu powerpc
build mips-linux-gnu mips
build mipsel-linux-gnu mips
build mips64el-linux-gnuabi64 mips
build alpha-linux-gnu alpha
build s390x-linux-gnu s390
build m68k-linux-gnu m68k
#build x86_64-linux-gnu x86
#build sparc-linux-gnu sparc
#build sparc64-linux-gnu sparc
#build cris-linux-gnu cris
#build sh4-linux-gnu sh
echo "Build Success!!"
動作テスト
今回はMIPS向けにビルドしたgccを試してみます。
下記の手順でgccを実行するとMIPS向けのアセンブリ出力ができるようになります。
(もちろんバイナリも吐くことができます)
// main.c
int test(int a, int b) {
return a + b;
}
$ mips-linux-gnu-gcc -S main.c
$ cat main.s
.file 1 "main.c"
.section .mdebug.abi32
.previous
.nan legacy
.module fp=32
.module nooddspreg
.abicalls
.text
.align 2
.globl test
.set nomips16
.set nomicromips
.ent test
.type test, @function
test:
.frame $fp,8,$31 # vars= 0, regs= 1/0, args= 0, gp= 0
.mask 0x40000000,-4
.fmask 0x00000000,0
.set noreorder
.set nomacro
addiu $sp,$sp,-8
sw $fp,4($sp)
move $fp,$sp
sw $4,8($fp)
sw $5,12($fp)
lw $3,8($fp)
lw $2,12($fp)
nop
addu $2,$3,$2
move $sp,$fp
lw $fp,4($sp)
addiu $sp,$sp,8
j $31
nop
.set macro
.set reorder
.end test
.size test, .-test
.ident "GCC: (GNU) 5.2.0"