1
1
use rustc_arena:: TypedArena ;
2
2
use rustc_ast:: CRATE_NODE_ID ;
3
+ use rustc_data_structures:: fx:: FxHashSet ;
3
4
use rustc_data_structures:: fx:: FxIndexMap ;
4
5
use rustc_data_structures:: memmap:: Mmap ;
5
6
use rustc_data_structures:: temp_dir:: MaybeTempDir ;
6
7
use rustc_errors:: { ErrorGuaranteed , Handler } ;
7
8
use rustc_fs_util:: fix_windows_verbatim_for_gcc;
8
9
use rustc_hir:: def_id:: CrateNum ;
10
+ use rustc_metadata:: find_native_static_library;
9
11
use rustc_metadata:: fs:: { emit_metadata, METADATA_FILENAME } ;
10
12
use rustc_middle:: middle:: dependency_format:: Linkage ;
11
13
use rustc_middle:: middle:: exported_symbols:: SymbolExportKind ;
@@ -24,7 +26,7 @@ use rustc_target::spec::crt_objects::{CrtObjects, LinkSelfContainedDefault};
24
26
use rustc_target:: spec:: { LinkOutputKind , LinkerFlavor , LldFlavor , SplitDebuginfo } ;
25
27
use rustc_target:: spec:: { PanicStrategy , RelocModel , RelroLevel , SanitizerSet , Target } ;
26
28
27
- use super :: archive:: { find_library , ArchiveBuilder , ArchiveBuilderBuilder } ;
29
+ use super :: archive:: { ArchiveBuilder , ArchiveBuilderBuilder } ;
28
30
use super :: command:: Command ;
29
31
use super :: linker:: { self , Linker } ;
30
32
use super :: metadata:: { create_rmeta_file, MetadataPosition } ;
@@ -307,6 +309,9 @@ fn link_rlib<'a>(
307
309
}
308
310
}
309
311
312
+ // Used if packed_bundled_libs flag enabled.
313
+ let mut packed_bundled_libs = Vec :: new ( ) ;
314
+
310
315
// Note that in this loop we are ignoring the value of `lib.cfg`. That is,
311
316
// we may not be configured to actually include a static library if we're
312
317
// adding it here. That's because later when we consume this rlib we'll
@@ -325,6 +330,8 @@ fn link_rlib<'a>(
325
330
// metadata of the rlib we're generating somehow.
326
331
for lib in codegen_results. crate_info . used_libraries . iter ( ) {
327
332
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 => { }
328
335
NativeLibKind :: Static { bundle : None | Some ( true ) , whole_archive : Some ( true ) }
329
336
if flavor == RlibFlavor :: Normal =>
330
337
{
@@ -348,7 +355,16 @@ fn link_rlib<'a>(
348
355
}
349
356
if let Some ( name) = lib. name {
350
357
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
+ }
352
368
ab. add_archive ( & location, Box :: new ( |_| false ) ) . unwrap_or_else ( |e| {
353
369
sess. fatal ( & format ! (
354
370
"failed to add native library {}: {}" ,
@@ -403,6 +419,12 @@ fn link_rlib<'a>(
403
419
ab. add_file ( & trailing_metadata) ;
404
420
}
405
421
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
+
406
428
return Ok ( ab) ;
407
429
}
408
430
@@ -2341,7 +2363,15 @@ fn add_upstream_rust_crates<'a>(
2341
2363
let src = & codegen_results. crate_info . used_crate_source [ & cnum] ;
2342
2364
match data[ cnum. as_usize ( ) - 1 ] {
2343
2365
_ 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
+ ) ;
2345
2375
}
2346
2376
// compiler-builtins are always placed last to ensure that they're
2347
2377
// linked correctly.
@@ -2351,7 +2381,23 @@ fn add_upstream_rust_crates<'a>(
2351
2381
}
2352
2382
Linkage :: NotLinked | Linkage :: IncludedFromDylib => { }
2353
2383
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
+ ) ;
2355
2401
2356
2402
// Link static native libs with "-bundle" modifier only if the crate they originate from
2357
2403
// is being linked statically to the current crate. If it's linked dynamically
@@ -2362,6 +2408,14 @@ fn add_upstream_rust_crates<'a>(
2362
2408
// external build system already has the native dependencies defined, and it
2363
2409
// will provide them to the linker itself.
2364
2410
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
+
2365
2419
let mut last = ( None , NativeLibKind :: Unspecified , None ) ;
2366
2420
for lib in & codegen_results. crate_info . native_libraries [ & cnum] {
2367
2421
let Some ( name) = lib. name else {
@@ -2411,10 +2465,17 @@ fn add_upstream_rust_crates<'a>(
2411
2465
| NativeLibKind :: Framework { .. }
2412
2466
| NativeLibKind :: Unspecified
2413
2467
| 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
+ }
2418
2479
}
2419
2480
}
2420
2481
}
@@ -2429,7 +2490,15 @@ fn add_upstream_rust_crates<'a>(
2429
2490
// was already "included" in a dylib (e.g., `libstd` when `-C prefer-dynamic`
2430
2491
// is used)
2431
2492
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
+ ) ;
2433
2502
}
2434
2503
2435
2504
// Converts a library file-stem into a cc -l argument
@@ -2462,6 +2531,7 @@ fn add_upstream_rust_crates<'a>(
2462
2531
codegen_results : & CodegenResults ,
2463
2532
tmpdir : & Path ,
2464
2533
cnum : CrateNum ,
2534
+ bundled_lib_file_names : & FxHashSet < Symbol > ,
2465
2535
) {
2466
2536
let src = & codegen_results. crate_info . used_crate_source [ & cnum] ;
2467
2537
let cratepath = & src. rlib . as_ref ( ) . unwrap ( ) . 0 ;
@@ -2490,6 +2560,7 @@ fn add_upstream_rust_crates<'a>(
2490
2560
let dst = tmpdir. join ( cratepath. file_name ( ) . unwrap ( ) ) ;
2491
2561
let name = cratepath. file_name ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) ;
2492
2562
let name = & name[ 3 ..name. len ( ) - 5 ] ; // chop off lib/.rlib
2563
+ let bundled_lib_file_names = bundled_lib_file_names. clone ( ) ;
2493
2564
2494
2565
sess. prof . generic_activity_with_arg ( "link_altering_rlib" , name) . run ( || {
2495
2566
let canonical_name = name. replace ( '-' , "_" ) ;
@@ -2523,6 +2594,15 @@ fn add_upstream_rust_crates<'a>(
2523
2594
let skip_because_lto =
2524
2595
upstream_rust_objects_already_included && is_rust_object && is_builtins;
2525
2596
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
+
2526
2606
if skip_because_cfg_say_so || skip_because_lto {
2527
2607
return true ;
2528
2608
}
0 commit comments