I want to cross-compile my Rust application on macOS to a Raspberry Pi 2. I searched a lot, but did not find a working solution. The last solution I tried was following this answer, but I couldn't get it to work.
What I did:
Created .cargo/config
file in the root of my project with following content
[target.armv-unknown-linux-gnueabihf]
linker = "/Users/user/Documents/Programming/RustProjects/hello-pi/../../Utils/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf-gcc"
Then I run cargo build --target=arm-unknown-linux-gnueabihf
I get the following error:
linking with /Users/user/Documents/Programming/RustProjects/hello-pi/../../Utils/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf-gcc failed: exit code: 126
....
cannot execute binary file
It seems that I cannot run the ...gcc
binary on my macOS machine. What would be the right way to cross-compile my Rust application from macOS to the ARM architecture for a Raspberry Pi 2?
rust-std
library relies on glibc
for things like syscalls
and other low-level stuff, in order to cross-compile a Rust binary, one needs the appropriate C toolchain to be present as well. And this is where crosstool-NG comes into play.
crosstool-NG
is in the toolchain building business. You’re going to use it to build yourself a toolchain for linking against ARMv7-compatible glibc
, which will in turn allow you to successfully build your Rust binary for the Pi.
cd /Users/USER
git clone https://github.com/crosstool-ng/crosstool-ng
cd crosstool-ng
./bootstrap
./configure --prefix=$PWD
make
make install
export PATH="${PATH}:${PWD}/bin"
If all things went as expected, you should be able to run ct-ng version
and verify the tool’s ready to go.
ARMv7 toolchain
. Luckily, crosstool-NG comes with some preset configurations, namely armv7-rpi2-linux-gnueabihf
. Run:ct-ng armv7-rpi2-linux-gnueabihf
There should be some output indicating that it’s now configured for armv7-rpi2-linux-gnueabihf
. You just need to tell ct-ng where the toolchain ought to go:
mkdir /Users/USER/ct-ng-toolchains
cd /Users/USER/ct-ng-toolchains
ct-ng menuconfig
It can be overwhelming, as there are a ton of options, but stick to the Paths and misc options ---> menu option
. Highlight it and hit Enter.
Under *** crosstool-NG behavior ***
, scroll down until you see this long string:
(${CT_PREFIX:-${HOME}/x-tools}/${CT_HOST:+HOST-${CT_HOST}/}${CT_TARGET}) Prefix directory
- Hit Enter, delete the contents, and replace it with /Users/USER/ct-ng-toolchains
.
- When you’re finished, hit Enter to confirm, scroll over and save, and then exit the configurator.
ct-ng build
If it worked successfully, You should see a great many binaries now in /Users/USER/ct-ng-toolchains/armv7-rpi2-linux-gnueabihf/bin
, namely armv7-rpi2-linux-gnueabihf-gcc
.
For cargo to build using your new cross-compiler, you must:
export PATH="${PATH}:/Users/USER/ct-ng-toolchains/armv7-rpi2-linux-gnueabihf/bin"
/Users/USER/.cargo/config
file with (you can avoid this and use it in local .cargo/config
):[target.armv7-unknown-linux-gnueabihf]
linker = "armv7-rpi2-linux-gnueabihf-gcc"
3.Return to your Rust project and rerun cargo build:
cd /Users/USER/rust/hello
cargo build --target=armv7-unknown-linux-gnueabihf
Compiling hello v0.1.0 (file:///Users/USER/rust/hello)
Finished dev [unoptimized + debuginfo] target(s) in 0.85 secs
scp target/armv7-unknown-linux-gnueabihf/debug/hello [email protected]:
ssh [email protected] 'chmod +x ~/hello && ~/hello'
Hello, world!
Credit goes to Kappel Codes I tried to summarize it here, as I found this question hours before I get that article :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With