I am learning to appreciate Rust as a highly performant and expressive language. My previous programming language of choice has been Go for a number of years. One thing I miss from Go, is the built-in linker, which makes cross-compiling a breeze. Could Rust get a similar built-in linker?
Meanwhile, the Rust community has been hard at work to fill in cross-compiler gaps, especially with the cross project:
I think we could make the cross contributors' lives easier, by moving beyond the need for a separate C/C++ compiler when building pure Rust projects for the various rustup targets.
Rust ships with llvm's lld linker. It is by default used on wasm, but you can use it on other platforms too. Do note however that on all platforms you need system libraries like libc and on unix gcc or clang as linker wrapper configured for this platform on your local machine. The system libraries are necessary to know which symbol should be resolved in which library (the raw-dylib feature will make this unnecessary on windows once the windows-sys crate and other crates binding against windows system libraries start using it by having rustc generate import libraries from the extern "C" {} blocks in those bindings. Raw-dylib isn't implemented on other targets yet) Gcc or clang is necessary as neither rustc nor the linker know where to find system libraries, nor what extra linker flags are necessary to produce a working executable. Gcc and clang contain this knowledge.
Go can cross-compile much more easily as unless you use cgo, you can't link against any system library and the list of supported targets is small enough that hardcoding target specific knowledge is feasible. If you use cgo you have to use the system linker (+ linker wrapper on unix) again, just like for rust.
In short while we are trying to make cross-compiling easier, there is a lot involved in this that makes it a non-trivial problem to solve.
Go makes the tradeoff that cross-compilation is important, but FFI to existing libraries written in languages other than Go, and FFI to let you call Go code from a non-Go language is not. This is fine if your entire program and everything you depend upon is written in Go, which is the common case at Google, but not so great if you want to depend on something not written in Go, or write a small component of a big system in Go. And if you do use CGo, you have all the cross-compilation difficulties that Rust has.
If you declare that the entire project must be written in one language, then the linker problem is more tractable - but Rust's goals from the beginning have included being usable as a language to replace C++ in applications like Mozilla Firefox, where the project is already multi-lingual.
Writing a linker is a lot of work and requires some really esoteric domain-specific knowledge which very few people in or outside the open-source community have. Lld already has a lot of amazing features (lto, multicore support). This isn't like asking for a tweak to some standard library function.
While Go tried to avoid libc on all platforms, except for Linux no mainstream OS has a stable syscall interface and in fact both macOS and OpenBSD have broken Go programs due to syscall interface changes, forcing Go to use libc again on those platforms. Also Go doesn't allow C++ exceptions to cross into Go AFAIK, while Rust is about to stabilize support for this (or has it already?). This requires linking against the system unwinder to handle exceptions.