Skip to content

Use lld by default on x86_64-unknown-linux-gnu stable #140525

New issue

Have a question about this project? No Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “No Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? No Sign in to your account

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_ssa/src/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1417,7 +1417,7 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
}
}

let features = sess.opts.unstable_opts.linker_features;
let features = sess.opts.cg.linker_features;

// linker and linker flavor specified via command line have precedence over what the target
// specification specifies
Expand Down
66 changes: 57 additions & 9 deletions compiler/rustc_session/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -370,9 +370,14 @@ impl LinkSelfContained {
/// components was set individually. This would also require the `-Zunstable-options` flag, to
/// be allowed.
fn are_unstable_variants_set(&self) -> bool {
let any_component_set =
!self.enabled_components.is_empty() || !self.disabled_components.is_empty();
self.explicitly_set.is_none() && any_component_set
if self.explicitly_set.is_some() {
return false;
}

// Only the linker component is stable, anything else is thus unstable.
let mentioned_components = self.enabled_components.union(self.disabled_components);
let unstable_components = mentioned_components - LinkSelfContainedComponents::LINKER;
!unstable_components.is_empty()
}

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

/// The different values that `-Z linker-features` can take on the CLI: a list of individually
/// The different values that `-C linker-features` can take on the CLI: a list of individually
/// enabled or disabled features used during linking.
///
/// There is no need to enable or disable them in bulk. Each feature is fine-grained, and can be
Expand Down Expand Up @@ -439,6 +444,44 @@ impl LinkerFeaturesCli {
_ => None,
}
}

/// When *not* using `-Z unstable-options` on the CLI, ensure only stable linker features are
/// used, for the given `TargetTuple`. Returns `Ok` if no unstable variants are used.
/// The caller should ensure that e.g. `nightly_options::is_unstable_enabled()`
/// returns false.
pub(crate) fn check_unstable_variants(&self, target_tuple: &TargetTuple) -> Result<(), String> {
// `-C linker-features=[-+]lld` is only stable on x64 linux.
let check_lld = |features: LinkerFeatures, polarity: &str| {
let has_lld = features.is_lld_enabled();
if has_lld && target_tuple.tuple() != "x86_64-unknown-linux-gnu" {
return Err(format!(
"`-C linker-features={polarity}lld` is unstable on the `{target_tuple}` \
target. The `-Z unstable-options` flag must also be passed to use it on this target",
));
}
Ok(())
};
check_lld(self.enabled, "+")?;
check_lld(self.disabled, "-")?;

// Since only lld is stable, any non-lld feature used is unstable, and that's an error.
let unstable_enabled = self.enabled - LinkerFeatures::LLD;
let unstable_disabled = self.disabled - LinkerFeatures::LLD;
if !unstable_enabled.union(unstable_disabled).is_empty() {
let unstable_features: Vec<_> = unstable_enabled
.iter()
.map(|f| format!("+{}", f.as_str().unwrap()))
.chain(unstable_disabled.iter().map(|f| format!("-{}", f.as_str().unwrap())))
.collect();
return Err(format!(
"the requested `-C linker-features={}` are unstable, and also require the \
`-Z unstable-options` flag to be usable",
unstable_features.join(","),
));
}

Ok(())
}
}

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

if !nightly_options::is_unstable_enabled(matches)
&& cg.force_frame_pointers == FramePointer::NonLeaf
{
let unstable_options_enabled = nightly_options::is_unstable_enabled(matches);
if !unstable_options_enabled && cg.force_frame_pointers == FramePointer::NonLeaf {
early_dcx.early_fatal(
"`-Cforce-frame-pointers=non-leaf` or `always` also requires `-Zunstable-options` \
and a nightly compiler",
Expand All @@ -2599,12 +2641,12 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
// For testing purposes, until we have more feedback about these options: ensure `-Z
// unstable-options` is required when using the unstable `-C link-self-contained` and `-C
// linker-flavor` options.
if !nightly_options::is_unstable_enabled(matches) {
if !unstable_options_enabled {
let uses_unstable_self_contained_option =
cg.link_self_contained.are_unstable_variants_set();
if uses_unstable_self_contained_option {
early_dcx.early_fatal(
"only `-C link-self-contained` values `y`/`yes`/`on`/`n`/`no`/`off` are stable, \
"only `-C link-self-contained` values `y`/`yes`/`on`/`n`/`no`/`off`/`-linker`/`+linker` are stable, \
the `-Z unstable-options` flag must also be passed to use the unstable values",
);
}
Expand Down Expand Up @@ -2647,6 +2689,12 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
let debuginfo = select_debuginfo(matches, &cg);
let debuginfo_compression = unstable_opts.debuginfo_compression;

if !unstable_options_enabled {
if let Err(error) = cg.linker_features.check_unstable_variants(&target_triple) {
early_dcx.early_fatal(error);
}
}

let crate_name = matches.opt_str("crate-name");
let unstable_features = UnstableFeatures::from_environment(crate_name.as_deref());
// Parse any `-l` flags, which link to native libraries.
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_session/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1994,6 +1994,8 @@ options! {
on a C toolchain or linker installed in the system"),
linker: Option<PathBuf> = (None, parse_opt_pathbuf, [UNTRACKED],
"system linker to link outputs with"),
linker_features: LinkerFeaturesCli = (LinkerFeaturesCli::default(), parse_linker_features, [UNTRACKED],
"a comma-separated list of linker features to enable (+) or disable (-): `lld`"),
linker_flavor: Option<LinkerFlavorCli> = (None, parse_linker_flavor, [UNTRACKED],
"linker flavor"),
linker_plugin_lto: LinkerPluginLto = (LinkerPluginLto::Disabled,
Expand Down Expand Up @@ -2282,8 +2284,6 @@ options! {
"link native libraries in the linker invocation (default: yes)"),
link_only: bool = (false, parse_bool, [TRACKED],
"link the `.rlink` file generated by `-Z no-link` (default: no)"),
linker_features: LinkerFeaturesCli = (LinkerFeaturesCli::default(), parse_linker_features, [UNTRACKED],
"a comma-separated list of linker features to enable (+) or disable (-): `lld`"),
lint_llvm_ir: bool = (false, parse_bool, [TRACKED],
"lint LLVM IR (default: no)"),
lint_mir: bool = (false, parse_bool, [UNTRACKED],
Expand Down
15 changes: 13 additions & 2 deletions compiler/rustc_target/src/spec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -721,7 +721,7 @@ impl ToJson for LinkSelfContainedComponents {
}

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

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

/// Return the linker feature name, as would be passed on the CLI.
///
/// Returns `None` if the bitflags aren't a singular component (but a mix of multiple flags).
pub fn as_str(self) -> Option<&'static str> {
Some(match self {
LinkerFeatures::CC => "cc",
LinkerFeatures::LLD => "lld",
_ => return None,
})
}

/// Returns whether the `lld` linker feature is enabled.
pub fn is_lld_enabled(self) -> bool {
self.contains(LinkerFeatures::LLD)
Expand Down
4 changes: 1 addition & 3 deletions src/bootstrap/src/core/build_steps/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1326,9 +1326,7 @@ pub fn rustc_cargo_env(
}

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

Expand Down
20 changes: 16 additions & 4 deletions src/bootstrap/src/core/build_steps/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,13 @@ impl Step for Cargotest {
.args(builder.config.test_args())
.env("RUSTC", builder.rustc(compiler))
.env("RUSTDOC", builder.rustdoc(compiler));
add_rustdoc_cargo_linker_args(&mut cmd, builder, compiler.host, LldThreads::No);
add_rustdoc_cargo_linker_args(
&mut cmd,
builder,
compiler.host,
LldThreads::No,
compiler.stage,
);
cmd.delay_failure().run(builder);
}
}
Expand Down Expand Up @@ -839,7 +845,7 @@ impl Step for RustdocTheme {
.env("CFG_RELEASE_CHANNEL", &builder.config.channel)
.env("RUSTDOC_REAL", builder.rustdoc(self.compiler))
.env("RUSTC_BOOTSTRAP", "1");
cmd.args(linker_args(builder, self.compiler.host, LldThreads::No));
cmd.args(linker_args(builder, self.compiler.host, LldThreads::No, self.compiler.stage));

cmd.delay_failure().run(builder);
}
Expand Down Expand Up @@ -1015,7 +1021,13 @@ impl Step for RustdocGUI {
cmd.env("RUSTDOC", builder.rustdoc(self.compiler))
.env("RUSTC", builder.rustc(self.compiler));

add_rustdoc_cargo_linker_args(&mut cmd, builder, self.compiler.host, LldThreads::No);
add_rustdoc_cargo_linker_args(
&mut cmd,
builder,
self.compiler.host,
LldThreads::No,
self.compiler.stage,
);

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

let mut hostflags = flags.clone();
hostflags.extend(linker_flags(builder, compiler.host, LldThreads::No));
hostflags.extend(linker_flags(builder, compiler.host, LldThreads::No, compiler.stage));

let mut targetflags = flags;

Expand Down
18 changes: 13 additions & 5 deletions src/bootstrap/src/core/builder/cargo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ impl Cargo {
// as they don't invoke rustc at all.
Kind::Clean | Kind::Suggest | Kind::Format | Kind::Setup => {}
_ => {
cargo.configure_linker(builder);
cargo.configure_linker(builder, mode);
}
}

Expand Down Expand Up @@ -205,7 +205,7 @@ impl Cargo {
self
}

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

Expand Down Expand Up @@ -260,7 +260,15 @@ impl Cargo {
}
}

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

for arg in linker_args(builder, compiler.host, LldThreads::Yes, host_stage) {
self.hostflags.arg(&arg);
}

Expand All @@ -270,10 +278,10 @@ impl Cargo {
}
// We want to set -Clinker using Cargo, therefore we only call `linker_flags` and not
// `linker_args` here.
for flag in linker_flags(builder, target, LldThreads::Yes) {
for flag in linker_flags(builder, target, LldThreads::Yes, compiler.stage) {
self.rustflags.arg(&flag);
}
for arg in linker_args(builder, target, LldThreads::Yes) {
for arg in linker_args(builder, target, LldThreads::Yes, compiler.stage) {
self.rustdocflags.arg(&arg);
}

Expand Down
2 changes: 1 addition & 1 deletion src/bootstrap/src/core/builder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1479,7 +1479,7 @@ impl<'a> Builder<'a> {
cmd.arg("-Dwarnings");
}
cmd.arg("-Znormalize-docs");
cmd.args(linker_args(self, compiler.host, LldThreads::Yes));
cmd.args(linker_args(self, compiler.host, LldThreads::Yes, compiler.stage));
cmd
}

Expand Down
6 changes: 1 addition & 5 deletions src/bootstrap/src/core/config/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2469,7 +2469,6 @@ impl Config {
// build our internal lld and use it as the default linker, by setting the `rust.lld` config
// to true by default:
// - on the `x86_64-unknown-linux-gnu` target
// - on the `dev` and `nightly` channels
// - when building our in-tree llvm (i.e. the target has not set an `llvm-config`), so that
// we're also able to build the corresponding lld
// - or when using an external llvm that's downloaded from CI, which also contains our prebuilt
Expand All @@ -2478,10 +2477,7 @@ impl Config {
// thus, disabled
// - similarly, lld will not be built nor used by default when explicitly asked not to, e.g.
// when the config sets `rust.lld = false`
if config.build.triple == "x86_64-unknown-linux-gnu"
&& config.hosts == [config.build]
&& (config.channel == "dev" || config.channel == "nightly")
{
if config.build.triple == "x86_64-unknown-linux-gnu" && config.hosts == [config.build] {
let no_llvm_config = config
.target_config
.get(&config.build)
Expand Down
25 changes: 19 additions & 6 deletions src/bootstrap/src/utils/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -445,8 +445,9 @@ pub fn linker_args(
builder: &Builder<'_>,
target: TargetSelection,
lld_threads: LldThreads,
stage: u32,
) -> Vec<String> {
let mut args = linker_flags(builder, target, lld_threads);
let mut args = linker_flags(builder, target, lld_threads, stage);

if let Some(linker) = builder.linker(target) {
args.push(format!("-Clinker={}", linker.display()));
Expand All @@ -461,19 +462,30 @@ pub fn linker_flags(
builder: &Builder<'_>,
target: TargetSelection,
lld_threads: LldThreads,
stage: u32,
) -> Vec<String> {
let mut args = vec![];
if !builder.is_lld_direct_linker(target) && builder.config.lld_mode.is_used() {
match builder.config.lld_mode {
LldMode::External => {
args.push("-Zlinker-features=+lld".to_string());
// FIXME(kobzol): remove this flag once MCP510 gets stabilized
// cfg(bootstrap) - remove the stage 0 check after updating the bootstrap compiler:
// `-Clinker-features` has been stabilized.
if stage == 0 {
args.push("-Zlinker-features=+lld".to_string());
} else {
args.push("-Clinker-features=+lld".to_string());
}
args.push("-Zunstable-options".to_string());
}
LldMode::SelfContained => {
args.push("-Zlinker-features=+lld".to_string());
// cfg(bootstrap) - remove the stage 0 check after updating the bootstrap compiler:
// `-Clinker-features` has been stabilized.
if stage == 0 {
args.push("-Zlinker-features=+lld".to_string());
} else {
args.push("-Clinker-features=+lld".to_string());
}
args.push("-Clink-self-contained=+linker".to_string());
// FIXME(kobzol): remove this flag once MCP510 gets stabilized
args.push("-Zunstable-options".to_string());
}
LldMode::Unused => unreachable!(),
Expand All @@ -494,8 +506,9 @@ pub fn add_rustdoc_cargo_linker_args(
builder: &Builder<'_>,
target: TargetSelection,
lld_threads: LldThreads,
stage: u32,
) {
let args = linker_args(builder, target, lld_threads);
let args = linker_args(builder, target, lld_threads, stage);
let mut flags = cmd
.get_envs()
.find_map(|(k, v)| if k == OsStr::new("RUSTDOCFLAGS") { v } else { None })
Expand Down
Loading
Loading