One Go feature which I’m using regularly is cross-compiling Go code to other platforms (usually from macOS to linux-amd64).
In Go, this is a built-in feature that “just works”. The following command produces a statically linked ELF binary which can simply be copied and run on a Linux machine:
1 2 3 | |
Rust doesn’t have built-in support for such a feature.
Edit: Rust core-commiter Steve Klabnik pointed out, that actually what I’m showing off here is the built-in Rust support :)
I’ve been looking for a while how to achieve this using Cargo and Rust. And (spoiler-alert!) I’ve found one, which is relatively simple to set up.
Assuming you have rustup and Homebrew installed, it’s actually quite simple to setup cross-compiling on macOS!
First, install Rust nightly. I haven’t tried whether this works on Rust stable, so let me know if you happen to try it.
1
| |
Second, install the required target. In our case (Linux x86_64) this is x86_64-unknown-linux-musl. The lightweight standard library musl is able to produce statically linked libraries (contrary to the x86_64-unknown-linux-gnu target, which uses GNU libc.
1
| |
What’s still missing is the linker. This was always the part where I go into trouble when trying this earlier. Finally, this blog post from Graham Enos guided me to a Homebrew tap by Filippo Valsorda, which provides a complete macOS to Linux cross-compile toolchain.
1
| |
That was the heavy-lifting. Now just tell Cargo where to find the linker. You can place the following into your projects .cargo/config or configure it globally in your ~/.cargo/config
1 2 | |
That’s it! You can now cross-compile Linux binaries with Cargo!
1
| |
You can find the resulting statically linked ELF binary in the target/x86_64-unknown-linux-musl/release directory. This file can be copied and run on any Linux x86_64 machine, just like the cross-compiled Go binary!
1 2 | |