@@ -685,8 +685,8 @@ fn link_natively(
685685 codegen_backend : & ' static str ,
686686) {
687687 info ! ( "preparing {:?} to {:?}" , crate_type, out_filename) ;
688- let ( linker_path , flavor ) = linker_and_flavor ( sess) ;
689- let self_contained_components = self_contained_components ( sess, crate_type , & linker_path ) ;
688+ let self_contained_components = self_contained_components ( sess, crate_type ) ;
689+ let ( linker_path , flavor ) = linker_and_flavor ( sess, & self_contained_components ) ;
690690
691691 // On AIX, we ship all libraries as .a big_af archive
692692 // the expected format is lib<name>.a(libname.so) for the actual
@@ -1318,7 +1318,10 @@ pub fn ignored_for_lto(sess: &Session, info: &CrateInfo, cnum: CrateNum) -> bool
13181318}
13191319
13201320/// This functions tries to determine the appropriate linker (and corresponding LinkerFlavor) to use
1321- pub fn linker_and_flavor ( sess : & Session ) -> ( PathBuf , LinkerFlavor ) {
1321+ pub fn linker_and_flavor (
1322+ sess : & Session ,
1323+ self_contained_components : & LinkSelfContainedComponents ,
1324+ ) -> ( PathBuf , LinkerFlavor ) {
13221325 fn infer_from (
13231326 sess : & Session ,
13241327 linker : Option < PathBuf > ,
@@ -1415,6 +1418,18 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
14151418 return ret;
14161419 }
14171420
1421+ // When using a supported target in self-contained linker mode, we want to use rust-lld directly.
1422+ let self_contained_target = sess. target . os == Os :: Windows
1423+ && sess. target . env == Env :: Gnu
1424+ && sess. target . abi == Abi :: Llvm
1425+ && self_contained_components. is_linker_enabled ( ) ;
1426+ if self_contained_target
1427+ && let Some ( ret) =
1428+ infer_from ( sess, None , Some ( LinkerFlavor :: Gnu ( Cc :: No , Lld :: Yes ) ) , features)
1429+ {
1430+ return ret;
1431+ }
1432+
14181433 if let Some ( ret) = infer_from (
14191434 sess,
14201435 sess. target . linker . as_deref ( ) . map ( PathBuf :: from) ,
@@ -1761,20 +1776,34 @@ fn link_output_kind(sess: &Session, crate_type: CrateType) -> LinkOutputKind {
17611776 }
17621777}
17631778
1764- // Returns true if linker is located within sysroot
1765- fn detect_self_contained_mingw ( sess : & Session , linker : & Path ) -> bool {
1766- // Assume `-C linker=rust-lld` as self-contained mode
1767- if linker == Path :: new ( "rust-lld" ) {
1768- return true ;
1779+ /// Returns true if linker is shipped by Rust.
1780+ // There are currently two different solutions for self-contained mode with mingw-w64:
1781+ // using rust-lld directly (`-gnullvm`) or using shipped cc to call the linker (`-gnu`).
1782+ // Eventually, `-gnu` toolchains might be moved to calling the linker directly.
1783+ fn detect_self_contained_mingw ( sess : & Session ) -> bool {
1784+ // Passing custom linker means non-self-contained mode.
1785+ if sess. opts . cg . linker . is_some ( ) {
1786+ // Unless running on `-windows-gnu-llvm` and using `-C linker=rust-lld`.
1787+ if sess. target . abi == Abi :: Llvm {
1788+ return sess
1789+ . opts
1790+ . cg
1791+ . linker
1792+ . as_ref ( )
1793+ . is_some_and ( |linker| linker == Path :: new ( "rust-lld" ) ) ;
1794+ }
1795+
1796+ return false ;
17691797 }
1770- let linker_with_extension = if cfg ! ( windows) && linker. extension ( ) . is_none ( ) {
1798+
1799+ let linker_with_extension = if let Some ( linker) = sess. target . linker . as_deref ( ) . map ( Path :: new) {
17711800 linker. with_extension ( "exe" )
17721801 } else {
1773- linker . to_path_buf ( )
1802+ return false ;
17741803 } ;
17751804 for dir in env:: split_paths ( & env:: var_os ( "PATH" ) . unwrap_or_default ( ) ) {
17761805 let full_path = dir. join ( & linker_with_extension) ;
1777- // If linker comes from sysroot assume self-contained mode
1806+ // If linker doesn't come from sysroot assume non- self-contained mode
17781807 if full_path. is_file ( ) && !full_path. starts_with ( sess. opts . sysroot . path ( ) ) {
17791808 return false ;
17801809 }
@@ -1785,11 +1814,7 @@ fn detect_self_contained_mingw(sess: &Session, linker: &Path) -> bool {
17851814/// Various toolchain components used during linking are used from rustc distribution
17861815/// instead of being found somewhere on the host system.
17871816/// We only provide such support for a very limited number of targets.
1788- fn self_contained_components (
1789- sess : & Session ,
1790- crate_type : CrateType ,
1791- linker : & Path ,
1792- ) -> LinkSelfContainedComponents {
1817+ fn self_contained_components ( sess : & Session , crate_type : CrateType ) -> LinkSelfContainedComponents {
17931818 // Turn the backwards compatible bool values for `self_contained` into fully inferred
17941819 // `LinkSelfContainedComponents`.
17951820 let self_contained =
@@ -1818,7 +1843,7 @@ fn self_contained_components(
18181843 LinkSelfContainedDefault :: InferredForMingw => {
18191844 sess. host == sess. target
18201845 && sess. target . abi != Abi :: Uwp
1821- && detect_self_contained_mingw ( sess, linker )
1846+ && detect_self_contained_mingw ( sess)
18221847 }
18231848 }
18241849 } ;
0 commit comments