Daniel Bank has been working with Snips offline machine learning stack and explains the ins and outs of cross compiling for a different architecture than you're machine.

Why Cross compile via @jacobRosenthal

We can technically compile just fine for rapsberry pi if we add the target: rustup target add armv7-unknown-linux-gnueabihf

But well get this error when we build for our target

$ cargo build --target armv7-unknown-linux-gnueabihf
   Compiling pi-example v0.1.0 (/Users/jacobrosenthal/Downloads/pi-example)
error: linker `arm-linux-gnueabihf-gcc` not found
  |
  = note: No such file or directory (os error 2)
error: aborting due to previous error
error: Could not compile `pi-example`.
To learn more, run the command again with --verbose.

So we need a linker, in this case its probably called something very near arm-linux-gnueabihf-gcc

These toolchains are generally very available for bare metal "no_std" cortex devices. You might remember from other workshops they just have us quickly install the toolchain as the first step

But were not targeting "no_std" raspberry pi, were targeting linux on top of pi, so we can use all the Rust "std" libraries.

As an aside, if you want to check out no_std raspberry pi stuff, I recommend Phillip Oppermans blog series which is basically a CS Degree in building an operating system from scratch on the rasperry pi

So if were in linux its probably actually not that hard to get the raspberry pi toolchain linker. Something like sudo apt-get install gcc-4.7-multilib-arm-linux-gnueabihf would probably work

Then create a .cargo/config file and add

[build]
target = "armv7-unknown-linux-gnueabihf"

[target.armv7-unknown-linux-gnueabihf]
linker = "arm-linux-gnueabihf-gcc-4.7"

and cargo build should work for you! Congrats you dont need cross (today).

But on Mac that toolchain is for some reason just not commonly hosted anywhere in brew etc. The best Ive found is this million page medium article Setup GCC 8.1 Cross Compiler Toolchain for Raspberry Pi 3 on macOS High Sierra

But you know whats better than doing all that yourself and polluting your machine? Having someone else do work for you and packaging it in a reusable cross platform way. Maybe with something like .. a docker container.. Enter Cross

Using Cross to cross compile via @danielbank

Setup

  • Install Docker

  • Add Rust targets

    rustup target add armv7-unknown-linux-gnueabihf # Pi
    rustup target add arm-unknown-linux-gnueabihf # Pi Zero
    rustup target list
    
  • Install cross

    cargo install --force --git https://github.com/rust-embedded/cross cross
    

Cross Compilation

  • Docker has to be running or you will get errors!

  • Go to the code directory you want to build

  • Build the code with cross

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

Common Reasons Your Build is Failing

  • Did you use cargo or cross? If cross compiling, you must use cross.

  • Did you specify a target? If you don't specify a target in the build command or haven't set it up in a .cargo/config, cross will just build for your local architecture.

  • Are you getting errors similar to the following?

    error: failed to load source for a dependency on \`tract-core\`
    

    I was able to resolve these errors by specifying a --manifest-path:

    cross build --target=armv7-unknown-linux-gnueabihf --manifest-path=examples/tensorflow-mobilenet-v2/Cargo.toml
    
  • Is there a supported Docker image for the target architecture? I noticed when trying to build for a Pi Zero that I couldn't find a Docker image for the arm-unknown-linux-gnueabihf target. In my case, someone published their own Docker image which I found from a GitHub Issue

    Unable to find image 'japaric/arm-unknown-linux-gnueabihf:latest' locally
    

My crate you should know is Rppal which has the fastest gpio access for raspberry pi

Theres a great blink example included

On your machine, assuming you have rust and cross installed lets make a new project with cargo new pi-example && cd pi-example

Then we have to add the rppal dependency to Cargo.toml like

[dependencies]
rppal = "0.11.3"

Now lets replace the src/main.rs with that example above. Ive put an led on our pi here on pin14 so change 23 to 14. This is agreat pinout site for raspberry pi

And were ready, compile with cross as daniel showed cross build --target armv7-unknown-linux-gnueabihf

Now, thanks to heatsync, andrew and @finkegabriel we have a pi cluster networked at Heatsync available at [email protected][1-8] (ie [email protected] ie [email protected]) with password raspberry

Now lets push our compiled executable over to a pi. Im going to use pinode1 and a tool called scp to send files over ssh to another device. Your compiled file is probably sitting at target/armv7-unknown-linux-gnueabihf/debug/pi-example so lets scp target/armv7-unknown-linux-gnueabihf/debug/pi-example [email protected]:/home/pi

And now lets ssh into our pi and run it like ssh [email protected] then ./pi-example

Now hopefully you can see your led blinking away. You can [ctrl-c] to kill the program and type 'exit' to get out of ssh back to your computer and make some changes. Can you blink at a different rate, a random rate, a sin wave so it looks like a heart beat? println! some stuff? Theres also i2c and many other protocols in the rppal library for you to try. Find some sensors and motors and other hardware.