diff --git a/xtask/src/run.rs b/xtask/src/run.rs index 8bba7a53..6878423d 100644 --- a/xtask/src/run.rs +++ b/xtask/src/run.rs @@ -55,12 +55,36 @@ pub fn build(target: Option<&str>, f: F) -> Result> where F: FnOnce(&mut Command) -> &mut Command, { - // Always use rust-lld and -Zbuild-std in case we're cross-compiling. + // Always use lld in case we're cross-compiling. let mut cmd = Command::new("cargo"); cmd.args(["build", "--message-format=json"]); if let Some(target) = target { - let config = format!("target.{target}.linker = \"rust-lld\""); - cmd.args(["--target", target, "--config", &config]); + // Using rust-lld directly on Linux does not work, as you are expected + // to invoke a C compiler, which then invokes the linker with necessary + // arguments, like the search path. Invoking linker directly results in + // inability to find the system libraries. + // + // On Rust nightly, the solution is to use `-Zlinker-features=+lld`, + // which tells the C compiler to use rust-lld. However, there is no + // guarantee that the build is going to be performed with nightly + // toolchain, so that's not an option. + // + // On Rust stable, the solution is to invoke lld through clang. That's + // our best bet for now. + // + // https://users.rust-lang.org/t/enabling-rust-lld-for-aarch64-unknown-linux-gnu/113243/2 + // https://github.com/rust-lang/rust/issues/130062#issuecomment-2336050640 + #[cfg(target_os = "linux")] + { + let config = format!("target.{target}.rustflags=[\"-C\", \"linker=clang\", \"-C\", \"link-arg=-fuse-ld=lld\"]"); + cmd.args(["--target", target, "--config", &config]); + } + #[cfg(not(target_os = "linux"))] + { + // On non-Linux systems, rust-lld should work fine. + let config = format!("target.{target}.linker = \"rust-lld\""); + cmd.args(["--target", target, "--config", &config]); + } } f(&mut cmd);