@@ -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