Cross-compile for Raspberry Pi with Docker

I am a lazy person so I've been really just compiling the code I want to run on Raspberry Pi ... well, on Raspberry Pi. It was slow but it is super simple to setup. However, sometimes you just want to compile something larger than the Raspberry Pi can handle. What now?

The first thing my lazy butt tried is to simply run a ARMv7 image using qemu-system-arm but that sadly is very slow on my computer due to emulating a different architecture altogether. I was also too lazy to setup a proper buildroot with all the toolchains and libraries properly cross-compiled for the ARMv7 architecture.

I decided to give another approach a try: using qemu user-mode emulation to run ARMv7 userspace directly and to wrap it in docker so I don't need to worry about messing my system up. We should be able to get near full-speed with this method.

Fortunately, someone already published an ARMv7 docker image agners/archlinuxarm-arm32v7. We just need to get our system to run ARMv7 file now. To do this, we need to install binfmt-qemu-static from AUR. This enables your system to run ELF files from other architecture.

If you just start running the container at this point on, you will run into this weird problem:

[root@f19789b92d0d code]# cargo build
    Updating crates.io index
warning: spurious network error (2 tries remaining): could not read directory '/root/.cargo/registry/index/github.com-1285ae84e5963aae/.git//refs': Value too large for defined data type; class=Os (2)
warning: spurious network error (1 tries remaining): could not read directory '/root/.cargo/registry/index/github.com-1285ae84e5963aae/.git//refs': Value too large for defined data type; class=Os (2)

Value too large... for wat? I didn't read into what exactly caused this but someone hypothysize that it could be filesystem compatibility between 32-bit/64-bit (ARMv7 is 32-bit and my PC is 64-bit. If you run the ARM64v8 image than it should just work) systems so we need to mount a filesystem that works on a 32-bit system. I've tried using mkfs.ext4 -O^64bit and even mkfs.ext3 but they all still produce the same problem. I decided to try another filesystem altoghter and JFS works!

To create a JFS image, you can run:

fallocate -l 4G disk.img
sudo mkfs.jfs disk.img

and than you can run this to mount it:

mkdir mnt
mount -o loop disk.img mnt

That's it! Once you have that JFS filesystem setup, you can run this command to run ARMv7 Arch Linux in docker and compile whatever you need!

docker run -it --rm -v $PWD/mnt:/work agners/archlinuxarm-arm32v7