-
Notifications
You must be signed in to change notification settings - Fork 13.8k
Description
What Happend?
When cross-compiling for x86_64-pc-windows-gnu on NixOS (or similar Linux environments), the Rust compiler automatically injects rsbegin.o and rsend.o into the linker command. However, there is no mechanism to configure or override the path to these startup object files.
Linker cannot find the object files unless they are in the expected sysroot location, e.g.:
$HOME/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-pc-windows-gnu/lib
Attempts to pass rsbegin.o / rsend.o manually via RUSTFLAGS or -C link-args result in duplicate object name errors, because the compiler still injects its own copies automatically.
This makes cross-compiling a minimal hello-world executable for x86_64-pc-windows-gnu unreliable on NixOS or other Linux systems using non-standard sysroot paths.
Steps to reproduce:
rustup target add x86_64-pc-windows-gnu
cargo new hello
cd hello
cargo build --target x86_64-pc-windows-gnu -Zbuild-std
Relevant code:
Rust bootstrap currently injects startup objects here:
for file in &["rsbegin", "rsend"] {
let src_file = &src_dir.join(file.to_string() + ".rs");
let dst_file = &dst_dir.join(file.to_string() + ".o");
if !up_to_date(src_file, dst_file) {
let mut cmd = Command::new(&builder.initial_rustc);
cmd.env("RUSTC_BOOTSTRAP", "1");
...
builder.run(
cmd.arg("--target")
.arg(target.rustc_target_arg())
.arg("--emit=obj")
.arg("-o")
.arg(dst_file)
.arg(src_file),
);
}
}
Proposed improvement / feature request:
-
Allow overriding the path to rsbegin.o / rsend.o via environment variable or Cargo configuration.
-
Alternatively, provide a mechanism to disable automatic injection for advanced cross-compilation setups.
This would make cross-compilation on non-standard systems (NixOS, custom sysroots) feasible without hacks.
Environment:
Rust nightly (toolchain: nightly-x86_64-unknown-linux-gnu)
Target: x86_64-pc-windows-gnu
OS: NixOS / Linux
cargo and rustc via rustup