SOLVED: I should have put the linker in .cargo/config.toml, not Cargo.toml. See followup blog post.

This is not the right way to do it, as will become abundantly clear. But it works.

Set up build environment

rustup toolchain install nightly
rustup component add rust-src --toolchain nightly
apt install {binutils,gcc}-mips-linux-gnu

Create test project

cargo new foo
cd foo

Build most of it

This will build for a while, then fail.

cargo +nightly build --release -Zbuild-std --target mips-unknown-linux-gnu

For some reason it’s trying to use cc to link. I tried putting this in Cargo.toml, but it does nothing:

[target.mips-unknown-linux-gnu]
linker = "mips-linux-gnu-gcc"

But I found a workaround.

Temporarily change /usr/bin/cc to point to the mips gcc

It does not work if you do this before the previous step.

PREV="$(readlink -v /usr/bin/cc)"
sudo rm /usr/bin/cc
sudo ln -s /usr/bin/mips-linux-gnu-gcc /usr/bin/cc

Same command again

cargo +nightly build --release -Zbuild-std --target mips-unknown-linux-gnu

It should succeed. Yay.

Restore /usr/bin/cc

sudo rm /usr/bin/cc
sudo ln -s "${PREV?}" /usr/bin/cc

Change the “interpreter” to what the Ubiquiti system expects

cd target/mips-unknown-linux-gnu/release
patchelf --remove-needed ld.so.1 foo
patchelf --set-interpreter /lib/ld-musl-mips-sf.so.1 foo

Building it again

Probably easiest to rm -fr target, and go back to the step “Build most of it”.

Does it work?

$ ./foo
Hello, world!

Yay!

  • https://doc.rust-lang.org/rustc/targets/custom.html