fedoraでdockerを使ってaarch64のクロスビルド環境を作る

qemuのstaticなバイナリとbinfmt_miscを使ってdockerでクロスビルド環境を作ってみます。

今回作ったものはこちらに置きました。

github.com

環境

HostはFedora 29で、arm64v8/fedoraにあるaarch 64のFedora 28(2018/10/11時点でのlatestはfedora 28です)。このイメージはオフィシャルなものです。

qemu

qemuのパッケージで必要なのは qemu-user-static です。これをサクッとインストールしましょう。

binfmt_misc

つぎにbinfmt_miscの設定が必要なんですが、fedoraの場合systemdのproc-sys-fs-binfmt_misc.mountが動いてればOKです。自分の場合はインストールした後に所要で再起動したのですが、restartとかすれば良い気がします。

masami@saga:~$ systemctl status proc-sys-fs-binfmt_misc.mount
● proc-sys-fs-binfmt_misc.mount - Arbitrary Executable File Formats File System
   Loaded: loaded (/usr/lib/systemd/system/proc-sys-fs-binfmt_misc.mount; static; vendor preset: disabled)
   Active: active (mounted) since Thu 2018-10-11 20:07:16 JST; 2h 2min ago
    Where: /proc/sys/fs/binfmt_misc
     What: binfmt_misc
     Docs: https://www.kernel.org/doc/html/latest/admin-guide/binfmt-misc.html
           https://www.freedesktop.org/wiki/Software/systemd/APIFileSystems
    Tasks: 0 (limit: 4915)
   Memory: 60.0K
   CGroup: /system.slice/proc-sys-fs-binfmt_misc.mount

Oct 11 20:07:16 saga systemd[1]: Mounting Arbitrary Executable File Formats File System...
Oct 11 20:07:16 saga systemd[1]: Mounted Arbitrary Executable File Formats File System.

/proc/sys/fs/binfmt_miscを手動で設定するときはELFバイナリのシグネチャとかを自分で設定しないといけないんですが、proc-sys-fs-binfmt_misc.mountが上手いことやってくれてるようです。/proc/sys/fs/binfmt_misc/が↓のようになっていれば設定完了です。

masami@saga:~$ ls /proc/sys/fs/binfmt_misc/
./            qemu-aarch64_be  qemu-armeb  qemu-microblaze    qemu-mips64    qemu-mipsn32    qemu-ppc      qemu-riscv32  qemu-sh4          qemu-xtensa    status
../           qemu-alpha       qemu-hppa   qemu-microblazeel  qemu-mips64el  qemu-mipsn32el  qemu-ppc64    qemu-riscv64  qemu-sh4eb        qemu-xtensaeb
qemu-aarch64  qemu-arm         qemu-m68k   qemu-mips          qemu-mipsel    qemu-or1k       qemu-ppc64le  qemu-s390x    qemu-sparc32plus  register

docker image

arm64v8/fedoraのイメージを使います。

試しに動作確認をしてたのが以下になります。unameコマンドで表示されるアーキテクチャがaarch64になってますね。

masami@saga:~$ sudo docker pull arm64v8/fedora
Using default tag: latest
Trying to pull repository docker.io/arm64v8/fedora ... 
sha256:a2adc1621935869bcd51a84b007b3ee6aa8aa9aef0bf30a947f7312fd43e5b0b: Pulling from docker.io/arm64v8/fedora
f9afc51fb922: Pull complete 
Digest: sha256:a2adc1621935869bcd51a84b007b3ee6aa8aa9aef0bf30a947f7312fd43e5b0b
Status: Downloaded newer image for docker.io/arm64v8/fedora:latest
masami@saga:~$ sudo docker image ls
REPOSITORY                 TAG                 IMAGE ID            CREATED             SIZE
docker.io/arm64v8/fedora   latest              95cddd448075        4 weeks ago         290 MB
runtimejstest_web          latest              5cf57ccadd2f        4 weeks ago         675 MB
docker.io/node             8                   8198006b2b57        5 weeks ago         673 MB
docker.io/amazonlinux      latest              585cc50169e6        3 months ago        163 MB
alpine                     latest              3fd9065eaf02        9 months ago        4.15 MB
masami@saga:~$ sudo docker run -it docker.io/arm64v8/fedora /bin/bash
[root@54034b092275 /]# uname -a
Linux 54034b092275 4.19.0-rc7-test+ #102 SMP Mon Oct 8 11:06:09 JST 2018 aarch64 aarch64 aarch64 GNU/Linux

ホストでunameコマンド使ったらx86_64となります。

masami@saga:~$ uname -a
Linux saga 4.19.0-rc7-test+ #102 SMP Mon Oct 8 11:06:09 JST 2018 x86_64 x86_64 x86_64 GNU/Linux

クロスビルド環境の作成

では、本題のクロスビルド環境を作ってみます。今回はソースはホストで編集し、docker-compose upでmakeとmake testを動かすようにします。ソースはDockerfileが有るディレクトリにsrc/というディレクトリを作ってそこに置きましょう。

Dockerfileはこうなります。とりあえずCMDでmakeしないでbashを起動させるだけにします。

FROM docker.io/arm64v8/fedora

RUN mkdir /src && \
dnf install -y gcc make file

WORKDIR /src

CMD /bin/bash

docker-compose.ymlはこうなります。selinuxが有効なのでvolumesの時にzオプションを付けています。commandのところでCMDを上書きしてmakeコマンドを実行するようにしました。

version: '3'

services:
  builder:
    build: .
    image: aarch64-cross-builder
    hostname: fedora-aarch64
    volumes:
      - ./src:/src:z
    command: make all

実行

masami@saga:~/codes/arm-cross-build$ sudo docker-compose up
Creating arm-cross-build_builder_1 ... done
Attaching to arm-cross-build_builder_1
builder_1  | rm -f hello
builder_1  | cc hello.c -o hello
builder_1  | file ./hello
builder_1  | ./hello: 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]=39cbef1ba26dcae61413b891b9bd4e9d202a5083, not stripped
builder_1  | ./hello
builder_1  | Hello, World
arm-cross-build_builder_1 exited with code 0

まとめ

Fedora 29ならかなり簡単にクロスビルド環境を作ることが出来ますね( ´∀`)bグッ! qemuで完全なエミュレーションをしてももちろんOKですが、ユーザーランドのアプリならdockerでも良さげですね。

( ´ー`)フゥー...

ARMで学ぶ アセンブリ言語入門

ARMで学ぶ アセンブリ言語入門