@@ -24,7 +24,7 @@ use rustc_span::symbol::Symbol;
2424use rustc_span:: DebuggerVisualizerFile ;
2525use rustc_target:: spec:: crt_objects:: { CrtObjects , LinkSelfContainedDefault } ;
2626use 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 } ;
2828
2929use super :: archive:: { ArchiveBuilder , ArchiveBuilderBuilder } ;
3030use super :: command:: Command ;
@@ -2512,138 +2512,6 @@ fn add_upstream_rust_crates<'a>(
25122512 link_dynamic,
25132513 ) ;
25142514 }
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- }
26472515}
26482516
26492517fn add_upstream_native_libraries (
@@ -2684,6 +2552,132 @@ fn add_upstream_native_libraries(
26842552 }
26852553}
26862554
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+
26872681fn relevant_lib ( sess : & Session , lib : & NativeLib ) -> bool {
26882682 match lib. cfg {
26892683 Some ( ref cfg) => rustc_attr:: cfg_matches ( cfg, & sess. parse_sess , CRATE_NODE_ID , None ) ,
0 commit comments