@@ -1844,7 +1844,7 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
18441844 // This change is somewhat breaking in practice due to local static libraries being linked
18451845 // as whole-archive (#85144), so removing whole-archive may be a pre-requisite.
18461846 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 ) ;
18481848 }
18491849
18501850 // Upstream rust libraries and their nobundle static libraries
@@ -2016,6 +2016,16 @@ fn add_order_independent_options(
20162016 add_rpath_args ( cmd, sess, codegen_results, out_filename) ;
20172017}
20182018
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+
20192029/// # Native library linking
20202030///
20212031/// 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(
20292039 cmd : & mut dyn Linker ,
20302040 sess : & Session ,
20312041 codegen_results : & CodegenResults ,
2042+ crate_type : CrateType ,
20322043) {
20332044 let filesearch = sess. target_filesearch ( PathKind :: All ) ;
20342045 for search_path in filesearch. search_paths ( ) {
@@ -2046,14 +2057,18 @@ fn add_local_native_libraries(
20462057 codegen_results. crate_info . used_libraries . iter ( ) . filter ( |l| relevant_lib ( sess, l) ) ;
20472058
20482059 let search_path = OnceCell :: new ( ) ;
2049- let mut last = ( NativeLibKind :: Unspecified , None ) ;
2060+ let mut last = ( None , NativeLibKind :: Unspecified , None ) ;
20502061 for lib in relevant_libs {
20512062 let Some ( name) = lib. name else {
20522063 continue ;
20532064 } ;
20542065
20552066 // 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+ } ;
20572072
20582073 let verbatim = lib. verbatim . unwrap_or ( false ) ;
20592074 match lib. kind {
@@ -2064,15 +2079,19 @@ fn add_local_native_libraries(
20642079 NativeLibKind :: Framework { as_needed } => {
20652080 cmd. link_framework ( name, as_needed. unwrap_or ( true ) )
20662081 }
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+ }
20742094 }
2075- NativeLibKind :: Static { .. } => cmd. link_staticlib ( name, verbatim) ,
20762095 NativeLibKind :: RawDylib => {
20772096 // FIXME(#58713): Proper handling for raw dylibs.
20782097 bug ! ( "raw_dylib feature not yet implemented" ) ;
@@ -2197,34 +2216,37 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(
21972216 // external build system already has the native dependencies defined, and it
21982217 // will provide them to the linker itself.
21992218 if sess. opts . debugging_opts . link_native_libraries {
2200- let mut last = None ;
2219+ let mut last = ( None , NativeLibKind :: Unspecified , None ) ;
22012220 for lib in & codegen_results. crate_info . native_libraries [ & cnum] {
2221+ let Some ( name) = lib. name else {
2222+ continue ;
2223+ } ;
22022224 if !relevant_lib ( sess, lib) {
2203- // Skip libraries if they are disabled by `#[link(cfg=...)]`
22042225 continue ;
22052226 }
22062227
22072228 // 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 {
22092230 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) )
22152242 {
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) ;
22282250 }
22292251 }
22302252 }
@@ -2282,15 +2304,10 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(
22822304 let cratepath = & src. rlib . as_ref ( ) . unwrap ( ) . 0 ;
22832305
22842306 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.
22922309 let path = fix_windows_verbatim_for_gcc ( path) ;
2293- if crate_type == CrateType :: Dylib
2310+ if default_to_whole_archive ( sess , crate_type, cmd )
22942311 && codegen_results. crate_info . compiler_builtins != Some ( cnum)
22952312 {
22962313 cmd. link_whole_rlib ( & path) ;
@@ -2401,7 +2418,7 @@ fn add_upstream_native_libraries(
24012418 sess : & Session ,
24022419 codegen_results : & CodegenResults ,
24032420) {
2404- let mut last = ( NativeLibKind :: Unspecified , None ) ;
2421+ let mut last = ( None , NativeLibKind :: Unspecified , None ) ;
24052422 for & cnum in & codegen_results. crate_info . used_crates {
24062423 for lib in codegen_results. crate_info . native_libraries [ & cnum] . iter ( ) {
24072424 let Some ( name) = lib. name else {
@@ -2412,7 +2429,11 @@ fn add_upstream_native_libraries(
24122429 }
24132430
24142431 // 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+ } ;
24162437
24172438 let verbatim = lib. verbatim . unwrap_or ( false ) ;
24182439 match lib. kind {
0 commit comments