Cross Compiling Rust to Your Pi
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
orcross
? If cross compiling, you must usecross
. -
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 IssueUnable to find image 'japaric/arm-unknown-linux-gnueabihf:latest' locally
Hands on: blink an led on a raspberry pi via @jacobRosenthal
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 pi@pinode[1-8] (ie pi@pinode1 ie pi@pinode2) 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.