In order to cross-compile the Debian cargo package I have to explicitly set RUSTFLAGS += -C linker=$(DEB_HOST_GNU_TYPE)-gcc, see here. I originally didn't think too much of this, however rustbuild does not require me to set this sort of thing when cross-compiling rustc, it automatically detects the appropriate linker to use. I wonder if it's possible to add similar detection logic to Cargo?
I've definitely often wanted to do this but Cargo's not really in a position to do so. It's never been quite clear where this logic would go.
I just spent some time debugging some obscure build failure, before realizing that this was the root cause (a non-native x86_64-unknown-linux-musl build using host cc instead of musl-gcc when linking).
This manifested as relocation errors with ring: https://github.com/briansmith/ring/issues/544.
But it looks like other people previously stepped on this, again with musl: https://github.com/rust-lang/rust/issues/40049#issuecomment-282082114.
I've definitely often wanted to do this but Cargo's not really in a position to do so. It's never been quite clear where this logic would go.
I think it is OK to put it in Cargo if we can't identify any better place to put it. The kind of issue it would fix has tripped me up multiple times. Also, people tend to blame ring when things fail to link because often the first linker errors reported are in ring.
What about adding the logic to rustc itself? Basically, what's already in cc-rs here. Since rustc is the one calling the linker, it could select the right linker when it's being told to cross-compile.
If this is implemented, could we please default to ${target}-cc, as opposed to ${target}-gcc? People who use Clang-based cross compiler toolchains obviously don't have the latter.
Since Clang uses LLVM does it not have a --target flag to support cross-compilation out-of-the-box via one single cc binary? This situation of different ccs is only needed because of GCC's build system where you can only target one architecture for a given output compiler.
This issue comes into play when cross compiling Cargo projects using scripted cross compile build systems. Most C Makefile or CMake projects seem to rely primarily on $CC and $LD to find the correct compiler and linker to use. This makes it easy to cross compile most projects just by setting those flags.
I tried using CARGO_TARGET_$(TRIPLET)_LINKER=$(LD) in a recent attempt to get Cargo to properly cross compile using a specific set of cross compiler and linker but it's pretty clumsy. The option was tricky to find, and it still resulted in a broken binary that wouldn't run.
IMHO, Cargo does seem the correct place for something like this if it's already going to support --target=xyz and automatically find the C cross compiler (for dependencies like backtrace-sys and nix), it should find the linker as well. Though the RUSTFLAGS option is probably better than the CARGO_TARGET_$(TRIPLET)_LINKER=$(LD) method I tried.
Most helpful comment
If this is implemented, could we please default to
${target}-cc, as opposed to${target}-gcc? People who use Clang-based cross compiler toolchains obviously don't have the latter.