はじめに
x86_64のLinux上でQEMUを使ってarm用の実行ファイルを動かす方法は以前に書いたことがあるのですが、最近は「マルチプラットフォームのライブラリをビルドしたときにCIを回す」というユースケースが出てきたので再度まとめてみました。
題材とするソースコードはこれ。
#include <stdio.h>
int main()
{
printf("Hello, world!\n");
}
Ubuntu 16.04 を使用しています。
ネイティブのコンパイルと実行
$ gcc -o hello_native hello.c
$ file hello_native
hello_native: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=ffce96d91ecac8524b1d8af9f37c9e719364df7e, not stripped
$ ./hello_native
Hello, world!
クロスコンパイラのインストール
sudo apt install g++-arm-linux-gnueabihf
gccしか必要なくても、あえてg++をインストールするのがコツです。そうするとクロスのlibcなど必要な物が全て芋づる式にインストールされます。
クロスコンパイル
$ arm-linux-gnueabihf-gcc -o hello_arm hello.c
$ file ./hello_arm
./hello_arm: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 3.2.0, BuildID[sha1]=9719544312d6cdfb69a31ca70a4655c12e5596d8, not stripped
$ ./hello_arm
-bash: ./hello_arm: cannot execute binary file: Exec format error
そのままではx86_64のUbuntuの上ではARM用の実行ファイルは実行することができません。
QEMUのインストール
sudo apt install qemu-user-binfmt
これでスタティックリンクされたARMの実行ファイルならそのまま実行できるようになります。
$ arm-linux-gnueabihf-gcc -o hello_arm_static -static hello.c
$ file ./hello_arm_static
./hello_arm_static: ELF 32-bit LSB executable, ARM, EABI5 version 1 (GNU/Linux), statically linked, for GNU/Linux 3.2.0, BuildID[sha1]=72d599d8f0e385a6daa8ebe6216f8fbe8755bda2, not stripped
$ ./hello_arm_static
Hello, world!
ダイナミックリンクされたARMの実行ファイルは以下のようにクロスのルートディレクトリをQEMUに明示的に指定すれば実行できるようになります。
$ qemu-arm -L /usr/arm-linux-gnueabihf/ ./hello_arm
Hello, world!
ダイナミックリンクされたARMの実行ファイルもそのまま実行できるようにする
sudo ln -s /usr/arm-linux-gnueabihf/lib /lib/arm-linux-gnueabihf
sudo ln -s /lib/arm-linux-gnueabihf/ld-2.23.so /lib/ld-linux-armhf.so.3
$ ./hello_arm
Hello, world!
arm64の場合
arm64のツールチェインの名前が違うだけで同様にできます。
sudo apt install g++-aarch64-linux-gnu qemu-user-binfmt
sudo ln -s /usr/aarch64-linux-gnu/lib/ /lib/aarch64-linux-gnu
sudo ln -s /lib/aarch64-linux-gnu/ld-2.23.so /lib/ld-linux-aarch64.so.1
$ aarch64-linux-gnu-gcc -o hello_arm64 hello.c
$ file ./hello_arm64
./hello_arm64: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, for GNU/Linux 3.7.0, BuildID[sha1]=776d40691c4192c0521c641f17b3754b37b73109, not stripped
$ ./hello_arm64
Hello, world!
参考
QEMUのもうひとつの使い方: ユーザーモードエミュレーションとbinfmtとchrootの組み合わせ
Ubuntu 12.04LTS Beta2でMultiarchを試す
Ubuntu 12.04LTS 正式版でMultiarchを試す