This took me a while to figure out, so I’m putting this here to save someone some time! I wanted to cross-compile Rust programs on my Mac to run on a Raspberry Pi (Zero in this case, but that shouldn’t matter much).
The easiest way to do this is as follows:
- Install tools to generate binaries:
brew install arm-linux-gnueabihf-binutils(note, you do not actually need this if you follow the alternative route described below!)
- Install an ARM Rust toolchain:
rustup target add arm-unknown-linux-musleabi
- Configure Cargo to support ARM als a build target by creating a file
[target.arm-unknown-linux-musleabi] linker = "arm-linux-gnueabihf-ld" [target.x86_64-linux-musleabi] linker = "x86_64-linux-gnueabihf-ld"
4. Build by calling
cargo build --target=arm-unknown-linux-musleabi
The above configures Rust to generate armv6 binaries for Linux that are fully statically linked, making use of the musl standard library (which is a smaller and statically linked replacement of the GNU C/C++ standard library).
The above works fine for programs that are pure Rust. However many crates depend on C/C++ parts that are built during the build process. This fails on macOS, as there is no C compiler that compiles to ARM code on Linux. A typical error is
Internal error occurred: Failed to find tool. Is `arm-linux-musleabi-gcc` installed?
To fix, simply download an appropriate prebuilt musl cross-compilation toolchain from lisa.musl.cc. I used this one. Unpack it in (for example)
~/musl. Then, call cargo build with the musl binaries in the path:
PATH=$PATH:/Users/yourname/musl/arm-linux-musleabi-cross/bin cargo build --target=arm-unknown-linux-musleabi.
Note that you could theoretically replace ‘arm’ with ‘armhf’, ‘armel’, ‘armv7’, ‘aarch64’ to build code that is faster on newer Pi models. As far as I know however the standard ‘arm’ code runs fine on all Pi’s (except perhaps the Pi 4 which is 64 bit ARM or AArch64).