/rust_armv6

Compile rust code for the ARMv6 architecture from x86 with Docker

Primary LanguageDockerfileApache License 2.0Apache-2.0

ARMv6 Rust compilation image

Background

I was working on a DIY project and needed to compile some Rust code I wrote for a Raspberry Pi Zero W. There are plenty of blog posts and howto’s on the web about how to cross-compile Rust for the Pi but most of those resources are about newer Pi’s which have the ARMv7 (or v8) architecture (see Wikipedia for a list of which Pis are based on which ARM architecture). The Zero W (and Zero) are based on ARMv6, so it took a little extra Google-ing to figure out how to compile for that. And since I don’t really want to have a bunch of ARM packages installed on my own x86 laptop I put everything in a Docker image so it’s nice and isolated.

Thanks to Reddit user Arakvk33 on who’s post this image is mostly based.

Usage

The cmd in the Dockerfile is:

cargo build --release --target=arm-unknown-linux-gnueabihf

Cargo knows how to cross-compile to ARMv6, but we need the linker from the official Raspberry PI toolchain (installed in the image). To use it, make sure your project has a .cargo/config file with at least the following content:

[target.arm-unknown-linux-gnueabihf]
linker = "/rpi_tools/arm-bcm2708/arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc"

For Cargo to pick up on this config it needs to be in the working directory (inside the running docker container) where the command is run, so we need to run docker with the -w switch. We should also mount our local Cargo registry in the container (to avoid downloading the registry and all dependencies each time) and provide an environment flag that tells pkg-config it’s allowed to cross-compile. Also, for good measure, don’t run the container as root (so that root doesn’t own all the binaries that are produced) and also set the HOME environment variable to the working directory so Cargo doesn’t attempt to create files in the home of a non-existent (in the container at least) uid.

Putting that all together we get:

WORKDIR="/work"
docker run -t --rm \
       -u "$(id -u):$(id -g)"
       -e "HOME=${WORKDIR}"
       -e "PKG_CONFIG_ALLOW_CROSS=1"
       -w "${WORKDIR}"
       -v "$(pwd):${WORKDIR}"
       -v "${HOME}/.cargo/registry:/usr/local/cargo/registry"
       mdirkse/rust_armv6:latest

Copy and paste at will or use the script included with this repo.