はじめに
RISC-Vのクロスコンパイラ(GCC)のビルド方法をメモしておきます。
良くある手順は、https://github.com/riscv-collab/riscv-gnu-toolchain を利用したビルド方法ですが、今回はあえて公式のGCCを利用する方法を採用します。
作業環境
- WSL2 on Windows 11
- Ubuntu 24.04.4 LTS
手順
ビルド環境の用意
必要に応じて、不足しているパッケージをインストールします。
一例として、以下コマンドによりインストールします。
sudo apt install gawk build-essential bison flex texinfo
また、今後の作業のための環境変数を設定します。
export PREFIX=/opt/riscv # ツールのインストール先(お好みで設定してください)
export SYSROOT=$PREFIX/sysroot
export TARGET=riscv64-unknown-linux-gnu
インストール先のフォルダを作成し、所有者を変更します。
(インストール時にsudoを使用しないようにするため。一部パッケージは誤ってホストにインストールするとホストシステムを破壊します(特にGlibc))。
sudo mkdir $PREFIX
sudo chown <user> $PREFIX
Binutils
コンパイラをビルドするためには、まずはアセンブラやリンカ等のユーティリティが必要です。Binutilsはアセンブラやリンカを含む、オブジェクトファイルを扱うためのツール群です。下記手順によりビルド、インストールします。
wget https://ftp.jaist.ac.jp/pub/GNU/binutils/binutils-2.45.tar.xz
tar xf binutils-2.45.tar.xz
cd binutils-2.45
mkdir build
cd build
../configure --prefix=$PREFIX \
--with-sysroot=$SYSROOT \
--target=$TARGET \
--disable-nls \
--enable-gprofng=no \
--disable-werror \
--enable-new-dtags \
--enable-default-hash-style=gnu
make -j$(nproc)
make install
インストール後、パスを通します。
export PATH=$PREFIX/bin:$PATH
GCC 1回目
GCCを完全にビルドするためには、標準Cライブラリが必要です。しかし標準CライブラリをビルドするにはGCCが必要であり、循環的な依存関係が生じます。
そのため、まずは標準Cライブラリに依存しない最小限のGCCをビルドし、そこでビルドしたGCCを使って標準Cライブラリをビルドします。最後に標準ライブラリと最小限のGCCを使って、完全なGCCをビルドします。
以下コマンドによりGCCをインストールします。
wget https://ftp.jaist.ac.jp/pub/GNU/gcc/gcc-15.2.0/gcc-15.2.0.tar.xz
tar xf gcc-15.2.0.tar.xz
cd gcc-15.2.0
contrib/download_prerequisites
mkdir build
cd build
../configure \
--target=$TARGET \
--prefix=$PREFIX \
--with-glibc-version=2.42 \
--with-sysroot=$SYSROOT \
--with-newlib \
--without-headers \
--enable-default-pie \
--enable-default-ssp \
--disable-nls \
--disable-shared \
--disable-multilib \
--disable-threads \
--disable-libatomic \
--disable-libgomp \
--disable-libquadmath \
--disable-libssp \
--disable-libvtv \
--disable-libstdcxx \
--enable-languages=c,c++
make -j$(nproc)
make install
cd ..
cat gcc/limitx.h gcc/glimits.h gcc/limity.h > \
`dirname $($TARGET-gcc -print-libgcc-file-name)`/include/limits.h
Linux APIヘッダ
Glibcのビルドのためには、Linuxのヘッダが必要となります。以下コマンドによりインストールします。
wget https://ftp.jaist.ac.jp/pub/Linux/kernel.org/linux/kernel/v6.x/linux-6.16.1.tar.xz
tar xf linux-6.16.1.tar.xz
cd linux-6.16.1
make mrproper
ARCH=riscv make headers
find usr/include -type f ! -name '*.h' -delete
mkdir -pv $SYSROOT/usr
cp -rv usr/include $SYSROOT/usr
Glibc
標準CライブラリであるGlibcを、以下コマンドによりビルドします。
wget https://ftp.jaist.ac.jp/pub/GNU/glibc/glibc-2.42.tar.xz
tar xf glibc-2.42.tar.xz
cd glibc-2.42
mkdir build
cd build
../configure \
--prefix=/usr \
--host=$TARGET \
--build=$(../scripts/config.guess) \
--disable-nscd \
libc_cv_slibdir=/usr/lib \
--enable-kernel=5.4
make -j$(nproc)
Glibcをホストにインストールしてしまうと、ホストが利用不能になります。$SYSROOTが適切に設定されていることを確認した上で、インストールは必ず一般ユーザであることを確認してから実行してください。
以下コマンドによりGlibcをインストールします。
make DESTDIR=$SYSROOT install
GCC 2回目
標準Cライブラリ(Glibc)がインストールできましたので、完全版のGCCをビルドしていきます。
cd gcc-15.2.0
mkdir build2
cd build2
../configure \
--target=$TARGET \
--prefix=$PREFIX \
--with-sysroot=$SYSROOT \
--enable-default-pie \
--enable-default-ssp \
--disable-nls \
--disable-multilib \
--disable-libatomic \
--disable-libgomp \
--disable-libquadmath \
--disable-libsanitizer \
--disable-libssp \
--disable-libvtv \
--enable-languages=c,c++ \
LDFLAGS_FOR_TARGET=-L$PWD/$TARGET/libgcc
make -j$(nproc)
make install
以上でクロスコンパイラのビルドは完了です。
テスト
今回ビルドしたクロスコンパイラをテストしてみましょう。コンパイルしたプログラムを実行するために、QEMUを導入します。
sudo apt install qemu-user
C言語のコンパイルテスト
Hello Worldをビルドしてみます。
cat > test.c << "EOF"
#include <stdio.h>
int main(void)
{
printf("Hello C World!!\n");
return 0;
}
EOF
riscv64-unknown-linux-gnu-gcc -o test -static test.c
実行します。
$ qemu-riscv64 test
Hello C World!!
C++のコンパイルテスト
C言語と同様、Hello Worldをビルドしてみます。
cat > test.cpp << "EOF"
#include <iostream>
int main()
{
std::cout << "Hello C++ World!!" << std::endl;
return 0;
}
EOF
riscv64-unknown-linux-gnu-g++ -o test -static test.cpp
実行します。
$ qemu-riscv64 test
Hello C++ World!!
成功です。お疲れ様でした。
参考
本記事に示す手順は、Linux From Scratchの手順をRISC-V向けにアレンジしました。
また、以下記事を参考にしました。