@@ -52,6 +52,15 @@ use std::path::{Path, PathBuf};
52
52
use std:: process:: { ExitStatus , Output , Stdio } ;
53
53
use std:: { env, fmt, fs, io, mem, str} ;
54
54
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
+
55
64
pub fn ensure_removed ( dcx : & DiagCtxt , path : & Path ) {
56
65
if let Err ( e) = fs:: remove_file ( path) {
57
66
if e. kind ( ) != io:: ErrorKind :: NotFound {
@@ -1265,15 +1274,15 @@ fn link_sanitizer_runtime(
1265
1274
let path = find_sanitizer_runtime ( sess, & filename) ;
1266
1275
let rpath = path. to_str ( ) . expect ( "non-utf8 component in path" ) ;
1267
1276
linker. args ( & [ "-Wl,-rpath" , "-Xlinker" , rpath] ) ;
1268
- linker. link_dylib ( & filename, false , true ) ;
1277
+ linker. link_dylib_by_name ( & filename, false , true ) ;
1269
1278
} else if sess. target . is_like_msvc && flavor == LinkerFlavor :: Msvc ( Lld :: No ) && name == "asan" {
1270
1279
// MSVC provides the `/INFERASANLIBS` argument to automatically find the
1271
1280
// compatible ASAN library.
1272
1281
linker. arg ( "/INFERASANLIBS" ) ;
1273
1282
} else {
1274
1283
let filename = format ! ( "librustc{channel}_rt.{name}.a" ) ;
1275
1284
let path = find_sanitizer_runtime ( sess, & filename) . join ( & filename) ;
1276
- linker. link_whole_rlib ( & path) ;
1285
+ linker. link_staticlib_by_path ( & path, true ) ;
1277
1286
}
1278
1287
}
1279
1288
@@ -2445,7 +2454,7 @@ fn add_native_libs_from_crate(
2445
2454
archive_builder_builder : & dyn ArchiveBuilderBuilder ,
2446
2455
codegen_results : & CodegenResults ,
2447
2456
tmpdir : & Path ,
2448
- search_paths : & OnceCell < Vec < PathBuf > > ,
2457
+ search_paths : & SearchPaths ,
2449
2458
bundled_libs : & FxHashSet < Symbol > ,
2450
2459
cnum : CrateNum ,
2451
2460
link_static : bool ,
@@ -2505,46 +2514,34 @@ fn add_native_libs_from_crate(
2505
2514
if let Some ( filename) = lib. filename {
2506
2515
// If rlib contains native libs as archives, they are unpacked to tmpdir.
2507
2516
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) ;
2513
2518
}
2514
2519
} 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) ;
2524
2521
}
2525
2522
}
2526
2523
}
2527
2524
NativeLibKind :: Dylib { as_needed } => {
2528
2525
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 ) )
2530
2527
}
2531
2528
}
2532
2529
NativeLibKind :: Unspecified => {
2533
2530
// If we are generating a static binary, prefer static library when the
2534
2531
// link kind is unspecified.
2535
2532
if !link_output_kind. can_link_dylib ( ) && !sess. target . crt_static_allows_dylibs {
2536
2533
if link_static {
2537
- cmd. link_staticlib ( name, verbatim)
2534
+ cmd. link_staticlib_by_name ( name, verbatim, false , search_paths ) ;
2538
2535
}
2539
2536
} else {
2540
2537
if link_dynamic {
2541
- cmd. link_dylib ( name, verbatim, true ) ;
2538
+ cmd. link_dylib_by_name ( name, verbatim, true ) ;
2542
2539
}
2543
2540
}
2544
2541
}
2545
2542
NativeLibKind :: Framework { as_needed } => {
2546
2543
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 ) )
2548
2545
}
2549
2546
}
2550
2547
NativeLibKind :: RawDylib => {
@@ -2581,7 +2578,7 @@ fn add_local_native_libraries(
2581
2578
}
2582
2579
}
2583
2580
2584
- let search_paths = OnceCell :: new ( ) ;
2581
+ let search_paths = SearchPaths :: default ( ) ;
2585
2582
// All static and dynamic native library dependencies are linked to the local crate.
2586
2583
let link_static = true ;
2587
2584
let link_dynamic = true ;
@@ -2623,7 +2620,7 @@ fn add_upstream_rust_crates<'a>(
2623
2620
. find ( |( ty, _) | * ty == crate_type)
2624
2621
. expect ( "failed to find crate type in dependency format list" ) ;
2625
2622
2626
- let search_paths = OnceCell :: new ( ) ;
2623
+ let search_paths = SearchPaths :: default ( ) ;
2627
2624
for & cnum in & codegen_results. crate_info . used_crates {
2628
2625
// We may not pass all crates through to the linker. Some crates may appear statically in
2629
2626
// an existing dylib, meaning we'll pick up all the symbols from the dylib.
@@ -2698,7 +2695,7 @@ fn add_upstream_native_libraries(
2698
2695
tmpdir : & Path ,
2699
2696
link_output_kind : LinkOutputKind ,
2700
2697
) {
2701
- let search_path = OnceCell :: new ( ) ;
2698
+ let search_paths = SearchPaths :: default ( ) ;
2702
2699
for & cnum in & codegen_results. crate_info . used_crates {
2703
2700
// Static libraries are not linked here, they are linked in `add_upstream_rust_crates`.
2704
2701
// FIXME: Merge this function to `add_upstream_rust_crates` so that all native libraries
@@ -2720,7 +2717,7 @@ fn add_upstream_native_libraries(
2720
2717
archive_builder_builder,
2721
2718
codegen_results,
2722
2719
tmpdir,
2723
- & search_path ,
2720
+ & search_paths ,
2724
2721
& Default :: default ( ) ,
2725
2722
cnum,
2726
2723
link_static,
@@ -2791,7 +2788,7 @@ fn add_static_crate<'a>(
2791
2788
} else {
2792
2789
fix_windows_verbatim_for_gcc ( path)
2793
2790
} ;
2794
- cmd. link_rlib ( & rlib_path) ;
2791
+ cmd. link_staticlib_by_path ( & rlib_path, false ) ;
2795
2792
} ;
2796
2793
2797
2794
if !are_upstream_rust_objects_already_included ( sess)
@@ -2859,13 +2856,20 @@ fn add_dynamic_crate(cmd: &mut dyn Linker, sess: &Session, cratepath: &Path) {
2859
2856
// Just need to tell the linker about where the library lives and
2860
2857
// what its name is
2861
2858
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
+ }
2862
2866
if let Some ( dir) = parent {
2863
2867
cmd. include_path ( & rehome_sysroot_lib_dir ( sess, dir) ) ;
2864
2868
}
2865
2869
let stem = cratepath. file_stem ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) ;
2866
2870
// Convert library file-stem into a cc -l argument.
2867
2871
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 ( "" ) ) ) ;
2872
+ cmd. link_dylib_by_name ( & stem[ prefix..] , false , true ) ;
2869
2873
}
2870
2874
2871
2875
fn relevant_lib ( sess : & Session , lib : & NativeLib ) -> bool {
0 commit comments