I try to cross-compile a simple rust program with sqlite on Linux for raspberry pi:
Cargo.toml
...
[dependencies]
rusqlite = { version = "0.26.3", features = ["bundled"] }
.cargo/config
[target.arm-unknown-linux-gnueabihf]
linker = "/opt/crosspi/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc"
When trying to build with cargo build --release --target=arm-unknown-linux-gnueabihf
rust bails out with a linker error which basically says:
error: linking with `/opt/crosspi/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc` failed: exit status: 1
...
= note: /home/hannenz/pidev/projects/kiddyblaster/webui-rust/target/arm-unknown-linux-gnueabihf/release/deps/liblibsqlite3_sys-950993cbbcc1e3eb.rlib(sqlite3.o):(.data.rel.aSyscall+0x58): undefined reference to `fcntl64'
collect2: error: ld returned 1 exit status
(The ...
is the full gcc command line, i can post the whole output if relevant)
Without rusqlite cross-compiling works and compiling for the host target is working as well. I also tried the sqlite
crate instead of rusqlite
, but that produces the exact same linker error.
Would be glad if someone could point me in the right direction what's goiong wrong here.
Cross compiling can be a bit tricky, luckily the cross crate (https://github.com/cross-rs/cross) makes it simple. Follow these steps:
cargo install cross
Cross.toml
in the root directory (where Cargo.toml is) with this contentBuild the docker container:
docker buildx build --platform linux/arm64 -t my-custom-cross --load .
Build your program:
cross build --target aarch64-unknown-linux-gnu --release
Now you have your binary compiled at
target/aarch64-unknown-linux-gnu/release
directoryA bit of explanation
The project
cross-rs
prepared all the environment and put it in a docker container. We created our own container based on this (FROM rustembedded/cross:aarch64-unknown-linux-gnu
) and we added the extra libraries we need, in this case the dev sqlite3 (apt-get install --assume-yes libsqlite3-dev:arm64
).Once our docker container is ready, we configured
cross
to use this container by using the fileCross.toml
.Depending on your raspberry and the operating system you use in your raspberry, you may need to use other arquitecture. In this case just change
aarch64
by yours. In my case I'm using rpi3 64 bit. In case you are using 32 bit or an older board, try something likearm-unknown-linux-gnueabihf
or go to the "Supported targets" section in the cross documentation https://github.com/cross-rs/cross.Dont forget to configure
Cross.toml
and the Dockerfile to use your target architecture!