@@ -11,6 +11,7 @@ use rustc_metadata::fs::{copy_to_stdout, emit_wrapper_file, METADATA_FILENAME};
11
11
use rustc_middle:: middle:: debugger_visualizer:: DebuggerVisualizerFile ;
12
12
use rustc_middle:: middle:: dependency_format:: Linkage ;
13
13
use rustc_middle:: middle:: exported_symbols:: SymbolExportKind ;
14
+ use rustc_session:: config:: LinkerFeaturesCli ;
14
15
use rustc_session:: config:: { self , CFGuard , CrateType , DebugInfo , OutFileName , Strip } ;
15
16
use rustc_session:: config:: { OutputFilenames , OutputType , PrintKind , SplitDwarfKind } ;
16
17
use rustc_session:: cstore:: DllImport ;
@@ -22,10 +23,10 @@ use rustc_session::utils::NativeLibKind;
22
23
use rustc_session:: { filesearch, Session } ;
23
24
use rustc_span:: symbol:: Symbol ;
24
25
use rustc_target:: spec:: crt_objects:: CrtObjects ;
25
- use rustc_target:: spec:: LinkSelfContainedComponents ;
26
26
use rustc_target:: spec:: LinkSelfContainedDefault ;
27
27
use rustc_target:: spec:: LinkerFlavorCli ;
28
28
use rustc_target:: spec:: { Cc , LinkOutputKind , LinkerFlavor , Lld , PanicStrategy } ;
29
+ use rustc_target:: spec:: { LinkSelfContainedComponents , LinkerFeatures } ;
29
30
use rustc_target:: spec:: { RelocModel , RelroLevel , SanitizerSet , SplitDebuginfo } ;
30
31
31
32
use super :: archive:: { ArchiveBuilder , ArchiveBuilderBuilder } ;
@@ -76,8 +77,8 @@ pub fn ensure_removed(dcx: &DiagCtxt, path: &Path) {
76
77
77
78
/// Performs the linkage portion of the compilation phase. This will generate all
78
79
/// 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 ,
81
82
archive_builder_builder : & dyn ArchiveBuilderBuilder ,
82
83
codegen_results : & CodegenResults ,
83
84
outputs : & OutputFilenames ,
@@ -465,9 +466,9 @@ fn link_rlib<'a>(
465
466
/// then the CodegenResults value contains one NativeLib instance for each block. However, the
466
467
/// linker appears to expect only a single import library for each library used, so we need to
467
468
/// 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 > ,
471
472
) -> Result < Vec < ( String , Vec < DllImport > ) > , ErrorGuaranteed > {
472
473
// Use index maps to preserve original order of imports and libraries.
473
474
let mut dylib_table = FxIndexMap :: < String , FxIndexMap < Symbol , & DllImport > > :: default ( ) ;
@@ -514,8 +515,8 @@ fn collate_raw_dylibs<'a, 'b>(
514
515
///
515
516
/// There's no need to include metadata in a static archive, so ensure to not link in the metadata
516
517
/// 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 ,
519
520
archive_builder_builder : & dyn ArchiveBuilderBuilder ,
520
521
codegen_results : & CodegenResults ,
521
522
out_filename : & Path ,
@@ -627,11 +628,7 @@ fn link_staticlib<'a>(
627
628
628
629
/// Use `thorin` (rust implementation of a dwarf packaging utility) to link DWARF objects into a
629
630
/// 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 ) {
635
632
let mut dwp_out_filename = executable_out_filename. to_path_buf ( ) . into_os_string ( ) ;
636
633
dwp_out_filename. push ( ".dwp" ) ;
637
634
debug ! ( ?dwp_out_filename, ?executable_out_filename) ;
@@ -735,8 +732,8 @@ fn link_dwarf_object<'a>(
735
732
///
736
733
/// This will invoke the system linker/cc to create the resulting file. This links to all upstream
737
734
/// files as well.
738
- fn link_natively < ' a > (
739
- sess : & ' a Session ,
735
+ fn link_natively (
736
+ sess : & Session ,
740
737
archive_builder_builder : & dyn ArchiveBuilderBuilder ,
741
738
crate_type : CrateType ,
742
739
out_filename : & Path ,
@@ -1100,8 +1097,8 @@ fn link_natively<'a>(
1100
1097
Ok ( ( ) )
1101
1098
}
1102
1099
1103
- fn strip_symbols_with_external_utility < ' a > (
1104
- sess : & ' a Session ,
1100
+ fn strip_symbols_with_external_utility (
1101
+ sess : & Session ,
1105
1102
util : & str ,
1106
1103
out_filename : & Path ,
1107
1104
option : Option < & str > ,
@@ -1338,7 +1335,9 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
1338
1335
sess : & Session ,
1339
1336
linker : Option < PathBuf > ,
1340
1337
flavor : Option < LinkerFlavor > ,
1338
+ features : LinkerFeaturesCli ,
1341
1339
) -> Option < ( PathBuf , LinkerFlavor ) > {
1340
+ let flavor = flavor. map ( |flavor| adjust_flavor_to_features ( flavor, features) ) ;
1342
1341
match ( linker, flavor) {
1343
1342
( Some ( linker) , Some ( flavor) ) => Some ( ( linker, flavor) ) ,
1344
1343
// 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) {
1386
1385
sess. dcx ( ) . emit_fatal ( errors:: LinkerFileStem ) ;
1387
1386
} ) ;
1388
1387
let flavor = sess. target . linker_flavor . with_linker_hints ( stem) ;
1388
+ let flavor = adjust_flavor_to_features ( flavor, features) ;
1389
1389
Some ( ( linker, flavor) )
1390
1390
}
1391
1391
( None , None ) => None ,
1392
1392
}
1393
1393
}
1394
1394
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
+
1395
1415
// linker and linker flavor specified via command line have precedence over what the target
1396
1416
// specification specifies
1397
1417
let linker_flavor = match sess. opts . cg . linker_flavor {
@@ -1405,14 +1425,15 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
1405
1425
. linker_flavor
1406
1426
. map ( |flavor| sess. target . linker_flavor . with_cli_hints ( flavor) ) ,
1407
1427
} ;
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 ) {
1409
1429
return ret;
1410
1430
}
1411
1431
1412
1432
if let Some ( ret) = infer_from (
1413
1433
sess,
1414
1434
sess. target . linker . as_deref ( ) . map ( PathBuf :: from) ,
1415
1435
Some ( sess. target . linker_flavor ) ,
1436
+ features,
1416
1437
) {
1417
1438
return ret;
1418
1439
}
@@ -2105,10 +2126,10 @@ fn add_rpath_args(
2105
2126
/// to the linking process as a whole.
2106
2127
/// Order-independent options may still override each other in order-dependent fashion,
2107
2128
/// e.g `--foo=yes --foo=no` may be equivalent to `--foo=no`.
2108
- fn linker_with_args < ' a > (
2129
+ fn linker_with_args (
2109
2130
path : & Path ,
2110
2131
flavor : LinkerFlavor ,
2111
- sess : & ' a Session ,
2132
+ sess : & Session ,
2112
2133
archive_builder_builder : & dyn ArchiveBuilderBuilder ,
2113
2134
crate_type : CrateType ,
2114
2135
tmpdir : & Path ,
@@ -2640,9 +2661,9 @@ fn add_local_native_libraries(
2640
2661
) ;
2641
2662
}
2642
2663
2643
- fn add_upstream_rust_crates < ' a > (
2664
+ fn add_upstream_rust_crates (
2644
2665
cmd : & mut dyn Linker ,
2645
- sess : & ' a Session ,
2666
+ sess : & Session ,
2646
2667
archive_builder_builder : & dyn ArchiveBuilderBuilder ,
2647
2668
codegen_results : & CodegenResults ,
2648
2669
crate_type : CrateType ,
@@ -2779,7 +2800,7 @@ fn add_upstream_native_libraries(
2779
2800
// file generated by the MSVC linker. See https://github.com/rust-lang/rust/issues/112586.
2780
2801
//
2781
2802
// 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 {
2783
2804
let sysroot_lib_path = sess. target_filesearch ( PathKind :: All ) . get_lib_path ( ) ;
2784
2805
let canonical_sysroot_lib_path =
2785
2806
{ 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 {
2812
2833
// Note, however, that if we're not doing LTO we can just pass the rlib
2813
2834
// blindly to the linker (fast) because it's fine if it's not actually
2814
2835
// included as we're at the end of the dependency chain.
2815
- fn add_static_crate < ' a > (
2836
+ fn add_static_crate (
2816
2837
cmd : & mut dyn Linker ,
2817
- sess : & ' a Session ,
2838
+ sess : & Session ,
2818
2839
archive_builder_builder : & dyn ArchiveBuilderBuilder ,
2819
2840
codegen_results : & CodegenResults ,
2820
2841
tmpdir : & Path ,
0 commit comments