@@ -24,7 +24,7 @@ use rustc_span::symbol::Symbol;
24
24
use rustc_span:: DebuggerVisualizerFile ;
25
25
use rustc_target:: spec:: crt_objects:: { CrtObjects , LinkSelfContainedDefault } ;
26
26
use rustc_target:: spec:: { Cc , LinkOutputKind , LinkerFlavor , LinkerFlavorCli , Lld , PanicStrategy } ;
27
- use rustc_target:: spec:: { RelocModel , RelroLevel , SanitizerSet , SplitDebuginfo , Target } ;
27
+ use rustc_target:: spec:: { RelocModel , RelroLevel , SanitizerSet , SplitDebuginfo } ;
28
28
29
29
use super :: archive:: { ArchiveBuilder , ArchiveBuilderBuilder } ;
30
30
use super :: command:: Command ;
@@ -2512,138 +2512,6 @@ fn add_upstream_rust_crates<'a>(
2512
2512
link_dynamic,
2513
2513
) ;
2514
2514
}
2515
-
2516
- // Converts a library file-stem into a cc -l argument
2517
- fn unlib < ' a > ( target : & Target , stem : & ' a str ) -> & ' a str {
2518
- if stem. starts_with ( "lib" ) && !target. is_like_windows { & stem[ 3 ..] } else { stem }
2519
- }
2520
-
2521
- // Adds the static "rlib" versions of all crates to the command line.
2522
- // There's a bit of magic which happens here specifically related to LTO,
2523
- // namely that we remove upstream object files.
2524
- //
2525
- // When performing LTO, almost(*) all of the bytecode from the upstream
2526
- // libraries has already been included in our object file output. As a
2527
- // result we need to remove the object files in the upstream libraries so
2528
- // the linker doesn't try to include them twice (or whine about duplicate
2529
- // symbols). We must continue to include the rest of the rlib, however, as
2530
- // it may contain static native libraries which must be linked in.
2531
- //
2532
- // (*) Crates marked with `#![no_builtins]` don't participate in LTO and
2533
- // their bytecode wasn't included. The object files in those libraries must
2534
- // still be passed to the linker.
2535
- //
2536
- // Note, however, that if we're not doing LTO we can just pass the rlib
2537
- // blindly to the linker (fast) because it's fine if it's not actually
2538
- // included as we're at the end of the dependency chain.
2539
- fn add_static_crate < ' a > (
2540
- cmd : & mut dyn Linker ,
2541
- sess : & ' a Session ,
2542
- archive_builder_builder : & dyn ArchiveBuilderBuilder ,
2543
- codegen_results : & CodegenResults ,
2544
- tmpdir : & Path ,
2545
- cnum : CrateNum ,
2546
- bundled_lib_file_names : & FxHashSet < Symbol > ,
2547
- ) {
2548
- let src = & codegen_results. crate_info . used_crate_source [ & cnum] ;
2549
- let cratepath = & src. rlib . as_ref ( ) . unwrap ( ) . 0 ;
2550
-
2551
- let mut link_upstream = |path : & Path | {
2552
- cmd. link_rlib ( & fix_windows_verbatim_for_gcc ( path) ) ;
2553
- } ;
2554
-
2555
- // See the comment above in `link_staticlib` and `link_rlib` for why if
2556
- // there's a static library that's not relevant we skip all object
2557
- // files.
2558
- let native_libs = & codegen_results. crate_info . native_libraries [ & cnum] ;
2559
- let skip_native = native_libs. iter ( ) . any ( |lib| {
2560
- matches ! ( lib. kind, NativeLibKind :: Static { bundle: None | Some ( true ) , .. } )
2561
- && !relevant_lib ( sess, lib)
2562
- } ) ;
2563
-
2564
- if ( !are_upstream_rust_objects_already_included ( sess)
2565
- || ignored_for_lto ( sess, & codegen_results. crate_info , cnum) )
2566
- && !skip_native
2567
- {
2568
- link_upstream ( cratepath) ;
2569
- return ;
2570
- }
2571
-
2572
- let dst = tmpdir. join ( cratepath. file_name ( ) . unwrap ( ) ) ;
2573
- let name = cratepath. file_name ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) ;
2574
- let name = & name[ 3 ..name. len ( ) - 5 ] ; // chop off lib/.rlib
2575
- let bundled_lib_file_names = bundled_lib_file_names. clone ( ) ;
2576
-
2577
- sess. prof . generic_activity_with_arg ( "link_altering_rlib" , name) . run ( || {
2578
- let canonical_name = name. replace ( '-' , "_" ) ;
2579
- let upstream_rust_objects_already_included =
2580
- are_upstream_rust_objects_already_included ( sess) ;
2581
- let is_builtins = sess. target . no_builtins
2582
- || !codegen_results. crate_info . is_no_builtins . contains ( & cnum) ;
2583
-
2584
- let mut archive = archive_builder_builder. new_archive_builder ( sess) ;
2585
- if let Err ( error) = archive. add_archive (
2586
- cratepath,
2587
- Box :: new ( move |f| {
2588
- if f == METADATA_FILENAME {
2589
- return true ;
2590
- }
2591
-
2592
- let canonical = f. replace ( '-' , "_" ) ;
2593
-
2594
- let is_rust_object =
2595
- canonical. starts_with ( & canonical_name) && looks_like_rust_object_file ( & f) ;
2596
-
2597
- // If we've been requested to skip all native object files
2598
- // (those not generated by the rust compiler) then we can skip
2599
- // this file. See above for why we may want to do this.
2600
- let skip_because_cfg_say_so = skip_native && !is_rust_object;
2601
-
2602
- // If we're performing LTO and this is a rust-generated object
2603
- // file, then we don't need the object file as it's part of the
2604
- // LTO module. Note that `#![no_builtins]` is excluded from LTO,
2605
- // though, so we let that object file slide.
2606
- let skip_because_lto =
2607
- upstream_rust_objects_already_included && is_rust_object && is_builtins;
2608
-
2609
- // We skip native libraries because:
2610
- // 1. This native libraries won't be used from the generated rlib,
2611
- // so we can throw them away to avoid the copying work.
2612
- // 2. We can't allow it to be a single remaining entry in archive
2613
- // as some linkers may complain on that.
2614
- if bundled_lib_file_names. contains ( & Symbol :: intern ( f) ) {
2615
- return true ;
2616
- }
2617
-
2618
- if skip_because_cfg_say_so || skip_because_lto {
2619
- return true ;
2620
- }
2621
-
2622
- false
2623
- } ) ,
2624
- ) {
2625
- sess. emit_fatal ( errors:: RlibArchiveBuildFailure { error } ) ;
2626
- }
2627
- if archive. build ( & dst) {
2628
- link_upstream ( & dst) ;
2629
- }
2630
- } ) ;
2631
- }
2632
-
2633
- // Same thing as above, but for dynamic crates instead of static crates.
2634
- fn add_dynamic_crate ( cmd : & mut dyn Linker , sess : & Session , cratepath : & Path ) {
2635
- // Just need to tell the linker about where the library lives and
2636
- // what its name is
2637
- let parent = cratepath. parent ( ) ;
2638
- if let Some ( dir) = parent {
2639
- cmd. include_path ( & fix_windows_verbatim_for_gcc ( dir) ) ;
2640
- }
2641
- let filestem = cratepath. file_stem ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) ;
2642
- cmd. link_rust_dylib (
2643
- & unlib ( & sess. target , filestem) ,
2644
- parent. unwrap_or_else ( || Path :: new ( "" ) ) ,
2645
- ) ;
2646
- }
2647
2515
}
2648
2516
2649
2517
fn add_upstream_native_libraries (
@@ -2684,6 +2552,132 @@ fn add_upstream_native_libraries(
2684
2552
}
2685
2553
}
2686
2554
2555
+ // Adds the static "rlib" versions of all crates to the command line.
2556
+ // There's a bit of magic which happens here specifically related to LTO,
2557
+ // namely that we remove upstream object files.
2558
+ //
2559
+ // When performing LTO, almost(*) all of the bytecode from the upstream
2560
+ // libraries has already been included in our object file output. As a
2561
+ // result we need to remove the object files in the upstream libraries so
2562
+ // the linker doesn't try to include them twice (or whine about duplicate
2563
+ // symbols). We must continue to include the rest of the rlib, however, as
2564
+ // it may contain static native libraries which must be linked in.
2565
+ //
2566
+ // (*) Crates marked with `#![no_builtins]` don't participate in LTO and
2567
+ // their bytecode wasn't included. The object files in those libraries must
2568
+ // still be passed to the linker.
2569
+ //
2570
+ // Note, however, that if we're not doing LTO we can just pass the rlib
2571
+ // blindly to the linker (fast) because it's fine if it's not actually
2572
+ // included as we're at the end of the dependency chain.
2573
+ fn add_static_crate < ' a > (
2574
+ cmd : & mut dyn Linker ,
2575
+ sess : & ' a Session ,
2576
+ archive_builder_builder : & dyn ArchiveBuilderBuilder ,
2577
+ codegen_results : & CodegenResults ,
2578
+ tmpdir : & Path ,
2579
+ cnum : CrateNum ,
2580
+ bundled_lib_file_names : & FxHashSet < Symbol > ,
2581
+ ) {
2582
+ let src = & codegen_results. crate_info . used_crate_source [ & cnum] ;
2583
+ let cratepath = & src. rlib . as_ref ( ) . unwrap ( ) . 0 ;
2584
+
2585
+ let mut link_upstream = |path : & Path | {
2586
+ cmd. link_rlib ( & fix_windows_verbatim_for_gcc ( path) ) ;
2587
+ } ;
2588
+
2589
+ // See the comment above in `link_staticlib` and `link_rlib` for why if
2590
+ // there's a static library that's not relevant we skip all object
2591
+ // files.
2592
+ let native_libs = & codegen_results. crate_info . native_libraries [ & cnum] ;
2593
+ let skip_native = native_libs. iter ( ) . any ( |lib| {
2594
+ matches ! ( lib. kind, NativeLibKind :: Static { bundle: None | Some ( true ) , .. } )
2595
+ && !relevant_lib ( sess, lib)
2596
+ } ) ;
2597
+
2598
+ if ( !are_upstream_rust_objects_already_included ( sess)
2599
+ || ignored_for_lto ( sess, & codegen_results. crate_info , cnum) )
2600
+ && !skip_native
2601
+ {
2602
+ link_upstream ( cratepath) ;
2603
+ return ;
2604
+ }
2605
+
2606
+ let dst = tmpdir. join ( cratepath. file_name ( ) . unwrap ( ) ) ;
2607
+ let name = cratepath. file_name ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) ;
2608
+ let name = & name[ 3 ..name. len ( ) - 5 ] ; // chop off lib/.rlib
2609
+ let bundled_lib_file_names = bundled_lib_file_names. clone ( ) ;
2610
+
2611
+ sess. prof . generic_activity_with_arg ( "link_altering_rlib" , name) . run ( || {
2612
+ let canonical_name = name. replace ( '-' , "_" ) ;
2613
+ let upstream_rust_objects_already_included =
2614
+ are_upstream_rust_objects_already_included ( sess) ;
2615
+ let is_builtins =
2616
+ sess. target . no_builtins || !codegen_results. crate_info . is_no_builtins . contains ( & cnum) ;
2617
+
2618
+ let mut archive = archive_builder_builder. new_archive_builder ( sess) ;
2619
+ if let Err ( e) = archive. add_archive (
2620
+ cratepath,
2621
+ Box :: new ( move |f| {
2622
+ if f == METADATA_FILENAME {
2623
+ return true ;
2624
+ }
2625
+
2626
+ let canonical = f. replace ( '-' , "_" ) ;
2627
+
2628
+ let is_rust_object =
2629
+ canonical. starts_with ( & canonical_name) && looks_like_rust_object_file ( & f) ;
2630
+
2631
+ // If we've been requested to skip all native object files
2632
+ // (those not generated by the rust compiler) then we can skip
2633
+ // this file. See above for why we may want to do this.
2634
+ let skip_because_cfg_say_so = skip_native && !is_rust_object;
2635
+
2636
+ // If we're performing LTO and this is a rust-generated object
2637
+ // file, then we don't need the object file as it's part of the
2638
+ // LTO module. Note that `#![no_builtins]` is excluded from LTO,
2639
+ // though, so we let that object file slide.
2640
+ let skip_because_lto =
2641
+ upstream_rust_objects_already_included && is_rust_object && is_builtins;
2642
+
2643
+ // We skip native libraries because:
2644
+ // 1. This native libraries won't be used from the generated rlib,
2645
+ // so we can throw them away to avoid the copying work.
2646
+ // 2. We can't allow it to be a single remaining entry in archive
2647
+ // as some linkers may complain on that.
2648
+ if bundled_lib_file_names. contains ( & Symbol :: intern ( f) ) {
2649
+ return true ;
2650
+ }
2651
+
2652
+ if skip_because_cfg_say_so || skip_because_lto {
2653
+ return true ;
2654
+ }
2655
+
2656
+ false
2657
+ } ) ,
2658
+ ) {
2659
+ sess. fatal ( & format ! ( "failed to build archive from rlib: {}" , e) ) ;
2660
+ }
2661
+ if archive. build ( & dst) {
2662
+ link_upstream ( & dst) ;
2663
+ }
2664
+ } ) ;
2665
+ }
2666
+
2667
+ // Same thing as above, but for dynamic crates instead of static crates.
2668
+ fn add_dynamic_crate ( cmd : & mut dyn Linker , sess : & Session , cratepath : & Path ) {
2669
+ // Just need to tell the linker about where the library lives and
2670
+ // what its name is
2671
+ let parent = cratepath. parent ( ) ;
2672
+ if let Some ( dir) = parent {
2673
+ cmd. include_path ( & fix_windows_verbatim_for_gcc ( dir) ) ;
2674
+ }
2675
+ let stem = cratepath. file_stem ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) ;
2676
+ // Convert library file-stem into a cc -l argument.
2677
+ let prefix = if stem. starts_with ( "lib" ) && !sess. target . is_like_windows { 3 } else { 0 } ;
2678
+ cmd. link_rust_dylib ( & stem[ prefix..] , parent. unwrap_or_else ( || Path :: new ( "" ) ) ) ;
2679
+ }
2680
+
2687
2681
fn relevant_lib ( sess : & Session , lib : & NativeLib ) -> bool {
2688
2682
match lib. cfg {
2689
2683
Some ( ref cfg) => rustc_attr:: cfg_matches ( cfg, & sess. parse_sess , CRATE_NODE_ID , None ) ,
0 commit comments