I really enjoy writing Rust, I own a growing number of Raspberry PIs. The RPI4 is a big step forward in terms of hardware resources on the platform. It is however 64bit not 32 like its predecessors and requires a different tool chain for cross compilation. In this guide I will take you through the setup. If you just want something that works now, you can use the
albeego/rust-musl-builder-aarch64:0.0.1 docker image.
docker run --rm -it -v "$(pwd)":/home/rust/src albeego/rust-musl-builder:0.0.1 cargo build --release --target=aarch64-unknown-linux-gnu
We’re going to need some packages for this, the following apt command will pull them all in:
apt install -y \ build-essential \ libssl-dev \ linux-libc-dev \ gcc-aarch64-linux-gnu \ software-properties-common \ crossbuild-essential-arm64
A note here on linking, you will need to tell rust to use
/usr/bin/aarch64-linux-gnu-gcc as the linker for the rust applications you compile. You can do this by including a
.cargo/config file in your
$HOME directory, the project directory with the following contents
[target.aarch64-unknown-linux-gnu] linker = "aarch64-linux-gnu-gcc"
Now you need to let rust know about your cross compilation target. You do this by adding the target to rustup:
rustup target add aarch64-unknown-linux-gnu
That’s it for the tool chain
One of the challenges with cross compiling rust applications is getting the dependencies correct for the build. Open SSL is pretty prevalent and if you are going to do anything web related, you will need it. This cannot be the pre-compiled Open SSL binaries that come with your OS, you need to produce a cross compiled binary for linking with your rust application. You don’t want to overwrite that pre-compile binary that came with your OS either. That would cause other issues! So, let’s make a place to store the cross compiled Open SSL binary and its source and open it in our terminal
mkdir /build cd /build
Grab the Open SSL source from the GitHub release and extract it (1_0_2r) at the time of writing
curl -LO "https://github.com/openssl/openssl/archive/OpenSSL_1_0_2r.tar.gz" tar xvzf "OpenSSL_1_0_2r.tar.gz cd "openssl-OpenSSL_1_0_2r"
Now we are ready to build Open SSL, we will configure it without ZLib (we need to provide our own cross compiled ZLib to consumers anyway), it needs to be non shared so we are not linking any of our x86_64 objects, position independent in memory and installed to a custom location
./Configure no-shared \ no-zlib \ -fPIC \ --prefix=/build/openssl-OpenSSL_1_0_2r/target \ --cross-compile-prefix=aarch64-linux-gnu- \ linux-aarch64
That’s the build setup, now run it to produce the binary in
make depend make sudo make install
We will need to do something similar with the compression library ZLib, again, if you are doing anything web related, you can’t avoid it. Lets keep everything together and drop the source code in to our
cd /build ZLIB_VERSION=1.2.11 curl -LO "http://zlib.net/zlib-1.2.11.tar.gz" tar xzf "zlib-1.2.11.tar.gz" cd "zlib-1.2.11"
and for the build (making sure we use out aarch64 compiler)
CC=aarch64-linux-gnu-gcc ./configure --static make sudo make install
Running the builds
You will need to pass a few signals over to rust to let it know where your pre-compiled binaries are and how to use them. After that it is simply a case of doing a cargo build with the target architecture specified
OPENSSL_DIR=/build/openssl-OpenSSL_$OPENSSL_VERSION/target \ PKG_CONFIG_ALLOW_CROSS=true \ LIBZ_SYS_STATIC=1 \ CC="aarch64-linux-gnu-gcc -static -Os" \ cargo build --release --target=aarch64-unknown-linux-gnu
Please let me know in the comments if you get any issues. I may have seen them and may be able to help!
I’d like to give a special mention to Eric Kidd from Vermont USA on this one. His repository here https://github.com/emk/rust-musl-builder formed the basis on which I did a lot of this work