Cross compiling rust applications for R-01 module

I tried to build a couple command line tools for the DevTerm – applications like a matrix client (iamb) and an email client (meli). Naive attempts at building these on the device were very slow due to the limited performance of the single core CPU and eventually failed due to memory pressure (OOMKiller killed rustc during linking).

So I looked into cross compiling. My host system runs POP! OS (an Ubuntu derivative), 8 core i7 and 32GB of RAM. The major source for setting up the host system was a detailed blog post about cross compiling rust.

The condensed how-to is as follows:

a) install gcc-riscv64-linux-gnu and gcc-riscv64-unknown-elf packages. These will pull in a number of dependencies.
b) remove the rustc dpkg should you have installed it.
c) re-install rust using rustup
d) add the riscv64 target to rust: rustup target add riscv64gc-unknown-linux-gnu
e) check out your favorite rust repository
f) in the build root of that repo, create .cargo/config.toml if it doesn’t yet exist, and add the following sections

target = "riscv64gc-unknown-linux-gnu"

rustflags = ["-C", "target-feature=+crt-static"]
linker = "riscv64-linux-gnu-gcc"

I had to change the linker to riscv64-linux-gnu-cc on my install, which is different to the blogpost I cribbed from, and I decided to take the static build option because that allows me to copy over a single binary to run on the DevTerm without worrying about libraries. The binary is usually inside the target/riscv64gc-unknown-linux-gnu/release/ directory, assuming you build with cargo build --release or similar.

I hope this helps someone. Let me close by saying I should not have wasted half a weekend trying to build locally and embraced cross-compiling from the get-go.


Why don’t you setup Ubuntu 22.04 riscv64 qemu image and run it on some powerful hardware ? You can define whatever memory you need there.

1 Like

Compiling in QEMU VMs is usually slower than using a cross toolchain directly on a powerful machine due to the translation overhead. The advantage is that you can properly build dynamically-linked executables without hacks in VMs, and the executables might consume less memory than the statically-linked ones.

@astr0 I am usually looking for the ‘least effort to get to the goal’ solution first, and only go further when needed. My least-effort approach fails for some things, especially those that require sys-openssl, where a build VM may be easier than trying to suss out what needs to go into a sysroot and where to point rustc for the openssl includes.

1 Like

There are no hacks in VMs - riscv64 Ubuntu 22.04 runs really well under qemu-system-riscv64. One huge advantage of this solution is you dont pollute your host system with unnecessary libs and toolchains.

1 Like

Ubuntu has a good support for riscv64 in qemu RISC-V/QEMU - Ubuntu Wiki

1 Like

that’s what @hyperyay said.

I am currently running a comparison between building in a RISC-V VM running on QEMU and cross compiling natively. I will share some numbers later.


You have a point. And that’s why I use chroot(any distro) or nix-shell to create an isolated environment(not full but enough) when I have to mess with the environment. I’ve written a few scripts specifically for preparing this kind of environments. :grinning:

BTW using kernel’s BINFMT_MISC feature and QEMU user mode emulation, a chroot can also work like a VM.

1 Like

OK, so with the naive approach, building a somewhat featureful application (download - meli MUA) on my Core i7 laptop with 8 cores and 32GB RAM took between 3:22min and 4:08min. Running a RISC-V VM with 4 cores and 16GB RAM, the same build took 88min while the machine was left sitting idle otherwise (still about 10 times faster than the R-01, which eventually fails due to the RAM situation). Unless required due to the sysroot/pkg-config errors, I’ll prefer cross compiling any day of the week.

I am sure that the performance of the QEMU could be increased to some extent one way or the other, but following just the standard setup instructions, this is what you get.

Thanks for testing the scenario - cross-compilation is faster, this is expected. When I was bootstrapping pkgsrc in qemu-system-riscv64 it took 40 minutes compared to 60 minutes on the actual R01

  • cargo install cross
  • cross build --target=riscv64gc-unknown-linux-gnu

that’s all fine and dandy, but a) it requires docker or podman – yet another indirection – and b) it does not solve the problem with building openssl-sys.

1 Like