I need to cross-compile a complex project (from x86-64 to aarch64, both on Debian). My project doesn't fit existing tools like cross, so I would like to learn how to do the cross-compilation "the hard way" so that I can make it build myself.
Can you recommend an extensive guide for this?
I've searched for guides, but all I find falls into one of two categories:
"How to draw an Owl meme". They say "Just run rustup target …and then solve the remaining thousand build errors yourself."
or "Here, run my Docker black-box". That's underwhelming. It doesn't teach me anything, and I'd rather not have to reverse-engineer that knowledge from someone else's sparsely-commented patched-up implementation.
I had to do sudo apt install libc6-arm64-cross gcc-aarch64-linux-gnu. I also did sudo apt install libc6-dev-arm64-cross, but I am not sure if that was necessary. Then I did rustup target add aarch64-unknown-linux-gnu. That worked for simple projects at least. You many need to install the aarch64 version of the libraries you depend on though. I think that would be sudo dpkg --add-architecture aarch64 and then sudo apt install libfoo-dev:aarch64.
Tools like cross have thousands of lines of code, so what you describe here is clearly not enough. I'm afraid this problem is a topic for a book, rather than something that could be answered in a single forum post.
I'm struggling, because I find a lot of variations of what you've posted, but that is only enough for a "hello world" project. When I need to compile hundreds of dependencies, including big C libraries and things that depend on the kernel or a different libc implementation, I'm stuck in the void between "use rustup and apt" (which is too little) and "give up, there is no documentation for these problems, just use someone's Docker image".
rust-cross is a fairly detailed guide, though many steps depend on both the host platform and target platform, and no guide can cover all of the possible host/target pairs. It does explain the various moving parts, with complete examples for some specific targets.
For things like C dependencies, Rust guides can't really help and you either need to dive into the build system of each particular C library or hope that someone else has already done so and produced a useful cross-compilation-friendly build script. I had to do a lot of this while working on Servo, and it was mostly just a bit of tedious work for each individual C library.
For the basic step, rustup target add will indeed very often be quite insufficient, given how usually one needs to also override the linker Configuration - The Cargo Book with that of the "apt-installed" platfor-specific toolchain.
This very simply added step may already solve most of the errors that arise when not using it.
For instance, when cross compiling to musl from OS X, doing
rustup target add x86_64-unknown-linux-musl
will usually not be enough, requiring to also add the raw musl toolchain:
brew install filosottile/musl-cross/musl-cross
and then telling Cargo to use it, by having the linker for the x86_64-unknown-linux-musl target be the (now present) x86_64-linux-musl-gcc binary.