@@ -11,6 +11,7 @@ use rustc_metadata::fs::{copy_to_stdout, emit_wrapper_file, METADATA_FILENAME};
1111use rustc_middle:: middle:: debugger_visualizer:: DebuggerVisualizerFile ;
1212use rustc_middle:: middle:: dependency_format:: Linkage ;
1313use rustc_middle:: middle:: exported_symbols:: SymbolExportKind ;
14+ use rustc_session:: config:: LinkerFeaturesCli ;
1415use rustc_session:: config:: { self , CFGuard , CrateType , DebugInfo , OutFileName , Strip } ;
1516use rustc_session:: config:: { OutputFilenames , OutputType , PrintKind , SplitDwarfKind } ;
1617use rustc_session:: cstore:: DllImport ;
@@ -22,10 +23,10 @@ use rustc_session::utils::NativeLibKind;
2223use rustc_session:: { filesearch, Session } ;
2324use rustc_span:: symbol:: Symbol ;
2425use rustc_target:: spec:: crt_objects:: CrtObjects ;
25- use rustc_target:: spec:: LinkSelfContainedComponents ;
2626use rustc_target:: spec:: LinkSelfContainedDefault ;
2727use rustc_target:: spec:: LinkerFlavorCli ;
2828use rustc_target:: spec:: { Cc , LinkOutputKind , LinkerFlavor , Lld , PanicStrategy } ;
29+ use rustc_target:: spec:: { LinkSelfContainedComponents , LinkerFeatures } ;
2930use rustc_target:: spec:: { RelocModel , RelroLevel , SanitizerSet , SplitDebuginfo } ;
3031
3132use super :: archive:: { ArchiveBuilder , ArchiveBuilderBuilder } ;
@@ -76,8 +77,8 @@ pub fn ensure_removed(dcx: &DiagCtxt, path: &Path) {
7677
7778/// Performs the linkage portion of the compilation phase. This will generate all
7879/// of the requested outputs for this compilation session.
79- pub fn link_binary < ' a > (
80- sess : & ' a Session ,
80+ pub fn link_binary (
81+ sess : & Session ,
8182 archive_builder_builder : & dyn ArchiveBuilderBuilder ,
8283 codegen_results : & CodegenResults ,
8384 outputs : & OutputFilenames ,
@@ -465,9 +466,9 @@ fn link_rlib<'a>(
465466/// then the CodegenResults value contains one NativeLib instance for each block. However, the
466467/// linker appears to expect only a single import library for each library used, so we need to
467468/// collate the symbols together by library name before generating the import libraries.
468- fn collate_raw_dylibs < ' a , ' b > (
469- sess : & ' a Session ,
470- used_libraries : impl IntoIterator < Item = & ' b NativeLib > ,
469+ fn collate_raw_dylibs < ' a > (
470+ sess : & Session ,
471+ used_libraries : impl IntoIterator < Item = & ' a NativeLib > ,
471472) -> Result < Vec < ( String , Vec < DllImport > ) > , ErrorGuaranteed > {
472473 // Use index maps to preserve original order of imports and libraries.
473474 let mut dylib_table = FxIndexMap :: < String , FxIndexMap < Symbol , & DllImport > > :: default ( ) ;
@@ -514,8 +515,8 @@ fn collate_raw_dylibs<'a, 'b>(
514515///
515516/// There's no need to include metadata in a static archive, so ensure to not link in the metadata
516517/// object file (and also don't prepare the archive with a metadata file).
517- fn link_staticlib < ' a > (
518- sess : & ' a Session ,
518+ fn link_staticlib (
519+ sess : & Session ,
519520 archive_builder_builder : & dyn ArchiveBuilderBuilder ,
520521 codegen_results : & CodegenResults ,
521522 out_filename : & Path ,
@@ -627,11 +628,7 @@ fn link_staticlib<'a>(
627628
628629/// Use `thorin` (rust implementation of a dwarf packaging utility) to link DWARF objects into a
629630/// DWARF package.
630- fn link_dwarf_object < ' a > (
631- sess : & ' a Session ,
632- cg_results : & CodegenResults ,
633- executable_out_filename : & Path ,
634- ) {
631+ fn link_dwarf_object ( sess : & Session , cg_results : & CodegenResults , executable_out_filename : & Path ) {
635632 let mut dwp_out_filename = executable_out_filename. to_path_buf ( ) . into_os_string ( ) ;
636633 dwp_out_filename. push ( ".dwp" ) ;
637634 debug ! ( ?dwp_out_filename, ?executable_out_filename) ;
@@ -735,8 +732,8 @@ fn link_dwarf_object<'a>(
735732///
736733/// This will invoke the system linker/cc to create the resulting file. This links to all upstream
737734/// files as well.
738- fn link_natively < ' a > (
739- sess : & ' a Session ,
735+ fn link_natively (
736+ sess : & Session ,
740737 archive_builder_builder : & dyn ArchiveBuilderBuilder ,
741738 crate_type : CrateType ,
742739 out_filename : & Path ,
@@ -1100,8 +1097,8 @@ fn link_natively<'a>(
11001097 Ok ( ( ) )
11011098}
11021099
1103- fn strip_symbols_with_external_utility < ' a > (
1104- sess : & ' a Session ,
1100+ fn strip_symbols_with_external_utility (
1101+ sess : & Session ,
11051102 util : & str ,
11061103 out_filename : & Path ,
11071104 option : Option < & str > ,
@@ -1338,7 +1335,9 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
13381335 sess : & Session ,
13391336 linker : Option < PathBuf > ,
13401337 flavor : Option < LinkerFlavor > ,
1338+ features : LinkerFeaturesCli ,
13411339 ) -> Option < ( PathBuf , LinkerFlavor ) > {
1340+ let flavor = flavor. map ( |flavor| adjust_flavor_to_features ( flavor, features) ) ;
13421341 match ( linker, flavor) {
13431342 ( Some ( linker) , Some ( flavor) ) => Some ( ( linker, flavor) ) ,
13441343 // only the linker flavor is known; use the default linker for the selected flavor
@@ -1386,12 +1385,33 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
13861385 sess. dcx ( ) . emit_fatal ( errors:: LinkerFileStem ) ;
13871386 } ) ;
13881387 let flavor = sess. target . linker_flavor . with_linker_hints ( stem) ;
1388+ let flavor = adjust_flavor_to_features ( flavor, features) ;
13891389 Some ( ( linker, flavor) )
13901390 }
13911391 ( None , None ) => None ,
13921392 }
13931393 }
13941394
1395+ // While linker flavors and linker features are isomorphic (and thus targets don't need to
1396+ // define features separately), we use the flavor as the root piece of data and have the
1397+ // linker-features CLI flag influence *that*, so that downstream code does not have to check for
1398+ // both yet.
1399+ fn adjust_flavor_to_features (
1400+ flavor : LinkerFlavor ,
1401+ features : LinkerFeaturesCli ,
1402+ ) -> LinkerFlavor {
1403+ // Note: a linker feature cannot be both enabled and disabled on the CLI.
1404+ if features. enabled . contains ( LinkerFeatures :: LLD ) {
1405+ flavor. with_lld_enabled ( )
1406+ } else if features. disabled . contains ( LinkerFeatures :: LLD ) {
1407+ flavor. with_lld_disabled ( )
1408+ } else {
1409+ flavor
1410+ }
1411+ }
1412+
1413+ let features = sess. opts . unstable_opts . linker_features ;
1414+
13951415 // linker and linker flavor specified via command line have precedence over what the target
13961416 // specification specifies
13971417 let linker_flavor = match sess. opts . cg . linker_flavor {
@@ -1405,14 +1425,15 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
14051425 . linker_flavor
14061426 . map ( |flavor| sess. target . linker_flavor . with_cli_hints ( flavor) ) ,
14071427 } ;
1408- if let Some ( ret) = infer_from ( sess, sess. opts . cg . linker . clone ( ) , linker_flavor) {
1428+ if let Some ( ret) = infer_from ( sess, sess. opts . cg . linker . clone ( ) , linker_flavor, features ) {
14091429 return ret;
14101430 }
14111431
14121432 if let Some ( ret) = infer_from (
14131433 sess,
14141434 sess. target . linker . as_deref ( ) . map ( PathBuf :: from) ,
14151435 Some ( sess. target . linker_flavor ) ,
1436+ features,
14161437 ) {
14171438 return ret;
14181439 }
@@ -2105,10 +2126,10 @@ fn add_rpath_args(
21052126/// to the linking process as a whole.
21062127/// Order-independent options may still override each other in order-dependent fashion,
21072128/// e.g `--foo=yes --foo=no` may be equivalent to `--foo=no`.
2108- fn linker_with_args < ' a > (
2129+ fn linker_with_args (
21092130 path : & Path ,
21102131 flavor : LinkerFlavor ,
2111- sess : & ' a Session ,
2132+ sess : & Session ,
21122133 archive_builder_builder : & dyn ArchiveBuilderBuilder ,
21132134 crate_type : CrateType ,
21142135 tmpdir : & Path ,
@@ -2640,9 +2661,9 @@ fn add_local_native_libraries(
26402661 ) ;
26412662}
26422663
2643- fn add_upstream_rust_crates < ' a > (
2664+ fn add_upstream_rust_crates (
26442665 cmd : & mut dyn Linker ,
2645- sess : & ' a Session ,
2666+ sess : & Session ,
26462667 archive_builder_builder : & dyn ArchiveBuilderBuilder ,
26472668 codegen_results : & CodegenResults ,
26482669 crate_type : CrateType ,
@@ -2779,7 +2800,7 @@ fn add_upstream_native_libraries(
27792800// file generated by the MSVC linker. See https://github.com/rust-lang/rust/issues/112586.
27802801//
27812802// The returned path will always have `fix_windows_verbatim_for_gcc()` applied to it.
2782- fn rehome_sysroot_lib_dir < ' a > ( sess : & ' a Session , lib_dir : & Path ) -> PathBuf {
2803+ fn rehome_sysroot_lib_dir ( sess : & Session , lib_dir : & Path ) -> PathBuf {
27832804 let sysroot_lib_path = sess. target_filesearch ( PathKind :: All ) . get_lib_path ( ) ;
27842805 let canonical_sysroot_lib_path =
27852806 { try_canonicalize ( & sysroot_lib_path) . unwrap_or_else ( |_| sysroot_lib_path. clone ( ) ) } ;
@@ -2812,9 +2833,9 @@ fn rehome_sysroot_lib_dir<'a>(sess: &'a Session, lib_dir: &Path) -> PathBuf {
28122833// Note, however, that if we're not doing LTO we can just pass the rlib
28132834// blindly to the linker (fast) because it's fine if it's not actually
28142835// included as we're at the end of the dependency chain.
2815- fn add_static_crate < ' a > (
2836+ fn add_static_crate (
28162837 cmd : & mut dyn Linker ,
2817- sess : & ' a Session ,
2838+ sess : & Session ,
28182839 archive_builder_builder : & dyn ArchiveBuilderBuilder ,
28192840 codegen_results : & CodegenResults ,
28202841 tmpdir : & Path ,
0 commit comments