Rust is a great tool because it allows compiling native code. This means you do not need to have a runtime installed on a target machine, but it does mean that you need to compile the program targeted for the hardware you expect it to run on ahead of time. Given the strength of not needing a runtime, I wanted to use Rust to compile some small executables for my Synology DS418j.
Rust has a good set of tools already to cross compile programs for a number of platforms.
Assuming that you use rustup
command (which is the recommended way), the default target
installed when you install Rust is the one that matches your platform. You can see a list
of already built targets by running rustup target list
.
The first step towards figuring out what I needed to target was determining the architecture that my NAS is running. I have the DS418j, which I know
is one that doesn't have one of the fancy Intel processors, and is likely a cheaper ARM processor.
After ssh'ing into the machine I was able to get this info by running uname -a
on the NAS to get the following output:
Linux potabo 4.4.59+ #25556 SMP Thu Mar 4 17:52:53 CST 2021 aarch64 GNU/Linux synology_rtd1296_ds418j
The notable piece of information for me was the aarch64
.
Looking at the list of targets available from rustup
, the one
that most closely matches is aarch64-unknown-linux-gnu
.
The breakdown of these targets is <architecture>-<vendor>-<system>-<abi>
.
If you don't already have a project to compile then running cargo new <executable name>
will scaffold out the folder for you.
We need to install some dependencies first in order to compile.
First, we need to get the base rust crates to compile our project against. This is done with rustup
:
$ rustup target add aarch64-unknown-linux-gnu
This installs the crates into your dev environment allowing you to use this as a target across any project.
Second, we'll need to install the gcc
tools to be able to have a linker that will link our binaries to the ones we expect to be on the target system. The real simple way to do this is installing all gcc-aarch64 tools with the following:
$ sudo apt-get install gcc-aarch64*
Now, the environment is all prepped.
The Rust project still needs a bit more information in order to find the right linker to use for the given target.
This is done through a cargo config file.
From the root of the Rust project you can create a .cargo
folder, and a config
file within it.
In the config file the following block needs to be added to tell cargo to use the specified linker when compiling for the given target:
[target.aarch64-unknown-linux-gnu]
linker = "aarch64-linux-gnu-gcc"
Finally, the project is ready to compile
$ cargo build --target=aarch64-unknown-linux-gnu
After building you can copy the created binary from the target/aarch64-unknown-linux-gnu/debug
folder to the target machine and run it to verify it works!
Reach out if you have any questions, comments, thoughts!