# Cross compile Rust to your Raspberry Pi

## Who is this for?

If you want to get started with ...

• ...cross compiling code for your Pi,
• ...packaging your programs in .deb archives,
• ...all of the above

then this guide is for you. This post serves as a starting point for your endeavours, so instead of going too much in depth, I will try to point you in the right direction.

## Getting started

In this guide I assume that you already have rust and cargo installed. On top of those, I will use cross and cargo-deb.

## Cross compilation

For cross compilation, I recommend the cross tool for cargo. Note that it relies on Docker being installed.

cargo install cross


Once it's installed, it's very easy to cross compile to a wide range of architectures. One thing thing to keep in mind is that it can be very tricky to cross-compile code (or dependencies) that bind to C code. Cross describes how to produce your own Dockerfile, but I found it fairly difficult to get this to run at all, let alone smoothly. Pure Rust projects work very well, though.

### Raspberry Pi 1 and Zero

cross build --release --target arm-unknown-linux-gnueabihf


If you prefer to create statically linked executables, use arm-unknown-linux-musleabihf instead.

### Raspberry Pi 2, 3, and 4

cross build --release --target armv7-unknown-linux-gnueabihf


Again, if you prefer to create statically linked executables, use armv7-unknown-linux-musleabihf instead.

## Create a deb package

I recommend using cargo-deb.

cargo install cargo-deb


Before running any of the following commands, make sure that your code has already been built. This is because cargo-deb defaults to using cargo instead of cross for compilation.

### Raspberry Pi 1 and Zero

cargo deb --no-build --target arm-unknown-linux-musleabihf


### Raspberry Pi 2, 3, and 4

cargo deb --no-build --target armv7-unknown-linux-gnueabihf


Note that this creates a bare-bones archive. You can find more information on this here.

## Launch on boot

The easiest way to get your service up and running at boot is to create a systemd.service file (or a service unit configuration file).

If you're installing your service with a deb file (as described above), and you went with the minimal approach described here, then your executable(s) will be installed in /usr/bin by default. You will probably also want the network to already be available when your program starts. Based on these assumptions, here's what a basic unit could look like:

Store this file in your project under assets/my-awesome-service.service.

[Unit]
Description=My awesome service
After=network.target

[Service]
ExecStart=/usr/bin/my-awesome-service
WorkingDirectory=/home/pi/
StandardOutput=inherit
StandardError=inherit
Restart=always
User=pi

[Install]
WantedBy=multi-user.target


To add it to your deb archive, you'll want to edit your Cargo.toml file, and add an asset under [package.metadata.deb].

[package.metadata.deb]
assets = [
["assets/my-awesome-service.service", "etc/systemd/system/", "755"],
]


(If that didn't make sense, you'll want to look at cargo-deb's configuration).

Once this is installed, you should now be able to monitor your service using systemd's service command.

sudo service my-awesome-service start
sudo service my-awesome-service status
sudo service my-awesome-service stop


Note that the executable will run as the pi user, and use /home/pi as its working directory. This might not be right for you. If you want to do this right, you'll probably want to useradd -r a system account, and giving it as few privileges as possible, as well as a place to store configurations under /etc/my-awesome-service. You may also want to store its logs under /var/log/my-awesome-service/main.log, which you of course want to rotate, etc. This post isn't really about any that, though. It's just about getting you started :)

Good luck!