Gentoo Linuxでパッケージのクロスビルドを行う

投稿者: | 8月 20, 2025

はじめに

PowerBook G4にGentoo Linuxを入れていたのですが、あまりにもemergeに時間がかかるので、パッケージのクロスビルドを行おうと考えました。distccを使っていたのですが、ホストの性能がダメダメなのか、そんなに早くないので変えることにしました。

環境

とりあえず、クロスビルド用のGentoo Linuxを用意します。WSLにサックと導入しました。Systemd版です。ここらへんのページを参考にしました。めんどくさいのでユーザはrootのままです。
pong.ursm.jp「Gentooはどんどん簡単になっている」
Gentoo Linux Wiki「WSL内でのGentoo」
名前解決が何故かできなかったのですが、
rm /etc/resolv.conf
ln -s /mnt/wsl/resolv.conf /etc/resolv.conf
で、resolv.confをwslが生成したものに変え、
systemctl stop systemd-resolved.service
systemctl disable systemd-resolved.service
でststemd-resolvedを停止したところ名前解決ができるようになりました。
なんか、gpg鍵も取ってきてくれなかったので
getuto --auto
で取得しました。

クロスビルド環境の構築

参考にしたサイト
Gentoo Linux Wiki「Cross build environment」
Gentoo Linux Wiki「Embedded Handbook/General/Compiling with QEMU user chroot」
Gentoo Linux Wiki「crossdev」

1. crossdev、eselectのインストール
emerge -av crossdev eselect-repository

2. Crossdev overlayの作成
eselect repository create crossdev

3. toolchainのインストールと設定
crossdev --stable --target powerpc-unknown-linux-gnu
stableオプションを付けないと~なバージョンをインストールされてしまい、母艦のglicやgccとバージョンが合わなくなってしまったりします。
/usr以下に生成されます
PORTAGE_CONFIGROOT=/usr/powerpc-unknown-linux-gnu eselect profile list
でプロファイルの一覧を表示し、
PORTAGE_CONFIGROOT=/usr/powerpc-unknown-linux-gnu eselect profile set default/linux/ppc/23.0/systemd
でプロファイルの設定を行います。母艦のamd64用のプロファイルしか出てこないことがありますが、適当に、
ln -s /var/db/repos/gentoo/profiles/default/linux/ppc/23.0/systemd /usr/powerpc-unknown-linux-gnu/etc/portage/make.profile
とかでシンボリックリンクを作成したあとにもう一度実行すれば正しいものが適用されます。

4. make.confの設定
一応バックアップを取ります。
cp /usr/powerpc-unknown-linux-gnu/etc/portage/make.conf /usr/powerpc-unknown-linux-gnu/etc/portage/make.back

PowerBook G4の方のmake.confが以下のような感じなので、

COMMON_FLAGS="-mcpu=7450 -O2 -maltivec -mabi=altivec -pipe"
CFLAGS="${COMMON_FLAGS}"
CXXFLAGS="${COMMON_FLAGS}"
FCFLAGS="${COMMON_FLAGS}"
FFLAGS="${COMMON_FLAGS}"
CHOST="powerpc-unknown-linux-gnu
ACCEPT_LICENSE="*"
MAKEOPTS="-j56"
NINJAOPTS="-j56"
CPU_FLAGS_PPC="altivec"
ACCEPT_KEYWORDS="ppc"
USE="X opengl gtk systemd dbus acpi mtp networkmanager bluetooth alsa pulseaudio cups fcitx5"
INPUT_DEVICES="libinput synaptics"
VIDEO_CARDS="ati radeon r300"
GRUB_PLATFORMS="ieee1275"

これをいい感じに書き換えて
vim /usr/powerpc-unknown-linux-gnu/etc/portage/make.conf
の中身は、

CHOST=powerpc-unknown-linux-gnu
CBUILD=x86_64-pc-linux-gnu

ROOT=/usr/${CHOST}/

ACCEPT_KEYWORDS="ppc"
ACCEPT_LICENSE="*"

USE="pam X opengl gtk systemd dbus acpi mtp networkmanager alsa pulseaudio cups fcitx5"

COMMON_FLAGS="-mcpu=7450 -O2 -maltivec -mabi=altivec -pipe"
CFLAGS="${COMMON_FLAGS}"
CXXFLAGS="${COMMON_FLAGS}"
FCFLAGS="${COMMON_FLAGS}"
FFLAGS="${COMMON_FLAGS}"

FEATURES="-collision-protect sandbox buildpkg noman noinfo nodoc -pid-sandbox -network-sandbox"
# Be sure we dont overwrite pkgs from another repo..
PKGDIR=${ROOT}var/cache/binpkgs/
PORTAGE_TMPDIR=${ROOT}tmp/

MAKEOPTS="-j56"
NINJAOPTS="-j56"
CPU_FLAGS_PPC="altivec"
VIDEO_CARDS="ati radeon r300"

としました。

5. ビルドのテスト
とりあえず、htopをビルドしてみます。
powerpc-unknown-linux-gnu-emerge -av htop
完了すると、
/usr/powerpc-unknown-linux-gnu/var/cache/binpkgs/sys-process/htop/
にgpkgが生成されます。

ここまででもgccとg++だけを使うパッケージならインストール・ビルドできます。しかしながら、他のビルドツールを使用したりインストール段階でpowerpc用のバイナリを使用する物の場合、アーキテクチャが違うので実行できません。そのためQEMUを使用したChrootが必要になってきます。

6. ステージの適用
インストール時と同じ用にStage3を適用させます。
cd /usr/powerpc-unknown-linux-gnu
wget ステージのURL
tar -xJpf stage3-*.tar.xz --xattrs-include='.*' --exclude=dev --skip-old-files
で展開します。

7. QEMUのインストール
vim /etc/portage/package.use/qemu

app-emulation/qemu QEMU_SOFTMMU_TARGETS: ppc
app-emulation/qemu QEMU_USER_TARGETS: ppc
app-emulation/qemu static-user static-libs
とインストールするシミュレーションするアーキテクチャを指定します。そしてインストール
emerge -a --buildpkg --oneshot app-emulation/qemu
多分USEの変更を求めれるので適当にdispatch-confします。
crossbuild環境にインストール
cd /usr/powerpc-unknown-linux-gnu && ROOT=$PWD/ emerge --ask --usepkgonly --oneshot --nodeps qemu

8. QEMUの設定
ラッパーを使ってQEMUをPowerPC G4用の設定にします。これをせずに、/etc/binfmt.d/qemu.confを使用すると
qemu: uncaught target signal 4 (Illegal instruction) – core dumped
Illegal instruction (core dumped)
とか言われてほとんど動きません。また、chroot外で動作させようとするとライブラリの場所が異なるためライブラリが見つからずエラーになります。これらを防ぐためにラッパーを書きます。
cd
vim qemu-ppc-g4-wrapper_chroot.c

#include <string.h>
#include <unistd.h>

int main(int argc, char **argv, char **envp) {
        char *newargv[argc + 3];

        newargv[0] = argv[0];
        newargv[1] = "-cpu";
        newargv[2] = "g4";

        memcpy(&newargv[3], &argv[1], sizeof(*argv) * (argc -1));
        newargv[argc + 2] = NULL;
        return execve("/usr/bin/qemu-ppc", newargv, envp);
}

と書き、
gcc -static qemu-ppc-g4-wrapper_chroot.c -O3 -s -o qemu-ppc-g4-wrapper
でバイナリを生成します。これを
mv qemu-ppc-g4-wrapper /usr/powerpc-unknown-linux-gnu/usr/local/bin/qemu-ppc-g4-wrapper
に配置します。続いて
vim qemu-ppc-g4-wrapper.c

#include <string.h>
#include <unistd.h>

int main(int argc, char **argv, char **envp) {
        char *newargv[argc + 5];

        newargv[0] = argv[0];
        newargv[1] = "-cpu";
        newargv[2] = "g4";
        newargv[3] = "-L";
        newargv[4] = "/usr/powerpc-unknown-linux-gnu/";

        memcpy(&newargv[5], &argv[1], sizeof(*argv) * (argc -1));
        newargv[argc + 4] = NULL;
        return execve("/usr/bin/qemu-ppc", newargv, envp);
}

と書き、
gcc -static qemu-ppc-g4-wrapper.c -O3 -s -o qemu-ppc-g4-wrapper
でバイナリを生成します。これを
mv qemu-ppc-g4-wrapper /usr/local/bin/qemu-ppc-g4-wrapper
でそれぞれに配置します。続いてはbinfmt_miscの設定です。
vim /etc/binfmt.d/qemu-ppc-g4.conf

:qemu-ppc:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x14:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/local/bin/qemu-ppc-g4-wrapper:OC
を記述し、
systemctl restart systemd-binfmt.service
で適用します。有効になっているqemuの設定の一覧は
ls /proc/sys/fs/binfmt_misc/
で確認でき、catで中身を確認できます。

8. Rustのクロスコンパイル設定
vim /etc/portage/package.use/cross-rust

dev-lang/rust rust-src
を記述
mkdir /etc/portage/env/dev-lang
vim /etc/portage/env/dev-lang/rust
にRUST_CROSS_TARGETS=<LLVM target>:<rust-target>:<CTARGET>を記述します。<LLVM target>の確認は、emerge –ask –oneshot llvm-core/llvmした時に確認できるUSEフラグから抽出し、<rust-target>の確認は、rustcのドキュメントから、<CTARGET>はcrossdevのtoolchainインストール時の物を使用します。今回の場合は以下の様です。
RUST_CROSS_TARGETS=PowerPC:powerpc-unknown-linux-gnu:powerpc-unknown-linux-gnu
一度world
emerge -avuDN @world

cd /var/db/repos/crossdev/cross-powerpc-unknown-linux-gnu
ln -s /var/db/repos/gentoo/sys-devel/rust-std
vim /etc/portage/package.accept_keywords/cross-rust

cross-powerpc-unknown-linux-gnu/rust-std **
を記述、そしてrustのインストール
emerge -av cmake
emerge -av cross-powerpc-unknown-linux-gnu/rust-std

9. chroot
まず必要のディレクトリの作成
cd /usr/powerpc-unknown-linux-gnu
mkdir var/db/repos/gentoo
mkdir var/db/repos/localrepo-crossdev
mkdir lib/modules
mkdir dev

下のコマンドは毎回打つのが面倒なのでシェルスクリプトにするか、arch-chrootを使うのが良いと思います。
cd /usr/powerpc-unknown-linux-gnu
mount -t proc none proc
mount –rbind /dev dev
mount –make-rslave dev
mount -o bind /var/db/repos/gentoo var/db/repos/gentoo
mount -o bind /var/db/repos/localrepo-crossdev var/db/repos/localrepo-crossdev
mount -o bind /lib/modules lib/modules
mount –rbind /sys sys
mount –make-rslave sys
cp /etc/resolv.conf etc/resolv.conf
chroot . /bin/bash –login

11. なんかシェルスクリプトを実行するとエラーが出る場合
# locale-gen
bash: /usr/bin/locale-gen: cannot execute: required file not found
とか言われます。/bin/bashが存在せず、/usr/bin/bashにしか無いため発生します。
ln -s /usr/bin/bash /bin/bash

12. とりあえず、world
chroot外で
emerge-powerpc-unknown-linux-gnu -avuDN @world
を行います。

12. なんかemergeするとqemuのエラーが出る
emergeすると
qemu: qemu_thread_create: Invalid argument
とか言われて何もできません。chrootのネットワーク周りの不完全さによるものらしいです。
chroot内で
vim /etc/portage/make.conf
のFEATURESに-pid-sandbox -network-sandboxを追加します。

13. なんかfunction.shが無いと言われる
母機の方からコピーしました。chrootから抜けた状態で
cp -R /lib/gentoo /usr/powerpc-unknown-linux-gnu/lib/

14. 初期設定
ln -s /tmp /usr/powerpc-unknown-linux-gnu/tmp
nano /etc/locale.gen
以下の2つを有効にしました。
en_US.UTF-8 UTF-8
ja_JP.UTF-8 UTF-8
そして適用
locale-gen
gccの設定の確認と適用
gcc-config -l;ldconfig -v;ROOT=/ env-update; source /etc/profile
emerge用の環境変数の設定
echo 'alias emerge-chroot="ROOT=/ emerge"' > ~/.bash_profile && source ~/.bash_profile

15. クロスビルドしたいものをビルド
chroot内ではemerge-chroot、chroot外ならemerge-powerpc-unknown-linux-gnuを使用します。
chroot内はQEMU上で動いているので遅いです。基本的にはemerge-powerpc-unknown-linux-gnuを使用して、エラーが出たらemerge-chrootを使う感じが良いと思います。

クロスビルド中に発生した様々なエラーと対処

1. なんかUSEフラグが自動では設定されない問題への対処法
dispach-confをしても何も出てこないし、–autounmask=y –autounmask-writeオプションを付けても変わりません。dispach-confのあとにパスを指定すればいけました。
chroot外なら、
dispach-conf /usr/powerpc-unknown-linux-gnu/etc/portage/package.use
とかで行けると思います。

2. なんかglibがインストールできない
ERROR: An exe_wrapper is needed for /tmp/portage/dev-libs/glib-2.84.3/work/gobject-introspection-1.82.0-build/tools/g-ir-compiler but was not found. Please define one in cross file and check the command and/or add it to PATH.
とかいうエラーが出てしまい進みませんでした。
Bug 850895 – dev-libs/gobject-introspection: cannot cross-compile An exe_wrapper is needed but was not found
Bug 751325 – meson.eclass: Support for setting exe wrapper for crosscompilation
とかを参考にして、直接mesonのファイルを編集して解決させました。
chroot内で、
cp /var/db/repos/gentoo/eclass/meson.eclass /var/db/repos/gentoo/eclass/meson.eclass.bak
でバックアップをとって、
vim /var/db/repos/gentoo/eclass/meson.eclass
で開いて_meson_create_cross_file()の[binaries]にexe_wrapper = ‘/usr/local/bin/qemu-ppc-g4-wrapper’を追加したところ、chroot内でemerge-chrootでインストールできました。

3. なんかlddがおかしくてnot a dynamic executableしか返さず、パッケージがインストールできない
/usr/powerpc-unknown-linux-gnu/lib/ld.so.1が含まれていないせいで、powerpc用のバイナリを解析できないのが原因でした。
vim /usr/bin/ldd
で開いて、RTLDLISTの最後に、/usr/powerpc-unknown-linux-gnu/lib/ld.so.1を追加しました。無事にインストールできるようになりました。

バイナリパッケージの配布とインストール

参考にしたサイト
gentoo linux Wiki「バイナリーパッケージガイド」
ntoofu「Gentoo Linuxで(Portageで)パッケージビルドサーバーを使う」

生成されたバイナリパッケージは
/usr/powerpc-unknown-linux-gnu/var/cache/binpkgs/
に存在します。これのディレクトリをSSHやhttpで公開し、インストールしたいデバイスの/etc/portage/make.confにPORTAGE_BINHOSTを設定することで使用できます。

1. apacheのインストールと実行
emerge -av apache
systemctl start apache2

2. シンボリックリンクの作成
なんかデフォルトだと、apache2のルートディレクトリが/var/www/localhost/htdocsなので、横着して、そのままシンボリックリンクを貼り付けました。
ln -s /usr/powerpc-unknown-linux-gnu/var/cache/binpkgs/ /var/www/localhost/htdocs/binpkgs
http://IPアドレス/binpkgs/にアクセスするとパッケージの一覧が見えるはずです。

3. クライアント(バイナリパッケージをインストールする)側の設定
vim /etc/portage/make.conf
に、
PORTAGE_BINHOST=http://IPアドレス/binpkgs/
を書きます。

4. バイナリパッケージのインストール
-Gオプションか、–getbinpkgonlyをつけることで、強制的にバイナリパッケージを使用することができます。

おわりに

かなり大変でしたがPowerBook G4にepiphany(GNOME Web)をインストールをすることができました。3回くらいWSLのインストールし直した気がします。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)