As part of my adventures in cross-compilation using Zig, I've been using QEMU extensively to test cross-compiled binaries. One issue I ran into is this:
$ zig cc -target aarch64-linux-gnu main.c
$ wsl qemu-aarch64 ./a.out
/lib/ld-linux-aarch64.so.1: No such file or directory
This stems from the fact that a.out
is a dynamically-linked executable (note the -gnu
rather than -musl
). It cannot be loaded without the dynamic linker for aarch64
being present.
It turns out that it's possible to install the dynamic linker (or, to be precise, the glibc) for other architectures. The process is not documented very well, unfortunately. I'll describe the steps I followed below.
First, run the following:
# dpkg --add-architecture arm64
You'll need to modify your /etc/apt/sources.list
(or files in /etc/apt/sources.list.d
depending on how you've organized things). In my case, it looked like this:
deb http://archive.ubuntu.com/ubuntu groovy main multiverse restricted universe
deb http://archive.ubuntu.com/ubuntu groovy-backports main multiverse restricted universe
deb http://archive.ubuntu.com/ubuntu groovy-updates main multiverse restricted universe
deb http://security.ubuntu.com/ubuntu groovy-security main multiverse restricted universe
These repositories don't actually have an arm64
port. So you'll need to decorate them like so:
deb [arch=amd64] http://archive.ubuntu.com/ubuntu groovy main multiverse restricted universe
deb [arch=amd64] http://archive.ubuntu.com/ubuntu groovy-backports main multiverse restricted universe
deb [arch=amd64] http://security.ubuntu.com/ubuntu groovy-security main multiverse restricted universe
deb [arch=amd64] http://archive.ubuntu.com/ubuntu groovy-updates main multiverse restricted universe
This informs apt
not to fetch from these repositories for architectures other than amd64
.
Before saving, you'll also need to add the actual arm64
repositories to the file:
deb [arch=arm64] http://ports.ubuntu.com groovy main multiverse restricted universe
deb [arch=arm64] http://ports.ubuntu.com groovy-backports main multiverse restricted universe
deb [arch=arm64] http://ports.ubuntu.com groovy-security main multiverse restricted universe
deb [arch=arm64] http://ports.ubuntu.com groovy-updates main multiverse restricted universe
Make sure everything's updated:
# apt update && apt full-upgrade
You can now install glibc:
# apt install libc6:arm64
Finally, run the foreign executable:
$ wsl qemu-aarch64 ./a.out
Hello World
Note: If you're like me and also care about armhf
, you can change the [arch=arm64]
to [arch=arm64,armhf]
in your /etc/apt/sources.list
and repeat all the other steps, replacing arm64
with armhf
. The same is true for ppc64el
, riscv64
, and s390x
.