Skip to content

Commit 13c5d06

Browse files
committed
Auto merge of rust-lang#138645 - Kobzol:stabilize-lld-test, r=<try>
[do not merge] Preparation for LLD stabilization This PR serves for testing test changes for stabilizing LLD. CC `@lqd` r? `@ghost` try-job: dist-x86_64-linux
2 parents 0134651 + 518c74f commit 13c5d06

File tree

36 files changed

+267
-123
lines changed

36 files changed

+267
-123
lines changed

compiler/rustc_codegen_ssa/src/back/link.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1417,7 +1417,7 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
14171417
}
14181418
}
14191419

1420-
let features = sess.opts.unstable_opts.linker_features;
1420+
let features = sess.opts.cg.linker_features;
14211421

14221422
// linker and linker flavor specified via command line have precedence over what the target
14231423
// specification specifies

compiler/rustc_session/src/config.rs

+57-9
Original file line numberDiff line numberDiff line change
@@ -370,9 +370,14 @@ impl LinkSelfContained {
370370
/// components was set individually. This would also require the `-Zunstable-options` flag, to
371371
/// be allowed.
372372
fn are_unstable_variants_set(&self) -> bool {
373-
let any_component_set =
374-
!self.enabled_components.is_empty() || !self.disabled_components.is_empty();
375-
self.explicitly_set.is_none() && any_component_set
373+
if self.explicitly_set.is_some() {
374+
return false;
375+
}
376+
377+
// Only the linker component is stable, anything else is thus unstable.
378+
let mentioned_components = self.enabled_components.union(self.disabled_components);
379+
let unstable_components = mentioned_components - LinkSelfContainedComponents::LINKER;
380+
!unstable_components.is_empty()
376381
}
377382

378383
/// Returns whether the self-contained linker component was enabled on the CLI, using the
@@ -399,7 +404,7 @@ impl LinkSelfContained {
399404
}
400405
}
401406

402-
/// The different values that `-Z linker-features` can take on the CLI: a list of individually
407+
/// The different values that `-C linker-features` can take on the CLI: a list of individually
403408
/// enabled or disabled features used during linking.
404409
///
405410
/// There is no need to enable or disable them in bulk. Each feature is fine-grained, and can be
@@ -439,6 +444,44 @@ impl LinkerFeaturesCli {
439444
_ => None,
440445
}
441446
}
447+
448+
/// When *not* using `-Z unstable-options` on the CLI, ensure only stable linker features are
449+
/// used, for the given `TargetTuple`. Returns `Ok` if no unstable variants are used.
450+
/// The caller should ensure that e.g. `nightly_options::is_unstable_enabled()`
451+
/// returns false.
452+
pub(crate) fn check_unstable_variants(&self, target_tuple: &TargetTuple) -> Result<(), String> {
453+
// `-C linker-features=[-+]lld` is only stable on x64 linux.
454+
let check_lld = |features: LinkerFeatures, polarity: &str| {
455+
let has_lld = features.is_lld_enabled();
456+
if has_lld && target_tuple.tuple() != "x86_64-unknown-linux-gnu" {
457+
return Err(format!(
458+
"`-C linker-features={polarity}lld` is unstable on the `{target_tuple}` \
459+
target. The `-Z unstable-options` flag must also be passed to use it on this target",
460+
));
461+
}
462+
Ok(())
463+
};
464+
check_lld(self.enabled, "+")?;
465+
check_lld(self.disabled, "-")?;
466+
467+
// Since only lld is stable, any non-lld feature used is unstable, and that's an error.
468+
let unstable_enabled = self.enabled - LinkerFeatures::LLD;
469+
let unstable_disabled = self.disabled - LinkerFeatures::LLD;
470+
if !unstable_enabled.union(unstable_disabled).is_empty() {
471+
let unstable_features: Vec<_> = unstable_enabled
472+
.iter()
473+
.map(|f| format!("+{}", f.as_str().unwrap()))
474+
.chain(unstable_disabled.iter().map(|f| format!("-{}", f.as_str().unwrap())))
475+
.collect();
476+
return Err(format!(
477+
"the requested `-C linker-features={}` are unstable, and also require the \
478+
`-Z unstable-options` flag to be usable",
479+
unstable_features.join(","),
480+
));
481+
}
482+
483+
Ok(())
484+
}
442485
}
443486

444487
/// Used with `-Z assert-incr-state`.
@@ -2587,9 +2630,8 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
25872630
}
25882631
}
25892632

2590-
if !nightly_options::is_unstable_enabled(matches)
2591-
&& cg.force_frame_pointers == FramePointer::NonLeaf
2592-
{
2633+
let unstable_options_enabled = nightly_options::is_unstable_enabled(matches);
2634+
if !unstable_options_enabled && cg.force_frame_pointers == FramePointer::NonLeaf {
25932635
early_dcx.early_fatal(
25942636
"`-Cforce-frame-pointers=non-leaf` or `always` also requires `-Zunstable-options` \
25952637
and a nightly compiler",
@@ -2599,12 +2641,12 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
25992641
// For testing purposes, until we have more feedback about these options: ensure `-Z
26002642
// unstable-options` is required when using the unstable `-C link-self-contained` and `-C
26012643
// linker-flavor` options.
2602-
if !nightly_options::is_unstable_enabled(matches) {
2644+
if !unstable_options_enabled {
26032645
let uses_unstable_self_contained_option =
26042646
cg.link_self_contained.are_unstable_variants_set();
26052647
if uses_unstable_self_contained_option {
26062648
early_dcx.early_fatal(
2607-
"only `-C link-self-contained` values `y`/`yes`/`on`/`n`/`no`/`off` are stable, \
2649+
"only `-C link-self-contained` values `y`/`yes`/`on`/`n`/`no`/`off`/`-linker`/`+linker` are stable, \
26082650
the `-Z unstable-options` flag must also be passed to use the unstable values",
26092651
);
26102652
}
@@ -2647,6 +2689,12 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
26472689
let debuginfo = select_debuginfo(matches, &cg);
26482690
let debuginfo_compression = unstable_opts.debuginfo_compression;
26492691

2692+
if !unstable_options_enabled {
2693+
if let Err(error) = cg.linker_features.check_unstable_variants(&target_triple) {
2694+
early_dcx.early_fatal(error);
2695+
}
2696+
}
2697+
26502698
let crate_name = matches.opt_str("crate-name");
26512699
let unstable_features = UnstableFeatures::from_environment(crate_name.as_deref());
26522700
// Parse any `-l` flags, which link to native libraries.

compiler/rustc_session/src/options.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1994,6 +1994,8 @@ options! {
19941994
on a C toolchain or linker installed in the system"),
19951995
linker: Option<PathBuf> = (None, parse_opt_pathbuf, [UNTRACKED],
19961996
"system linker to link outputs with"),
1997+
linker_features: LinkerFeaturesCli = (LinkerFeaturesCli::default(), parse_linker_features, [UNTRACKED],
1998+
"a comma-separated list of linker features to enable (+) or disable (-): `lld`"),
19971999
linker_flavor: Option<LinkerFlavorCli> = (None, parse_linker_flavor, [UNTRACKED],
19982000
"linker flavor"),
19992001
linker_plugin_lto: LinkerPluginLto = (LinkerPluginLto::Disabled,
@@ -2282,8 +2284,6 @@ options! {
22822284
"link native libraries in the linker invocation (default: yes)"),
22832285
link_only: bool = (false, parse_bool, [TRACKED],
22842286
"link the `.rlink` file generated by `-Z no-link` (default: no)"),
2285-
linker_features: LinkerFeaturesCli = (LinkerFeaturesCli::default(), parse_linker_features, [UNTRACKED],
2286-
"a comma-separated list of linker features to enable (+) or disable (-): `lld`"),
22872287
lint_llvm_ir: bool = (false, parse_bool, [TRACKED],
22882288
"lint LLVM IR (default: no)"),
22892289
lint_mir: bool = (false, parse_bool, [UNTRACKED],

compiler/rustc_target/src/spec/mod.rs

+13-2
Original file line numberDiff line numberDiff line change
@@ -721,7 +721,7 @@ impl ToJson for LinkSelfContainedComponents {
721721
}
722722

723723
bitflags::bitflags! {
724-
/// The `-Z linker-features` components that can individually be enabled or disabled.
724+
/// The `-C linker-features` components that can individually be enabled or disabled.
725725
///
726726
/// They are feature flags intended to be a more flexible mechanism than linker flavors, and
727727
/// also to prevent a combinatorial explosion of flavors whenever a new linker feature is
@@ -752,7 +752,7 @@ bitflags::bitflags! {
752752
rustc_data_structures::external_bitflags_debug! { LinkerFeatures }
753753

754754
impl LinkerFeatures {
755-
/// Parses a single `-Z linker-features` well-known feature, not a set of flags.
755+
/// Parses a single `-C linker-features` well-known feature, not a set of flags.
756756
pub fn from_str(s: &str) -> Option<LinkerFeatures> {
757757
Some(match s {
758758
"cc" => LinkerFeatures::CC,
@@ -761,6 +761,17 @@ impl LinkerFeatures {
761761
})
762762
}
763763

764+
/// Return the linker feature name, as would be passed on the CLI.
765+
///
766+
/// Returns `None` if the bitflags aren't a singular component (but a mix of multiple flags).
767+
pub fn as_str(self) -> Option<&'static str> {
768+
Some(match self {
769+
LinkerFeatures::CC => "cc",
770+
LinkerFeatures::LLD => "lld",
771+
_ => return None,
772+
})
773+
}
774+
764775
/// Returns whether the `lld` linker feature is enabled.
765776
pub fn is_lld_enabled(self) -> bool {
766777
self.contains(LinkerFeatures::LLD)

src/bootstrap/src/core/build_steps/compile.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -1326,9 +1326,7 @@ pub fn rustc_cargo_env(
13261326
}
13271327

13281328
// Enable rustc's env var for `rust-lld` when requested.
1329-
if builder.config.lld_enabled
1330-
&& (builder.config.channel == "dev" || builder.config.channel == "nightly")
1331-
{
1329+
if builder.config.lld_enabled {
13321330
cargo.env("CFG_USE_SELF_CONTAINED_LINKER", "1");
13331331
}
13341332

src/bootstrap/src/core/build_steps/test.rs

+16-4
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,13 @@ impl Step for Cargotest {
261261
.args(builder.config.test_args())
262262
.env("RUSTC", builder.rustc(compiler))
263263
.env("RUSTDOC", builder.rustdoc(compiler));
264-
add_rustdoc_cargo_linker_args(&mut cmd, builder, compiler.host, LldThreads::No);
264+
add_rustdoc_cargo_linker_args(
265+
&mut cmd,
266+
builder,
267+
compiler.host,
268+
LldThreads::No,
269+
compiler.stage,
270+
);
265271
cmd.delay_failure().run(builder);
266272
}
267273
}
@@ -839,7 +845,7 @@ impl Step for RustdocTheme {
839845
.env("CFG_RELEASE_CHANNEL", &builder.config.channel)
840846
.env("RUSTDOC_REAL", builder.rustdoc(self.compiler))
841847
.env("RUSTC_BOOTSTRAP", "1");
842-
cmd.args(linker_args(builder, self.compiler.host, LldThreads::No));
848+
cmd.args(linker_args(builder, self.compiler.host, LldThreads::No, self.compiler.stage));
843849

844850
cmd.delay_failure().run(builder);
845851
}
@@ -1015,7 +1021,13 @@ impl Step for RustdocGUI {
10151021
cmd.env("RUSTDOC", builder.rustdoc(self.compiler))
10161022
.env("RUSTC", builder.rustc(self.compiler));
10171023

1018-
add_rustdoc_cargo_linker_args(&mut cmd, builder, self.compiler.host, LldThreads::No);
1024+
add_rustdoc_cargo_linker_args(
1025+
&mut cmd,
1026+
builder,
1027+
self.compiler.host,
1028+
LldThreads::No,
1029+
self.compiler.stage,
1030+
);
10191031

10201032
for path in &builder.paths {
10211033
if let Some(p) = helpers::is_valid_test_suite_arg(path, "tests/rustdoc-gui", builder) {
@@ -1784,7 +1796,7 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
17841796
}
17851797

17861798
let mut hostflags = flags.clone();
1787-
hostflags.extend(linker_flags(builder, compiler.host, LldThreads::No));
1799+
hostflags.extend(linker_flags(builder, compiler.host, LldThreads::No, compiler.stage));
17881800

17891801
let mut targetflags = flags;
17901802

src/bootstrap/src/core/builder/cargo.rs

+13-5
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ impl Cargo {
116116
// as they don't invoke rustc at all.
117117
Kind::Clean | Kind::Suggest | Kind::Format | Kind::Setup => {}
118118
_ => {
119-
cargo.configure_linker(builder);
119+
cargo.configure_linker(builder, mode);
120120
}
121121
}
122122

@@ -205,7 +205,7 @@ impl Cargo {
205205
self
206206
}
207207

208-
fn configure_linker(&mut self, builder: &Builder<'_>) -> &mut Cargo {
208+
fn configure_linker(&mut self, builder: &Builder<'_>, mode: Mode) -> &mut Cargo {
209209
let target = self.target;
210210
let compiler = self.compiler;
211211

@@ -260,7 +260,15 @@ impl Cargo {
260260
}
261261
}
262262

263-
for arg in linker_args(builder, compiler.host, LldThreads::Yes) {
263+
// When determining flags for the host (build scripts/proc macros),
264+
// we use the snapshot compiler when building `Mode::Std` tools, and
265+
// the current compiler when building anything else.
266+
// We need to determine the current stage here to pass proper linker args (e.g. -C vs -Z)
267+
// to the compiler used to compile build scripts.
268+
// This should stay synchronized with the [cargo] function.
269+
let host_stage = if mode == Mode::Std { 0 } else { compiler.stage };
270+
271+
for arg in linker_args(builder, compiler.host, LldThreads::Yes, host_stage) {
264272
self.hostflags.arg(&arg);
265273
}
266274

@@ -270,10 +278,10 @@ impl Cargo {
270278
}
271279
// We want to set -Clinker using Cargo, therefore we only call `linker_flags` and not
272280
// `linker_args` here.
273-
for flag in linker_flags(builder, target, LldThreads::Yes) {
281+
for flag in linker_flags(builder, target, LldThreads::Yes, compiler.stage) {
274282
self.rustflags.arg(&flag);
275283
}
276-
for arg in linker_args(builder, target, LldThreads::Yes) {
284+
for arg in linker_args(builder, target, LldThreads::Yes, compiler.stage) {
277285
self.rustdocflags.arg(&arg);
278286
}
279287

src/bootstrap/src/core/builder/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1479,7 +1479,7 @@ impl<'a> Builder<'a> {
14791479
cmd.arg("-Dwarnings");
14801480
}
14811481
cmd.arg("-Znormalize-docs");
1482-
cmd.args(linker_args(self, compiler.host, LldThreads::Yes));
1482+
cmd.args(linker_args(self, compiler.host, LldThreads::Yes, compiler.stage));
14831483
cmd
14841484
}
14851485

src/bootstrap/src/core/config/config.rs

+1-5
Original file line numberDiff line numberDiff line change
@@ -2464,7 +2464,6 @@ impl Config {
24642464
// build our internal lld and use it as the default linker, by setting the `rust.lld` config
24652465
// to true by default:
24662466
// - on the `x86_64-unknown-linux-gnu` target
2467-
// - on the `dev` and `nightly` channels
24682467
// - when building our in-tree llvm (i.e. the target has not set an `llvm-config`), so that
24692468
// we're also able to build the corresponding lld
24702469
// - or when using an external llvm that's downloaded from CI, which also contains our prebuilt
@@ -2473,10 +2472,7 @@ impl Config {
24732472
// thus, disabled
24742473
// - similarly, lld will not be built nor used by default when explicitly asked not to, e.g.
24752474
// when the config sets `rust.lld = false`
2476-
if config.build.triple == "x86_64-unknown-linux-gnu"
2477-
&& config.hosts == [config.build]
2478-
&& (config.channel == "dev" || config.channel == "nightly")
2479-
{
2475+
if config.build.triple == "x86_64-unknown-linux-gnu" && config.hosts == [config.build] {
24802476
let no_llvm_config = config
24812477
.target_config
24822478
.get(&config.build)

src/bootstrap/src/utils/helpers.rs

+23-9
Original file line numberDiff line numberDiff line change
@@ -445,8 +445,9 @@ pub fn linker_args(
445445
builder: &Builder<'_>,
446446
target: TargetSelection,
447447
lld_threads: LldThreads,
448+
stage: u32,
448449
) -> Vec<String> {
449-
let mut args = linker_flags(builder, target, lld_threads);
450+
let mut args = linker_flags(builder, target, lld_threads, stage);
450451

451452
if let Some(linker) = builder.linker(target) {
452453
args.push(format!("-Clinker={}", linker.display()));
@@ -461,20 +462,32 @@ pub fn linker_flags(
461462
builder: &Builder<'_>,
462463
target: TargetSelection,
463464
lld_threads: LldThreads,
465+
stage: u32,
464466
) -> Vec<String> {
465467
let mut args = vec![];
466468
if !builder.is_lld_direct_linker(target) && builder.config.lld_mode.is_used() {
467469
match builder.config.lld_mode {
468470
LldMode::External => {
469-
args.push("-Zlinker-features=+lld".to_string());
470-
// FIXME(kobzol): remove this flag once MCP510 gets stabilized
471-
args.push("-Zunstable-options".to_string());
471+
// cfg(bootstrap) - remove the stage 0 check after updating the bootstrap compiler:
472+
// `-Clinker-features` has been stabilized.
473+
if stage == 0 {
474+
args.push("-Zlinker-features=+lld".to_string());
475+
args.push("-Zunstable-options".to_string());
476+
} else {
477+
args.push("-Clinker-features=+lld".to_string());
478+
}
472479
}
473480
LldMode::SelfContained => {
474-
args.push("-Zlinker-features=+lld".to_string());
475-
args.push("-Clink-self-contained=+linker".to_string());
476-
// FIXME(kobzol): remove this flag once MCP510 gets stabilized
477-
args.push("-Zunstable-options".to_string());
481+
// cfg(bootstrap) - remove the stage 0 check after updating the bootstrap compiler:
482+
// `-Clinker-features` and `-Clink-self-contained=+linker` have been stabilized.
483+
if stage == 0 {
484+
args.push("-Zlinker-features=+lld".to_string());
485+
args.push("-Clink-self-contained=+linker".to_string());
486+
args.push("-Zunstable-options".to_string());
487+
} else {
488+
args.push("-Clinker-features=+lld".to_string());
489+
args.push("-Clink-self-contained=+linker".to_string());
490+
}
478491
}
479492
LldMode::Unused => unreachable!(),
480493
};
@@ -494,8 +507,9 @@ pub fn add_rustdoc_cargo_linker_args(
494507
builder: &Builder<'_>,
495508
target: TargetSelection,
496509
lld_threads: LldThreads,
510+
stage: u32,
497511
) {
498-
let args = linker_args(builder, target, lld_threads);
512+
let args = linker_args(builder, target, lld_threads, stage);
499513
let mut flags = cmd
500514
.get_envs()
501515
.find_map(|(k, v)| if k == OsStr::new("RUSTDOCFLAGS") { v } else { None })

0 commit comments

Comments
 (0)