@@ -1844,7 +1844,7 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
1844
1844
// This change is somewhat breaking in practice due to local static libraries being linked
1845
1845
// as whole-archive (#85144), so removing whole-archive may be a pre-requisite.
1846
1846
if sess. opts . debugging_opts . link_native_libraries {
1847
- add_local_native_libraries ( cmd, sess, codegen_results) ;
1847
+ add_local_native_libraries ( cmd, sess, codegen_results, crate_type ) ;
1848
1848
}
1849
1849
1850
1850
// Upstream rust libraries and their nobundle static libraries
@@ -2016,6 +2016,16 @@ fn add_order_independent_options(
2016
2016
add_rpath_args ( cmd, sess, codegen_results, out_filename) ;
2017
2017
}
2018
2018
2019
+ // A dylib may reexport symbols from the linked rlib or native static library.
2020
+ // Even if some symbol is reexported it's still not necessarily counted as used and may be
2021
+ // dropped, at least with `ld`-like ELF linkers. So we have to link some rlibs and static
2022
+ // libraries as whole-archive to avoid losing reexported symbols.
2023
+ // FIXME: Find a way to mark reexported symbols as used and avoid this use of whole-archive.
2024
+ fn default_to_whole_archive ( sess : & Session , crate_type : CrateType , cmd : & dyn Linker ) -> bool {
2025
+ crate_type == CrateType :: Dylib
2026
+ && !( sess. target . limit_rdylib_exports && cmd. exported_symbol_means_used_symbol ( ) )
2027
+ }
2028
+
2019
2029
/// # Native library linking
2020
2030
///
2021
2031
/// User-supplied library search paths (-L on the command line). These are the same paths used to
@@ -2029,6 +2039,7 @@ fn add_local_native_libraries(
2029
2039
cmd : & mut dyn Linker ,
2030
2040
sess : & Session ,
2031
2041
codegen_results : & CodegenResults ,
2042
+ crate_type : CrateType ,
2032
2043
) {
2033
2044
let filesearch = sess. target_filesearch ( PathKind :: All ) ;
2034
2045
for search_path in filesearch. search_paths ( ) {
@@ -2046,14 +2057,18 @@ fn add_local_native_libraries(
2046
2057
codegen_results. crate_info . used_libraries . iter ( ) . filter ( |l| relevant_lib ( sess, l) ) ;
2047
2058
2048
2059
let search_path = OnceCell :: new ( ) ;
2049
- let mut last = ( NativeLibKind :: Unspecified , None ) ;
2060
+ let mut last = ( None , NativeLibKind :: Unspecified , None ) ;
2050
2061
for lib in relevant_libs {
2051
2062
let Some ( name) = lib. name else {
2052
2063
continue ;
2053
2064
} ;
2054
2065
2055
2066
// Skip if this library is the same as the last.
2056
- last = if ( lib. kind , lib. name ) == last { continue } else { ( lib. kind , lib. name ) } ;
2067
+ last = if ( lib. name , lib. kind , lib. verbatim ) == last {
2068
+ continue ;
2069
+ } else {
2070
+ ( lib. name , lib. kind , lib. verbatim )
2071
+ } ;
2057
2072
2058
2073
let verbatim = lib. verbatim . unwrap_or ( false ) ;
2059
2074
match lib. kind {
@@ -2064,15 +2079,19 @@ fn add_local_native_libraries(
2064
2079
NativeLibKind :: Framework { as_needed } => {
2065
2080
cmd. link_framework ( name, as_needed. unwrap_or ( true ) )
2066
2081
}
2067
- NativeLibKind :: Static { bundle : None | Some ( true ) , .. }
2068
- | NativeLibKind :: Static { whole_archive : Some ( true ) , .. } => {
2069
- cmd. link_whole_staticlib (
2070
- name,
2071
- verbatim,
2072
- & search_path. get_or_init ( || archive_search_paths ( sess) ) ,
2073
- ) ;
2082
+ NativeLibKind :: Static { whole_archive, .. } => {
2083
+ if whole_archive == Some ( true )
2084
+ || ( whole_archive == None && default_to_whole_archive ( sess, crate_type, cmd) )
2085
+ {
2086
+ cmd. link_whole_staticlib (
2087
+ name,
2088
+ verbatim,
2089
+ & search_path. get_or_init ( || archive_search_paths ( sess) ) ,
2090
+ ) ;
2091
+ } else {
2092
+ cmd. link_staticlib ( name, verbatim)
2093
+ }
2074
2094
}
2075
- NativeLibKind :: Static { .. } => cmd. link_staticlib ( name, verbatim) ,
2076
2095
NativeLibKind :: RawDylib => {
2077
2096
// FIXME(#58713): Proper handling for raw dylibs.
2078
2097
bug ! ( "raw_dylib feature not yet implemented" ) ;
@@ -2197,34 +2216,37 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(
2197
2216
// external build system already has the native dependencies defined, and it
2198
2217
// will provide them to the linker itself.
2199
2218
if sess. opts . debugging_opts . link_native_libraries {
2200
- let mut last = None ;
2219
+ let mut last = ( None , NativeLibKind :: Unspecified , None ) ;
2201
2220
for lib in & codegen_results. crate_info . native_libraries [ & cnum] {
2221
+ let Some ( name) = lib. name else {
2222
+ continue ;
2223
+ } ;
2202
2224
if !relevant_lib ( sess, lib) {
2203
- // Skip libraries if they are disabled by `#[link(cfg=...)]`
2204
2225
continue ;
2205
2226
}
2206
2227
2207
2228
// Skip if this library is the same as the last.
2208
- if last == lib. name {
2229
+ last = if ( lib. name , lib . kind , lib . verbatim ) == last {
2209
2230
continue ;
2210
- }
2211
-
2212
- if let Some ( static_lib_name) = lib. name {
2213
- if let NativeLibKind :: Static { bundle : Some ( false ) , whole_archive } =
2214
- lib. kind
2231
+ } else {
2232
+ ( lib. name , lib. kind , lib. verbatim )
2233
+ } ;
2234
+
2235
+ if let NativeLibKind :: Static { bundle : Some ( false ) , whole_archive } =
2236
+ lib. kind
2237
+ {
2238
+ let verbatim = lib. verbatim . unwrap_or ( false ) ;
2239
+ if whole_archive == Some ( true )
2240
+ || ( whole_archive == None
2241
+ && default_to_whole_archive ( sess, crate_type, cmd) )
2215
2242
{
2216
- let verbatim = lib. verbatim . unwrap_or ( false ) ;
2217
- if whole_archive == Some ( true ) {
2218
- cmd. link_whole_staticlib (
2219
- static_lib_name,
2220
- verbatim,
2221
- search_path. get_or_init ( || archive_search_paths ( sess) ) ,
2222
- ) ;
2223
- } else {
2224
- cmd. link_staticlib ( static_lib_name, verbatim) ;
2225
- }
2226
-
2227
- last = lib. name ;
2243
+ cmd. link_whole_staticlib (
2244
+ name,
2245
+ verbatim,
2246
+ search_path. get_or_init ( || archive_search_paths ( sess) ) ,
2247
+ ) ;
2248
+ } else {
2249
+ cmd. link_staticlib ( name, verbatim) ;
2228
2250
}
2229
2251
}
2230
2252
}
@@ -2282,15 +2304,10 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(
2282
2304
let cratepath = & src. rlib . as_ref ( ) . unwrap ( ) . 0 ;
2283
2305
2284
2306
let mut link_upstream = |path : & Path | {
2285
- // If we're creating a dylib, then we need to include the
2286
- // whole of each object in our archive into that artifact. This is
2287
- // because a `dylib` can be reused as an intermediate artifact.
2288
- //
2289
- // Note, though, that we don't want to include the whole of a
2290
- // compiler-builtins crate (e.g., compiler-rt) because it'll get
2291
- // repeatedly linked anyway.
2307
+ // We don't want to include the whole compiler-builtins crate (e.g., compiler-rt)
2308
+ // regardless of the default because it'll get repeatedly linked anyway.
2292
2309
let path = fix_windows_verbatim_for_gcc ( path) ;
2293
- if crate_type == CrateType :: Dylib
2310
+ if default_to_whole_archive ( sess , crate_type, cmd )
2294
2311
&& codegen_results. crate_info . compiler_builtins != Some ( cnum)
2295
2312
{
2296
2313
cmd. link_whole_rlib ( & path) ;
@@ -2401,7 +2418,7 @@ fn add_upstream_native_libraries(
2401
2418
sess : & Session ,
2402
2419
codegen_results : & CodegenResults ,
2403
2420
) {
2404
- let mut last = ( NativeLibKind :: Unspecified , None ) ;
2421
+ let mut last = ( None , NativeLibKind :: Unspecified , None ) ;
2405
2422
for & cnum in & codegen_results. crate_info . used_crates {
2406
2423
for lib in codegen_results. crate_info . native_libraries [ & cnum] . iter ( ) {
2407
2424
let Some ( name) = lib. name else {
@@ -2412,7 +2429,11 @@ fn add_upstream_native_libraries(
2412
2429
}
2413
2430
2414
2431
// Skip if this library is the same as the last.
2415
- last = if ( lib. kind , lib. name ) == last { continue } else { ( lib. kind , lib. name ) } ;
2432
+ last = if ( lib. name , lib. kind , lib. verbatim ) == last {
2433
+ continue ;
2434
+ } else {
2435
+ ( lib. name , lib. kind , lib. verbatim )
2436
+ } ;
2416
2437
2417
2438
let verbatim = lib. verbatim . unwrap_or ( false ) ;
2418
2439
match lib. kind {
0 commit comments