@@ -6,6 +6,7 @@ use rustc_data_structures::temp_dir::MaybeTempDir;
66use rustc_errors:: { ErrorGuaranteed , Handler } ;
77use rustc_fs_util:: fix_windows_verbatim_for_gcc;
88use rustc_hir:: def_id:: CrateNum ;
9+ use rustc_metadata:: find_native_static_library;
910use rustc_metadata:: fs:: { emit_metadata, METADATA_FILENAME } ;
1011use rustc_middle:: middle:: dependency_format:: Linkage ;
1112use rustc_middle:: middle:: exported_symbols:: SymbolExportKind ;
@@ -24,7 +25,7 @@ use rustc_target::spec::crt_objects::{CrtObjects, LinkSelfContainedDefault};
2425use rustc_target:: spec:: { LinkOutputKind , LinkerFlavor , LldFlavor , SplitDebuginfo } ;
2526use rustc_target:: spec:: { PanicStrategy , RelocModel , RelroLevel , SanitizerSet , Target } ;
2627
27- use super :: archive:: { find_library , ArchiveBuilder , ArchiveBuilderBuilder } ;
28+ use super :: archive:: { ArchiveBuilder , ArchiveBuilderBuilder } ;
2829use super :: command:: Command ;
2930use super :: linker:: { self , Linker } ;
3031use super :: metadata:: { create_rmeta_file, MetadataPosition } ;
@@ -307,6 +308,9 @@ fn link_rlib<'a>(
307308 }
308309 }
309310
311+ // Used if packed_bundled_libs flag enabled.
312+ let mut packed_bundled_libs = Vec :: new ( ) ;
313+
310314 // Note that in this loop we are ignoring the value of `lib.cfg`. That is,
311315 // we may not be configured to actually include a static library if we're
312316 // adding it here. That's because later when we consume this rlib we'll
@@ -325,6 +329,8 @@ fn link_rlib<'a>(
325329 // metadata of the rlib we're generating somehow.
326330 for lib in codegen_results. crate_info . used_libraries . iter ( ) {
327331 match lib. kind {
332+ NativeLibKind :: Static { bundle : None | Some ( true ) , whole_archive : Some ( true ) }
333+ if flavor == RlibFlavor :: Normal && sess. opts . unstable_opts . packed_bundled_libs => { }
328334 NativeLibKind :: Static { bundle : None | Some ( true ) , whole_archive : Some ( true ) }
329335 if flavor == RlibFlavor :: Normal =>
330336 {
@@ -348,7 +354,16 @@ fn link_rlib<'a>(
348354 }
349355 if let Some ( name) = lib. name {
350356 let location =
351- find_library ( name. as_str ( ) , lib. verbatim . unwrap_or ( false ) , & lib_search_paths, sess) ;
357+ find_native_static_library ( name. as_str ( ) , lib. verbatim , & lib_search_paths, sess) ;
358+ if sess. opts . unstable_opts . packed_bundled_libs && flavor == RlibFlavor :: Normal {
359+ packed_bundled_libs. push ( find_native_static_library (
360+ lib. filename . unwrap ( ) . as_str ( ) ,
361+ Some ( true ) ,
362+ & lib_search_paths,
363+ sess,
364+ ) ) ;
365+ continue ;
366+ }
352367 ab. add_archive ( & location, Box :: new ( |_| false ) ) . unwrap_or_else ( |e| {
353368 sess. fatal ( & format ! (
354369 "failed to add native library {}: {}" ,
@@ -403,6 +418,12 @@ fn link_rlib<'a>(
403418 ab. add_file ( & trailing_metadata) ;
404419 }
405420
421+ // Add all bundled static native library dependencies.
422+ // Archives added to the end of .rlib archive, see comment above for the reason.
423+ for lib in packed_bundled_libs {
424+ ab. add_file ( & lib)
425+ }
426+
406427 return Ok ( ab) ;
407428}
408429
@@ -2398,7 +2419,15 @@ fn add_upstream_rust_crates<'a>(
23982419 let src = & codegen_results. crate_info . used_crate_source [ & cnum] ;
23992420 match data[ cnum. as_usize ( ) - 1 ] {
24002421 _ if codegen_results. crate_info . profiler_runtime == Some ( cnum) => {
2401- add_static_crate ( cmd, sess, archive_builder_builder, codegen_results, tmpdir, cnum) ;
2422+ add_static_crate (
2423+ cmd,
2424+ sess,
2425+ archive_builder_builder,
2426+ codegen_results,
2427+ tmpdir,
2428+ cnum,
2429+ & Default :: default ( ) ,
2430+ ) ;
24022431 }
24032432 // compiler-builtins are always placed last to ensure that they're
24042433 // linked correctly.
@@ -2408,7 +2437,23 @@ fn add_upstream_rust_crates<'a>(
24082437 }
24092438 Linkage :: NotLinked | Linkage :: IncludedFromDylib => { }
24102439 Linkage :: Static => {
2411- add_static_crate ( cmd, sess, archive_builder_builder, codegen_results, tmpdir, cnum) ;
2440+ let bundled_libs = if sess. opts . unstable_opts . packed_bundled_libs {
2441+ codegen_results. crate_info . native_libraries [ & cnum]
2442+ . iter ( )
2443+ . filter_map ( |lib| lib. filename )
2444+ . collect :: < FxHashSet < _ > > ( )
2445+ } else {
2446+ Default :: default ( )
2447+ } ;
2448+ add_static_crate (
2449+ cmd,
2450+ sess,
2451+ archive_builder_builder,
2452+ codegen_results,
2453+ tmpdir,
2454+ cnum,
2455+ & bundled_libs,
2456+ ) ;
24122457
24132458 // Link static native libs with "-bundle" modifier only if the crate they originate from
24142459 // is being linked statically to the current crate. If it's linked dynamically
@@ -2419,6 +2464,14 @@ fn add_upstream_rust_crates<'a>(
24192464 // external build system already has the native dependencies defined, and it
24202465 // will provide them to the linker itself.
24212466 if sess. opts . unstable_opts . link_native_libraries {
2467+ if sess. opts . unstable_opts . packed_bundled_libs {
2468+ // If rlib contains native libs as archives, unpack them to tmpdir.
2469+ let rlib = & src. rlib . as_ref ( ) . unwrap ( ) . 0 ;
2470+ archive_builder_builder
2471+ . extract_bundled_libs ( rlib, tmpdir, & bundled_libs)
2472+ . unwrap_or_else ( |e| sess. fatal ( e) ) ;
2473+ }
2474+
24222475 let mut last = ( None , NativeLibKind :: Unspecified , None ) ;
24232476 for lib in & codegen_results. crate_info . native_libraries [ & cnum] {
24242477 let Some ( name) = lib. name else {
@@ -2460,10 +2513,17 @@ fn add_upstream_rust_crates<'a>(
24602513 | NativeLibKind :: Framework { .. }
24612514 | NativeLibKind :: Unspecified
24622515 | NativeLibKind :: RawDylib => { }
2463- NativeLibKind :: Static {
2464- bundle : Some ( true ) | None ,
2465- whole_archive : _,
2466- } => { }
2516+ NativeLibKind :: Static { bundle : Some ( true ) | None , whole_archive } => {
2517+ if sess. opts . unstable_opts . packed_bundled_libs {
2518+ // If rlib contains native libs as archives, they are unpacked to tmpdir.
2519+ let path = tmpdir. join ( lib. filename . unwrap ( ) . as_str ( ) ) ;
2520+ if whole_archive == Some ( true ) {
2521+ cmd. link_whole_rlib ( & path) ;
2522+ } else {
2523+ cmd. link_rlib ( & path) ;
2524+ }
2525+ }
2526+ }
24672527 }
24682528 }
24692529 }
@@ -2482,7 +2542,15 @@ fn add_upstream_rust_crates<'a>(
24822542 // was already "included" in a dylib (e.g., `libstd` when `-C prefer-dynamic`
24832543 // is used)
24842544 if let Some ( cnum) = compiler_builtins {
2485- add_static_crate ( cmd, sess, archive_builder_builder, codegen_results, tmpdir, cnum) ;
2545+ add_static_crate (
2546+ cmd,
2547+ sess,
2548+ archive_builder_builder,
2549+ codegen_results,
2550+ tmpdir,
2551+ cnum,
2552+ & Default :: default ( ) ,
2553+ ) ;
24862554 }
24872555
24882556 // Converts a library file-stem into a cc -l argument
@@ -2515,6 +2583,7 @@ fn add_upstream_rust_crates<'a>(
25152583 codegen_results : & CodegenResults ,
25162584 tmpdir : & Path ,
25172585 cnum : CrateNum ,
2586+ bundled_lib_file_names : & FxHashSet < Symbol > ,
25182587 ) {
25192588 let src = & codegen_results. crate_info . used_crate_source [ & cnum] ;
25202589 let cratepath = & src. rlib . as_ref ( ) . unwrap ( ) . 0 ;
@@ -2543,6 +2612,7 @@ fn add_upstream_rust_crates<'a>(
25432612 let dst = tmpdir. join ( cratepath. file_name ( ) . unwrap ( ) ) ;
25442613 let name = cratepath. file_name ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) ;
25452614 let name = & name[ 3 ..name. len ( ) - 5 ] ; // chop off lib/.rlib
2615+ let bundled_lib_file_names = bundled_lib_file_names. clone ( ) ;
25462616
25472617 sess. prof . generic_activity_with_arg ( "link_altering_rlib" , name) . run ( || {
25482618 let canonical_name = name. replace ( '-' , "_" ) ;
@@ -2576,6 +2646,15 @@ fn add_upstream_rust_crates<'a>(
25762646 let skip_because_lto =
25772647 upstream_rust_objects_already_included && is_rust_object && is_builtins;
25782648
2649+ // We skip native libraries because:
2650+ // 1. This native libraries won't be used from the generated rlib,
2651+ // so we can throw them away to avoid the copying work.
2652+ // 2. We can't allow it to be a single remaining entry in archive
2653+ // as some linkers may complain on that.
2654+ if bundled_lib_file_names. contains ( & Symbol :: intern ( f) ) {
2655+ return true ;
2656+ }
2657+
25792658 if skip_because_cfg_say_so || skip_because_lto {
25802659 return true ;
25812660 }
0 commit comments