11use rustc_arena:: TypedArena ;
22use rustc_ast:: CRATE_NODE_ID ;
3+ use rustc_data_structures:: fx:: FxHashSet ;
34use rustc_data_structures:: fx:: FxIndexMap ;
45use rustc_data_structures:: memmap:: Mmap ;
56use rustc_data_structures:: temp_dir:: MaybeTempDir ;
67use rustc_errors:: { ErrorGuaranteed , Handler } ;
78use rustc_fs_util:: fix_windows_verbatim_for_gcc;
89use rustc_hir:: def_id:: CrateNum ;
10+ use rustc_metadata:: find_native_static_library;
911use rustc_metadata:: fs:: { emit_metadata, METADATA_FILENAME } ;
1012use rustc_middle:: middle:: dependency_format:: Linkage ;
1113use rustc_middle:: middle:: exported_symbols:: SymbolExportKind ;
@@ -24,7 +26,7 @@ use rustc_target::spec::crt_objects::{CrtObjects, LinkSelfContainedDefault};
2426use rustc_target:: spec:: { LinkOutputKind , LinkerFlavor , LldFlavor , SplitDebuginfo } ;
2527use rustc_target:: spec:: { PanicStrategy , RelocModel , RelroLevel , SanitizerSet , Target } ;
2628
27- use super :: archive:: { find_library , ArchiveBuilder , ArchiveBuilderBuilder } ;
29+ use super :: archive:: { ArchiveBuilder , ArchiveBuilderBuilder } ;
2830use super :: command:: Command ;
2931use super :: linker:: { self , Linker } ;
3032use super :: metadata:: { create_rmeta_file, MetadataPosition } ;
@@ -307,6 +309,9 @@ fn link_rlib<'a>(
307309 }
308310 }
309311
312+ // Used if packed_bundled_libs flag enabled.
313+ let mut packed_bundled_libs = Vec :: new ( ) ;
314+
310315 // Note that in this loop we are ignoring the value of `lib.cfg`. That is,
311316 // we may not be configured to actually include a static library if we're
312317 // adding it here. That's because later when we consume this rlib we'll
@@ -325,6 +330,8 @@ fn link_rlib<'a>(
325330 // metadata of the rlib we're generating somehow.
326331 for lib in codegen_results. crate_info . used_libraries . iter ( ) {
327332 match lib. kind {
333+ NativeLibKind :: Static { bundle : None | Some ( true ) , whole_archive : Some ( true ) }
334+ if flavor == RlibFlavor :: Normal && sess. opts . unstable_opts . packed_bundled_libs => { }
328335 NativeLibKind :: Static { bundle : None | Some ( true ) , whole_archive : Some ( true ) }
329336 if flavor == RlibFlavor :: Normal =>
330337 {
@@ -348,7 +355,16 @@ fn link_rlib<'a>(
348355 }
349356 if let Some ( name) = lib. name {
350357 let location =
351- find_library ( name. as_str ( ) , lib. verbatim . unwrap_or ( false ) , & lib_search_paths, sess) ;
358+ find_native_static_library ( name. as_str ( ) , lib. verbatim , & lib_search_paths, sess) ;
359+ if sess. opts . unstable_opts . packed_bundled_libs && flavor == RlibFlavor :: Normal {
360+ packed_bundled_libs. push ( find_native_static_library (
361+ lib. filename . unwrap ( ) . as_str ( ) ,
362+ Some ( true ) ,
363+ & lib_search_paths,
364+ sess,
365+ ) ) ;
366+ continue ;
367+ }
352368 ab. add_archive ( & location, Box :: new ( |_| false ) ) . unwrap_or_else ( |e| {
353369 sess. fatal ( & format ! (
354370 "failed to add native library {}: {}" ,
@@ -403,6 +419,12 @@ fn link_rlib<'a>(
403419 ab. add_file ( & trailing_metadata) ;
404420 }
405421
422+ // Add all bundled static native library dependencies.
423+ // Archives added to the end of .rlib archive, see comment above for the reason.
424+ for lib in packed_bundled_libs {
425+ ab. add_file ( & lib)
426+ }
427+
406428 return Ok ( ab) ;
407429}
408430
@@ -2341,7 +2363,15 @@ fn add_upstream_rust_crates<'a>(
23412363 let src = & codegen_results. crate_info . used_crate_source [ & cnum] ;
23422364 match data[ cnum. as_usize ( ) - 1 ] {
23432365 _ if codegen_results. crate_info . profiler_runtime == Some ( cnum) => {
2344- add_static_crate ( cmd, sess, archive_builder_builder, codegen_results, tmpdir, cnum) ;
2366+ add_static_crate (
2367+ cmd,
2368+ sess,
2369+ archive_builder_builder,
2370+ codegen_results,
2371+ tmpdir,
2372+ cnum,
2373+ & Default :: default ( ) ,
2374+ ) ;
23452375 }
23462376 // compiler-builtins are always placed last to ensure that they're
23472377 // linked correctly.
@@ -2351,7 +2381,23 @@ fn add_upstream_rust_crates<'a>(
23512381 }
23522382 Linkage :: NotLinked | Linkage :: IncludedFromDylib => { }
23532383 Linkage :: Static => {
2354- add_static_crate ( cmd, sess, archive_builder_builder, codegen_results, tmpdir, cnum) ;
2384+ let bundled_libs = if sess. opts . unstable_opts . packed_bundled_libs {
2385+ codegen_results. crate_info . native_libraries [ & cnum]
2386+ . iter ( )
2387+ . filter_map ( |lib| lib. filename )
2388+ . collect :: < FxHashSet < _ > > ( )
2389+ } else {
2390+ Default :: default ( )
2391+ } ;
2392+ add_static_crate (
2393+ cmd,
2394+ sess,
2395+ archive_builder_builder,
2396+ codegen_results,
2397+ tmpdir,
2398+ cnum,
2399+ & bundled_libs,
2400+ ) ;
23552401
23562402 // Link static native libs with "-bundle" modifier only if the crate they originate from
23572403 // is being linked statically to the current crate. If it's linked dynamically
@@ -2362,6 +2408,14 @@ fn add_upstream_rust_crates<'a>(
23622408 // external build system already has the native dependencies defined, and it
23632409 // will provide them to the linker itself.
23642410 if sess. opts . unstable_opts . link_native_libraries {
2411+ if sess. opts . unstable_opts . packed_bundled_libs {
2412+ // If rlib contains native libs as archives, unpack them to tmpdir.
2413+ let rlib = & src. rlib . as_ref ( ) . unwrap ( ) . 0 ;
2414+ archive_builder_builder
2415+ . extract_bundled_libs ( rlib, tmpdir, & bundled_libs)
2416+ . unwrap_or_else ( |e| sess. fatal ( e) ) ;
2417+ }
2418+
23652419 let mut last = ( None , NativeLibKind :: Unspecified , None ) ;
23662420 for lib in & codegen_results. crate_info . native_libraries [ & cnum] {
23672421 let Some ( name) = lib. name else {
@@ -2411,10 +2465,17 @@ fn add_upstream_rust_crates<'a>(
24112465 | NativeLibKind :: Framework { .. }
24122466 | NativeLibKind :: Unspecified
24132467 | NativeLibKind :: RawDylib => { }
2414- NativeLibKind :: Static {
2415- bundle : Some ( true ) | None ,
2416- whole_archive : _,
2417- } => { }
2468+ NativeLibKind :: Static { bundle : Some ( true ) | None , whole_archive } => {
2469+ if sess. opts . unstable_opts . packed_bundled_libs {
2470+ // If rlib contains native libs as archives, they are unpacked to tmpdir.
2471+ let path = tmpdir. join ( lib. filename . unwrap ( ) . as_str ( ) ) ;
2472+ if whole_archive == Some ( true ) {
2473+ cmd. link_whole_rlib ( & path) ;
2474+ } else {
2475+ cmd. link_rlib ( & path) ;
2476+ }
2477+ }
2478+ }
24182479 }
24192480 }
24202481 }
@@ -2429,7 +2490,15 @@ fn add_upstream_rust_crates<'a>(
24292490 // was already "included" in a dylib (e.g., `libstd` when `-C prefer-dynamic`
24302491 // is used)
24312492 if let Some ( cnum) = compiler_builtins {
2432- add_static_crate ( cmd, sess, archive_builder_builder, codegen_results, tmpdir, cnum) ;
2493+ add_static_crate (
2494+ cmd,
2495+ sess,
2496+ archive_builder_builder,
2497+ codegen_results,
2498+ tmpdir,
2499+ cnum,
2500+ & Default :: default ( ) ,
2501+ ) ;
24332502 }
24342503
24352504 // Converts a library file-stem into a cc -l argument
@@ -2462,6 +2531,7 @@ fn add_upstream_rust_crates<'a>(
24622531 codegen_results : & CodegenResults ,
24632532 tmpdir : & Path ,
24642533 cnum : CrateNum ,
2534+ bundled_lib_file_names : & FxHashSet < Symbol > ,
24652535 ) {
24662536 let src = & codegen_results. crate_info . used_crate_source [ & cnum] ;
24672537 let cratepath = & src. rlib . as_ref ( ) . unwrap ( ) . 0 ;
@@ -2490,6 +2560,7 @@ fn add_upstream_rust_crates<'a>(
24902560 let dst = tmpdir. join ( cratepath. file_name ( ) . unwrap ( ) ) ;
24912561 let name = cratepath. file_name ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) ;
24922562 let name = & name[ 3 ..name. len ( ) - 5 ] ; // chop off lib/.rlib
2563+ let bundled_lib_file_names = bundled_lib_file_names. clone ( ) ;
24932564
24942565 sess. prof . generic_activity_with_arg ( "link_altering_rlib" , name) . run ( || {
24952566 let canonical_name = name. replace ( '-' , "_" ) ;
@@ -2523,6 +2594,15 @@ fn add_upstream_rust_crates<'a>(
25232594 let skip_because_lto =
25242595 upstream_rust_objects_already_included && is_rust_object && is_builtins;
25252596
2597+ // We skip native libraries because:
2598+ // 1. This native libraries won't be used from the generated rlib,
2599+ // so we can throw them away to avoid the copying work.
2600+ // 2. We can't allow it to be a single remaining entry in archive
2601+ // as some linkers may complain on that.
2602+ if bundled_lib_file_names. contains ( & Symbol :: intern ( f) ) {
2603+ return true ;
2604+ }
2605+
25262606 if skip_because_cfg_say_so || skip_because_lto {
25272607 return true ;
25282608 }
0 commit comments