Cross compilation

The goal is to run the aggregator on our routers. Therefore, we need to cross-compile it for the target architecture.

1 The simple case

Often, the target architecture will be directly supported by an existing rustc target. This is the case of the Turris Omnia router (with the downside of being statically linked, therefore creating a slightly larger binary). In the case of the Omnia router, the target name is armv7-unknown-linux-musleabihf, for other targets pick one appropriate.

The process assumes the rust compiler to be installed by rustup. We simply ask rustup to install base libraries for the target and let the compiler do the magic.

rustup target add armv7-unknown-linux-musleabihf
cargo build --release --target armv7-unknown-linux-musleabihf

Then, the binary target/armv7-unknown-linux-musleabihf/release/pakon-aggregator is the thing that can run on the router.

2 The hard way

It is possible to compile for whatever linux-based system provided a C cross-compiler is available and LLVM can generate code for the given compiler. It however needs some more work.

We'll need these ingredients:

Now, we'll do few things.

2.1 Quirks

Cross-compilation is tricky business. Therefore, each target usually needs a trick or two.

2.2 The blue Turris

Currently, the old Turris router uses uclibc. We could define a new target for it and do the full hard way process, maybe even needing to provide support for uclibc in some of the core rust libraries. But it seems uclibc and glibc are API-level compatible. Therefore, we can abuse the powerpc-unknown-linux-gnu target and skip writing the target specification. However, we still need to do the xargo build as uclibc is not ABI compatible. Do not download the target libraries through rustup. When we link the rust libraries against uclibc instead of glibc ourselves (through xargo), it seems to work.

We still may want to go the proper way and define a new target specification in the future, just to make sure.

This is what the Makefile in the top-level directory does (with some small workaround).

2.3 Omnia

There's a slight problem. Rust's musl targets are fully statically linked. If the size of the binary is a concern, it is possible to define a custom target that links to musl dynamically. This is a bit tricky, though, as this is not very well supported yet.

There's a working prototype for cross-compiling a dynamically-allocated musl application for Omnia at https://gitlab.labs.nic.cz/mvaner/xcompile. It's only a hello-world application, but it should be applicable to the aggregator as well. The cross-compilation is run by the build script.

2.4 The nix dependency

The nix crate, which is depended on by some of our dependencies (AFAIK something of logging) had a bug which prevented it from working on powerpc. The Cargo.toml currently replaces the dependency with a fixed version. We may drop the replacement once the newest version is used by the other dependencies.

The other option is stripping down and migrating from slog to the basic log crate. This means less fancy log output, but also smaller binary output, so it might be worth it.