@@ -52,6 +52,15 @@ use std::path::{Path, PathBuf};
5252use std:: process:: { ExitStatus , Output , Stdio } ;
5353use std:: { env, fmt, fs, io, mem, str} ;
5454
55+ #[ derive( Default ) ]
56+ pub struct SearchPaths ( OnceCell < Vec < PathBuf > > ) ;
57+
58+ impl SearchPaths {
59+ pub ( super ) fn get ( & self , sess : & Session ) -> & [ PathBuf ] {
60+ self . 0 . get_or_init ( || archive_search_paths ( sess) )
61+ }
62+ }
63+
5564pub fn ensure_removed ( dcx : & DiagCtxt , path : & Path ) {
5665 if let Err ( e) = fs:: remove_file ( path) {
5766 if e. kind ( ) != io:: ErrorKind :: NotFound {
@@ -1265,15 +1274,15 @@ fn link_sanitizer_runtime(
12651274 let path = find_sanitizer_runtime ( sess, & filename) ;
12661275 let rpath = path. to_str ( ) . expect ( "non-utf8 component in path" ) ;
12671276 linker. args ( & [ "-Wl,-rpath" , "-Xlinker" , rpath] ) ;
1268- linker. link_dylib ( & filename, false , true ) ;
1277+ linker. link_dylib_by_name ( & filename, false , true ) ;
12691278 } else if sess. target . is_like_msvc && flavor == LinkerFlavor :: Msvc ( Lld :: No ) && name == "asan" {
12701279 // MSVC provides the `/INFERASANLIBS` argument to automatically find the
12711280 // compatible ASAN library.
12721281 linker. arg ( "/INFERASANLIBS" ) ;
12731282 } else {
12741283 let filename = format ! ( "librustc{channel}_rt.{name}.a" ) ;
12751284 let path = find_sanitizer_runtime ( sess, & filename) . join ( & filename) ;
1276- linker. link_whole_rlib ( & path) ;
1285+ linker. link_staticlib_by_path ( & path, true ) ;
12771286 }
12781287}
12791288
@@ -2445,7 +2454,7 @@ fn add_native_libs_from_crate(
24452454 archive_builder_builder : & dyn ArchiveBuilderBuilder ,
24462455 codegen_results : & CodegenResults ,
24472456 tmpdir : & Path ,
2448- search_paths : & OnceCell < Vec < PathBuf > > ,
2457+ search_paths : & SearchPaths ,
24492458 bundled_libs : & FxHashSet < Symbol > ,
24502459 cnum : CrateNum ,
24512460 link_static : bool ,
@@ -2505,46 +2514,34 @@ fn add_native_libs_from_crate(
25052514 if let Some ( filename) = lib. filename {
25062515 // If rlib contains native libs as archives, they are unpacked to tmpdir.
25072516 let path = tmpdir. join ( filename. as_str ( ) ) ;
2508- if whole_archive {
2509- cmd. link_whole_rlib ( & path) ;
2510- } else {
2511- cmd. link_rlib ( & path) ;
2512- }
2517+ cmd. link_staticlib_by_path ( & path, whole_archive) ;
25132518 }
25142519 } else {
2515- if whole_archive {
2516- cmd. link_whole_staticlib (
2517- name,
2518- verbatim,
2519- search_paths. get_or_init ( || archive_search_paths ( sess) ) ,
2520- ) ;
2521- } else {
2522- cmd. link_staticlib ( name, verbatim)
2523- }
2520+ cmd. link_staticlib_by_name ( name, verbatim, whole_archive, search_paths) ;
25242521 }
25252522 }
25262523 }
25272524 NativeLibKind :: Dylib { as_needed } => {
25282525 if link_dynamic {
2529- cmd. link_dylib ( name, verbatim, as_needed. unwrap_or ( true ) )
2526+ cmd. link_dylib_by_name ( name, verbatim, as_needed. unwrap_or ( true ) )
25302527 }
25312528 }
25322529 NativeLibKind :: Unspecified => {
25332530 // If we are generating a static binary, prefer static library when the
25342531 // link kind is unspecified.
25352532 if !link_output_kind. can_link_dylib ( ) && !sess. target . crt_static_allows_dylibs {
25362533 if link_static {
2537- cmd. link_staticlib ( name, verbatim)
2534+ cmd. link_staticlib_by_name ( name, verbatim, false , search_paths ) ;
25382535 }
25392536 } else {
25402537 if link_dynamic {
2541- cmd. link_dylib ( name, verbatim, true ) ;
2538+ cmd. link_dylib_by_name ( name, verbatim, true ) ;
25422539 }
25432540 }
25442541 }
25452542 NativeLibKind :: Framework { as_needed } => {
25462543 if link_dynamic {
2547- cmd. link_framework ( name, as_needed. unwrap_or ( true ) )
2544+ cmd. link_framework_by_name ( name, verbatim , as_needed. unwrap_or ( true ) )
25482545 }
25492546 }
25502547 NativeLibKind :: RawDylib => {
@@ -2581,7 +2578,7 @@ fn add_local_native_libraries(
25812578 }
25822579 }
25832580
2584- let search_paths = OnceCell :: new ( ) ;
2581+ let search_paths = SearchPaths :: default ( ) ;
25852582 // All static and dynamic native library dependencies are linked to the local crate.
25862583 let link_static = true ;
25872584 let link_dynamic = true ;
@@ -2623,7 +2620,7 @@ fn add_upstream_rust_crates<'a>(
26232620 . find ( |( ty, _) | * ty == crate_type)
26242621 . expect ( "failed to find crate type in dependency format list" ) ;
26252622
2626- let search_paths = OnceCell :: new ( ) ;
2623+ let search_paths = SearchPaths :: default ( ) ;
26272624 for & cnum in & codegen_results. crate_info . used_crates {
26282625 // We may not pass all crates through to the linker. Some crates may appear statically in
26292626 // an existing dylib, meaning we'll pick up all the symbols from the dylib.
@@ -2698,7 +2695,7 @@ fn add_upstream_native_libraries(
26982695 tmpdir : & Path ,
26992696 link_output_kind : LinkOutputKind ,
27002697) {
2701- let search_path = OnceCell :: new ( ) ;
2698+ let search_paths = SearchPaths :: default ( ) ;
27022699 for & cnum in & codegen_results. crate_info . used_crates {
27032700 // Static libraries are not linked here, they are linked in `add_upstream_rust_crates`.
27042701 // FIXME: Merge this function to `add_upstream_rust_crates` so that all native libraries
@@ -2720,7 +2717,7 @@ fn add_upstream_native_libraries(
27202717 archive_builder_builder,
27212718 codegen_results,
27222719 tmpdir,
2723- & search_path ,
2720+ & search_paths ,
27242721 & Default :: default ( ) ,
27252722 cnum,
27262723 link_static,
@@ -2791,7 +2788,7 @@ fn add_static_crate<'a>(
27912788 } else {
27922789 fix_windows_verbatim_for_gcc ( path)
27932790 } ;
2794- cmd. link_rlib ( & rlib_path) ;
2791+ cmd. link_staticlib_by_path ( & rlib_path, false ) ;
27952792 } ;
27962793
27972794 if !are_upstream_rust_objects_already_included ( sess)
@@ -2859,13 +2856,24 @@ fn add_dynamic_crate(cmd: &mut dyn Linker, sess: &Session, cratepath: &Path) {
28592856 // Just need to tell the linker about where the library lives and
28602857 // what its name is
28612858 let parent = cratepath. parent ( ) ;
2859+ // When producing a dll, the MSVC linker may not actually emit a
2860+ // `foo.lib` file if the dll doesn't actually export any symbols, so we
2861+ // check to see if the file is there and just omit linking to it if it's
2862+ // not present.
2863+ if sess. target . is_like_msvc && !cratepath. with_extension ( "dll.lib" ) . exists ( ) {
2864+ return ;
2865+ }
28622866 if let Some ( dir) = parent {
28632867 cmd. include_path ( & rehome_sysroot_lib_dir ( sess, dir) ) ;
28642868 }
2865- let stem = cratepath. file_stem ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) ;
2869+ // "<dir>/name.dll -> name.dll" on windows-msvc
2870+ // "<dir>/name.dll -> name" on windows-gnu
2871+ // "<dir>/libname.<ext> -> name" elsewhere
2872+ let stem = if sess. target . is_like_msvc { cratepath. file_name ( ) } else { cratepath. file_stem ( ) } ;
2873+ let stem = stem. unwrap ( ) . to_str ( ) . unwrap ( ) ;
28662874 // Convert library file-stem into a cc -l argument.
28672875 let prefix = if stem. starts_with ( "lib" ) && !sess. target . is_like_windows { 3 } else { 0 } ;
2868- cmd. link_rust_dylib ( & stem[ prefix..] , parent . unwrap_or_else ( || Path :: new ( "" ) ) ) ;
2876+ cmd. link_dylib_by_name ( & stem[ prefix..] , false , true ) ;
28692877}
28702878
28712879fn relevant_lib ( sess : & Session , lib : & NativeLib ) -> bool {
0 commit comments