Here’s a practical, no-drama way to cross-compile Rust for Raspberry Pi with Cargo. Pick ONE of the three methods below; Method A is the simplest.
A) Easiest: cross (Docker-based)
# 1) Install
cargo install cross
rustup target add aarch64-unknown-linux-gnu # 64-bit Pi OS
rustup target add armv7-unknown-linux-gnueabihf # 32-bit Pi 2/3/4 OS
rustup target add arm-unknown-linux-gnueabihf # ARMv6 (Pi Zero/1)
# 2) Build
cross build --target aarch64-unknown-linux-gnu --release
# or: cross build --target armv7-unknown-linux-gnueabihf --release
# or: cross build --target arm-unknown-linux-gnueabihf --release
# 3) Copy & run on the Pi
scp target//release/yourapp pi@raspberrypi.local:/home/pi/
ssh pi@raspberrypi.local ./yourapp
cross bundles the right GCC/linkers in Docker images, so you avoid toolchain setup pain. Great if your project pulls C libraries.
B) Native toolchains + Cargo (no Docker)
- Install cross GCC/linker on your dev machine
Ubuntu/Debian:
sudo apt-get update
sudo apt-get install gcc-aarch64-linux-gnu gcc-arm-linux-gnueabihf
macOS (Homebrew):
brew tap messense/macos-cross-toolchains
brew install aarch64-linux-gnu-gcc arm-linux-gnueabihf-gcc
- Add Rust targets
rustup target add aarch64-unknown-linux-gnu
rustup target add armv7-unknown-linux-gnueabihf
rustup target add arm-unknown-linux-gnueabihf
- Tell Cargo which linker to use (.cargo/config.toml at workspace root)
[target.aarch64-unknown-linux-gnu]
linker = "aarch64-linux-gnu-gcc"
[target.armv7-unknown-linux-gnueabihf]
linker = "arm-linux-gnueabihf-gcc"
[target.arm-unknown-linux-gnueabihf]
linker = "arm-linux-gnueabihf-gcc"
# (Pi Zero/1 may need: rustflags = ["-C", "target-cpu=arm1176jzf-s"])
- Build
cargo build --target=aarch64-unknown-linux-gnu --release
C) “It just works” linker: cargo-zigbuild
If you can install Zig:
cargo install cargo-zigbuild
rustup target add aarch64-unknown-linux-gnu
cargo zigbuild --target aarch64-unknown-linux-gnu --release
Zig handles cross-linking without extra GCC toolchains.
Pick the correct target
The target depends on the OS architecture, not just the board. uname -m on the Pi: aarch64 → 64-bit, armv7l/armv6l → 32-bit.
Dealing with native C deps (OpenSSL, SDL, etc.)
- On the Pi, install dev packages (sudo apt-get install libssl-dev, etc.).
- When cross-compiling without cross/zigbuild, you may need:
export PKG_CONFIG_ALLOW_CROSS=1
export PKG_CONFIG_LIBDIR=/usr//lib/pkgconfig
export PKG_CONFIG_SYSROOT_DIR=/
- If it’s painful, build those crates on the Pi once, or switch to Method A/C.
Sanity checks
file target/aarch64-unknown-linux-gnu/release/yourapp
# Expect: ELF 64-bit LSB executable, ARM aarch64, ...