概要
chroot
先で異なる CPU architecture をエミュレーションしたい場合は、static link された QEMU user space emulator を使うと便利である。しかし、Debian stretch でインストールできる QEMU 3.1 では APT コマンドが発行されると Segmentation fault が発生し、エミュレーションが正常に完了しない。QEMU 7 以降を使用すると動作する報告があるので、ソースコードをビルドして最新版をインストールする。
QEMU を static link でビルドする際には、静的ライブラリが必要である。しかし、Debian stretch (そしておそらくそれ以降) ではいくつかの必要な静的ライブラリが配布されていない (e.g. libpulseaudio0
は共有ライブラリのみの配布)。依存ライブラリはかなり多く、それぞれビルドするのはかなり難儀であるが、多くが音声や画面描画のツールキットであり、目的によっては不要となるものが多い。今回は、https://github.com/OmeSatoFoundation/ome2023 をビルドするのに (おそらく) 最低限必要なライブラリのみをリンクするよう設定する。
作業は QEMU をビルドして binfmt を設定しているだけなので、他のディストリビューション等でも動作する可能性はある。一方で、QEMU を static build するのに必要な静的ライブラリの配布状況はディストリビューションにより異なるので、Debian stretch 以外で試す際は無効にすべきライブラリが増えるかもしれない。
手順
QEMU のビルド
まず、QEMU をダウンロードする。今回は、7.1.0 をダウンロードした。
https://www.qemu.org/download/
ビルドする。キモは、--static
で static link させることと、--disable-xxx
で余剰な依存ライブラリをへらすこと。
./configure prefix=/usr --static '--disable-tools' '--disable-sdl' '--disable-gtk' '--disable-vnc' '--disable-virtfs' '--disable-attr' '--disable-libiscsi' '--disable-libnfs' '--disable-libusb' '--disable-opengl' '--disable-numa' '--disable-usb-redir' '--disable-bzip2' '--audio-drv-list=' '--disable-guest-agent' '--disable-vte' '--disable-mpath' '--disable-libudev' '--disable-vhost-user' '--disable-curl' '--disable-gnutls' --disable-alsa --disable-coreaudio --disable-pa
make
sudo make install
(--prefix=/usr)/bin/qemu-aarch64
が生成される。これは事前の --static
設定のおかげで静的リンクされているので
$ ldd $(which qemu-aarch64)
statically linked
慣例に従い qemu-aarch64-static
にリネームする。
ln -sf /usr/bin/qemu-aarch64 /usr/bin/qemu-aarch64-static
binfmt の更新
binfmt
を更新し、システムコールが正しく変換されるようにする。
/usr/share/binfmts/qemu-aarch64
に設定ファイルを書く。
package qemu-user-static
interpreter /usr/bin/qemu-aarch64-static
flags: OC
offset 0
magic \x7f\x45\x4c\x46\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xb7\x00
mask \xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff
参考: ARMing Yourself - Working with ARM on x86_64 | Code Pyre https://codepyre.com/2019/12/arming-yourself/
設定ファイルをもとに更新する。
sudo update-binfmts --import qemu-aarch64
sudo update-binfmts --enable qemu-aarch64
update-binfmts が反映されたか確認。/proc/sys/fs/binfmt_misc/qemu-aarch64
が /usr/share/binfmts/qemu-aarch64
と等価か確認する。
$ cat /proc/sys/fs/binfmt_misc/qemu-aarch64
enabled
interpreter /usr/bin/qemu-aarch64-static
flags:
offset 0
magic 7f454c460201010000000000000000000200b700
mask ffffffffffffff00fffffffffffffffffeffffff
以上で、qemu-aarch64-static
が chroot
下ではたらき、異なるCPUアーキテクチャのエミュレーションが可能になる。
今後の展望
これをコンテナで行う。QEMU と、binfmt が必要。
Ubuntu以外のディストリビューションでarmhfなDocker imageを作成する - Qiita https://qiita.com/abtc/items/0696ebef11038f29261c
また、余談だが、chroot 先は .iso
などディスクのアーカイブのループバックデバイスであることが多い。ループバックデバイスを (上手に隔離の上で) コンテナ内で使用するには、工夫が必要である。適当な隔離の上コンテナ内で異なる CPU アーキテクチャ向けのディスクアーカイブを (手動で) losetup
し、chroot して作業する方法を調査することが今後の課題として残る。