From dd7246501ec4f3a1510c202e69521fc4fe7f1542 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Miku=C5=82a?= Date: Fri, 21 Nov 2025 13:55:38 +0100 Subject: [PATCH] refactor mingw-w64 self-contained detection --- compiler/rustc_codegen_ssa/src/back/link.rs | 31 +++++++++++---------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 820f7ba4a6f23..97b1d5d5918c1 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -686,7 +686,7 @@ fn link_natively( ) { info!("preparing {:?} to {:?}", crate_type, out_filename); let (linker_path, flavor) = linker_and_flavor(sess); - let self_contained_components = self_contained_components(sess, crate_type, &linker_path); + let self_contained_components = self_contained_components(sess, crate_type); // On AIX, we ship all libraries as .a big_af archive // the expected format is lib.a(libname.so) for the actual @@ -1761,20 +1761,25 @@ fn link_output_kind(sess: &Session, crate_type: CrateType) -> LinkOutputKind { } } -// Returns true if linker is located within sysroot -fn detect_self_contained_mingw(sess: &Session, linker: &Path) -> bool { - // Assume `-C linker=rust-lld` as self-contained mode - if linker == Path::new("rust-lld") { - return true; +/// Returns true if linker is shipped by Rust. +// There are currently two different solutions for self-contained mode with mingw-w64: +// using rust-lld directly (`-gnullvm` and `-gnu`) or using shipped cc to call the linker (`-gnu`). +// Eventually, `-gnu` toolchains might be moved to calling the linker directly. +fn detect_self_contained_mingw(sess: &Session) -> bool { + // Passing explicit linker other than `rust-lld` means non-self-contained mode. + if let Some(linker) = &sess.opts.cg.linker { + return linker == Path::new("rust-lld"); } - let linker_with_extension = if cfg!(windows) && linker.extension().is_none() { + + // If no explicit linker was given, proceed with implicit one (if present). + let linker_with_extension = if let Some(linker) = sess.target.linker.as_deref().map(Path::new) { linker.with_extension("exe") } else { - linker.to_path_buf() + return false; }; for dir in env::split_paths(&env::var_os("PATH").unwrap_or_default()) { let full_path = dir.join(&linker_with_extension); - // If linker comes from sysroot assume self-contained mode + // If found linker doesn't come from sysroot assume non-self-contained mode. if full_path.is_file() && !full_path.starts_with(sess.opts.sysroot.path()) { return false; } @@ -1785,11 +1790,7 @@ fn detect_self_contained_mingw(sess: &Session, linker: &Path) -> bool { /// Various toolchain components used during linking are used from rustc distribution /// instead of being found somewhere on the host system. /// We only provide such support for a very limited number of targets. -fn self_contained_components( - sess: &Session, - crate_type: CrateType, - linker: &Path, -) -> LinkSelfContainedComponents { +fn self_contained_components(sess: &Session, crate_type: CrateType) -> LinkSelfContainedComponents { // Turn the backwards compatible bool values for `self_contained` into fully inferred // `LinkSelfContainedComponents`. let self_contained = @@ -1818,7 +1819,7 @@ fn self_contained_components( LinkSelfContainedDefault::InferredForMingw => { sess.host == sess.target && sess.target.abi != Abi::Uwp - && detect_self_contained_mingw(sess, linker) + && detect_self_contained_mingw(sess) } } };