Cross Compiling Rust for the Raspberry Pi
Published on 2024-11-01
To get this blog up and running I had to endure the horrors of cross-compiling Rust. I currently use a MacBook Air that I do most of my programming on. This blog is simply a Cargo project that I compile and rsync over to my Raspberry Pi to run. The issue of course is that compiling the Rust binary on my MacBook means cross compilation. Here’s a detailed outline of the steps I took to get this working to save future people pain.
Specs
Technology is always changing and both MacBooks and Raspberry Pis will both continue to update. Here are the exact tech specs I’m working with. If yours are different you may have to adapt these instructions.
I’m working on a 2020 M1 MacBook Air. The Raspberry Pi is a gen 4 Model B Rev 1.4.
Install musl-cross
This Homebrew formula contains a ton of cross-compilation tools for every architecture under the sun. I originally installed it to cross-compile Golang projects that relied on cgo for a x86_64 Linux server but it had the required tools to also compile Rust for a Raspberry Pi.
Install Rust std lib
Next you’ll need the Rust standard library for the Raspberry Pi. If
you’re using Rust you should have rustup installed. Run
rustup target add aarch64-unknown-linux-musl
to add the std
lib for the Raspberry Pi.
Side note here, from my limited understanding it seems like both arm and aarch64 can run on the RPi but arm is 32 bits while aarch64 is 64 bits as the name implies. Not completely sure about this though.
Add the linker for the target
While it doesn’t seem like you need to specify CC
, you
do need a linker. Create a file at .cargo/config.toml
and
put the following config options into it to specify the linker for the
aarch64-unknown-linux-musl
target we’ll be using.
[target.aarch64-unknown-linux-musl]
linker = "aarch64-linux-musl-ld"
This part tripped me up because I assumed that this must be an older
way of configuring Cargo because everyone knows config options go in the
Cargo.toml
file right? Wrong. Apparently the
Cargo.toml
and .cargo/config.toml
both serve
different functions as shown by the docs here,
and here,
respectively.
Compiling
Now we can cross-compile our project with the command
cargo build --release --target=aarch64-unknown-linux-musl
.
One weird bug I haven’t quite ironed out yet is that if I run that shell
command directly on the command line it compiles correctly but if I run
it from a Makefile then it throws a weird error while compiling a
sqlx
macro. I’ll update this blog if I figure out why that
is.