Rename rust.use-lld to rust.bootstrap-override-lld

This commit is contained in:
Jakub Beránek
2025-09-25 22:45:07 +02:00
parent a885811104
commit 852aa20c90
11 changed files with 113 additions and 54 deletions
+3 -4
View File
@@ -768,8 +768,7 @@
# make this default to false.
#rust.lld = false in all cases, except on `x86_64-unknown-linux-gnu` as described above, where it is true
# Indicates whether LLD will be used to link Rust crates during bootstrap on
# supported platforms.
# Indicates if we should override the linker used to link Rust crates during bootstrap to be LLD.
# If set to `true` or `"external"`, a global `lld` binary that has to be in $PATH
# will be used.
# If set to `"self-contained"`, rust-lld from the snapshot compiler will be used.
@@ -777,7 +776,7 @@
# On MSVC, LLD will not be used if we're cross linking.
#
# Explicitly setting the linker for a target will override this option when targeting MSVC.
#rust.use-lld = false
#rust.bootstrap-override-lld = false
# Indicates whether some LLVM tools, like llvm-objdump, will be made available in the
# sysroot.
@@ -950,7 +949,7 @@
# Linker to be used to bootstrap Rust code. Note that the
# default value is platform specific, and if not specified it may also depend on
# what platform is crossing to what platform.
# Setting this will override the `use-lld` option for Rust code when targeting MSVC.
# Setting this will override the `bootstrap-override-lld` option for Rust code when targeting MSVC.
#linker = "cc" (path)
# Should rustc and the standard library be built with split debuginfo? Default
@@ -1219,7 +1219,7 @@ pub fn rustc_cargo(
// us a faster startup time. However GNU ld < 2.40 will error if we try to link a shared object
// with direct references to protected symbols, so for now we only use protected symbols if
// linking with LLD is enabled.
if builder.build.config.lld_mode.is_used() {
if builder.build.config.bootstrap_override_lld.is_used() {
cargo.rustflag("-Zdefault-visibility=protected");
}
@@ -1256,7 +1256,7 @@ pub fn rustc_cargo(
// is already on by default in MSVC optimized builds, which is interpreted as --icf=all:
// https://github.com/llvm/llvm-project/blob/3329cec2f79185bafd678f310fafadba2a8c76d2/lld/COFF/Driver.cpp#L1746
// https://github.com/rust-lang/rust/blob/f22819bcce4abaff7d1246a56eec493418f9f4ee/compiler/rustc_codegen_ssa/src/back/linker.rs#L827
if builder.config.lld_mode.is_used() && !build_compiler.host.is_msvc() {
if builder.config.bootstrap_override_lld.is_used() && !build_compiler.host.is_msvc() {
cargo.rustflag("-Clink-args=-Wl,--icf=all");
}
+15 -5
View File
@@ -41,7 +41,7 @@
use crate::core::config::toml::install::Install;
use crate::core::config::toml::llvm::Llvm;
use crate::core::config::toml::rust::{
LldMode, Rust, RustOptimize, check_incompatible_options_for_ci_rustc,
BootstrapOverrideLld, Rust, RustOptimize, check_incompatible_options_for_ci_rustc,
default_lld_opt_in_targets, parse_codegen_backends,
};
use crate::core::config::toml::target::Target;
@@ -174,7 +174,7 @@ pub struct Config {
pub llvm_from_ci: bool,
pub llvm_build_config: HashMap<String, String>,
pub lld_mode: LldMode,
pub bootstrap_override_lld: BootstrapOverrideLld,
pub lld_enabled: bool,
pub llvm_tools_enabled: bool,
pub llvm_bitcode_linker_enabled: bool,
@@ -567,7 +567,8 @@ pub(crate) fn parse_inner(
frame_pointers: rust_frame_pointers,
stack_protector: rust_stack_protector,
strip: rust_strip,
lld_mode: rust_lld_mode,
bootstrap_override_lld: rust_bootstrap_override_lld,
bootstrap_override_lld_legacy: rust_bootstrap_override_lld_legacy,
std_features: rust_std_features,
break_on_ice: rust_break_on_ice,
} = toml.rust.unwrap_or_default();
@@ -615,6 +616,15 @@ pub(crate) fn parse_inner(
let Gcc { download_ci_gcc: gcc_download_ci_gcc } = toml.gcc.unwrap_or_default();
if rust_bootstrap_override_lld.is_some() && rust_bootstrap_override_lld_legacy.is_some() {
panic!(
"Cannot use both `rust.use-lld` and `rust.bootstrap-override-lld`. Please use only `rust.bootstrap-override-lld`"
);
}
let bootstrap_override_lld =
rust_bootstrap_override_lld.or(rust_bootstrap_override_lld_legacy).unwrap_or_default();
if rust_optimize.as_ref().is_some_and(|v| matches!(v, RustOptimize::Bool(false))) {
eprintln!(
"WARNING: setting `optimize` to `false` is known to cause errors and \
@@ -960,7 +970,7 @@ pub(crate) fn parse_inner(
let initial_rustfmt = build_rustfmt.or_else(|| maybe_download_rustfmt(&dwn_ctx, &out));
if matches!(rust_lld_mode.unwrap_or_default(), LldMode::SelfContained)
if matches!(bootstrap_override_lld, BootstrapOverrideLld::SelfContained)
&& !lld_enabled
&& flags_stage.unwrap_or(0) > 0
{
@@ -1172,6 +1182,7 @@ pub(crate) fn parse_inner(
backtrace_on_ice: rust_backtrace_on_ice.unwrap_or(false),
bindir: install_bindir.map(PathBuf::from).unwrap_or("bin".into()),
bootstrap_cache_path: build_bootstrap_cache_path,
bootstrap_override_lld,
bypass_bootstrap_lock: flags_bypass_bootstrap_lock,
cargo_info,
cargo_native_static: build_cargo_native_static.unwrap_or(false),
@@ -1238,7 +1249,6 @@ pub(crate) fn parse_inner(
libdir: install_libdir.map(PathBuf::from),
library_docs_private_items: build_library_docs_private_items.unwrap_or(false),
lld_enabled,
lld_mode: rust_lld_mode.unwrap_or_default(),
lldb: build_lldb.map(PathBuf::from),
llvm_allow_old_toolchain: llvm_allow_old_toolchain.unwrap_or(false),
llvm_assertions,
+1 -1
View File
@@ -37,7 +37,7 @@
pub use target_selection::TargetSelection;
pub use toml::BUILDER_CONFIG_FILENAME;
pub use toml::change_id::ChangeId;
pub use toml::rust::LldMode;
pub use toml::rust::BootstrapOverrideLld;
pub use toml::target::Target;
use crate::Display;
+30 -6
View File
@@ -17,7 +17,9 @@
use crate::core::build_steps::llvm::LLVM_INVALIDATION_PATHS;
use crate::core::build_steps::{llvm, test};
use crate::core::config::toml::TomlConfig;
use crate::core::config::{CompilerBuiltins, LldMode, StringOrBool, Target, TargetSelection};
use crate::core::config::{
BootstrapOverrideLld, CompilerBuiltins, StringOrBool, Target, TargetSelection,
};
use crate::utils::tests::TestCtx;
use crate::utils::tests::git::git_test;
@@ -222,11 +224,33 @@ fn verify_file_integrity() {
#[test]
fn rust_lld() {
assert!(matches!(parse("").lld_mode, LldMode::Unused));
assert!(matches!(parse("rust.use-lld = \"self-contained\"").lld_mode, LldMode::SelfContained));
assert!(matches!(parse("rust.use-lld = \"external\"").lld_mode, LldMode::External));
assert!(matches!(parse("rust.use-lld = true").lld_mode, LldMode::External));
assert!(matches!(parse("rust.use-lld = false").lld_mode, LldMode::Unused));
assert!(matches!(parse("").bootstrap_override_lld, BootstrapOverrideLld::None));
assert!(matches!(
parse("rust.bootstrap-override-lld = \"self-contained\"").bootstrap_override_lld,
BootstrapOverrideLld::SelfContained
));
assert!(matches!(
parse("rust.bootstrap-override-lld = \"external\"").bootstrap_override_lld,
BootstrapOverrideLld::External
));
assert!(matches!(
parse("rust.bootstrap-override-lld = true").bootstrap_override_lld,
BootstrapOverrideLld::External
));
assert!(matches!(
parse("rust.bootstrap-override-lld = false").bootstrap_override_lld,
BootstrapOverrideLld::None
));
// Also check the legacy options
assert!(matches!(
parse("rust.use-lld = true").bootstrap_override_lld,
BootstrapOverrideLld::External
));
assert!(matches!(
parse("rust.use-lld = false").bootstrap_override_lld,
BootstrapOverrideLld::None
));
}
#[test]
+31 -18
View File
@@ -45,7 +45,9 @@ struct Rust {
codegen_backends: Option<Vec<String>> = "codegen-backends",
llvm_bitcode_linker: Option<bool> = "llvm-bitcode-linker",
lld: Option<bool> = "lld",
lld_mode: Option<LldMode> = "use-lld",
bootstrap_override_lld: Option<BootstrapOverrideLld> = "bootstrap-override-lld",
// FIXME: Remove this option in Spring 2026
bootstrap_override_lld_legacy: Option<BootstrapOverrideLld> = "use-lld",
llvm_tools: Option<bool> = "llvm-tools",
deny_warnings: Option<bool> = "deny-warnings",
backtrace_on_ice: Option<bool> = "backtrace-on-ice",
@@ -70,22 +72,33 @@ struct Rust {
}
}
/// LLD in bootstrap works like this:
/// - Self-contained lld: use `rust-lld` from the compiler's sysroot
/// Determines if we should override the linker used for linking Rust code built
/// during the bootstrapping process to be LLD.
///
/// The primary use-case for this is to make local (re)builds of Rust code faster
/// when using bootstrap.
///
/// This does not affect the *behavior* of the built/distributed compiler when invoked
/// outside of bootstrap.
/// It might affect its performance/binary size though, as that can depend on the
/// linker that links rustc.
///
/// There are two ways of overriding the linker to be LLD:
/// - Self-contained LLD: use `rust-lld` from the compiler's sysroot
/// - External: use an external `lld` binary
///
/// It is configured depending on the target:
/// 1) Everything except MSVC
/// - Self-contained: `-Clinker-flavor=gnu-lld-cc -Clink-self-contained=+linker`
/// - External: `-Clinker-flavor=gnu-lld-cc`
/// - Self-contained: `-Clinker-features=+lld -Clink-self-contained=+linker`
/// - External: `-Clinker-features=+lld`
/// 2) MSVC
/// - Self-contained: `-Clinker=<path to rust-lld>`
/// - External: `-Clinker=lld`
#[derive(Copy, Clone, Default, Debug, PartialEq)]
pub enum LldMode {
/// Do not use LLD
pub enum BootstrapOverrideLld {
/// Do not override the linker LLD
#[default]
Unused,
None,
/// Use `rust-lld` from the compiler's sysroot
SelfContained,
/// Use an externally provided `lld` binary.
@@ -94,16 +107,16 @@ pub enum LldMode {
External,
}
impl LldMode {
impl BootstrapOverrideLld {
pub fn is_used(&self) -> bool {
match self {
LldMode::SelfContained | LldMode::External => true,
LldMode::Unused => false,
BootstrapOverrideLld::SelfContained | BootstrapOverrideLld::External => true,
BootstrapOverrideLld::None => false,
}
}
}
impl<'de> Deserialize<'de> for LldMode {
impl<'de> Deserialize<'de> for BootstrapOverrideLld {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
@@ -111,7 +124,7 @@ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
struct LldModeVisitor;
impl serde::de::Visitor<'_> for LldModeVisitor {
type Value = LldMode;
type Value = BootstrapOverrideLld;
fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
formatter.write_str("one of true, 'self-contained' or 'external'")
@@ -121,7 +134,7 @@ fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(if v { LldMode::External } else { LldMode::Unused })
Ok(if v { BootstrapOverrideLld::External } else { BootstrapOverrideLld::None })
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
@@ -129,8 +142,8 @@ fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
E: serde::de::Error,
{
match v {
"external" => Ok(LldMode::External),
"self-contained" => Ok(LldMode::SelfContained),
"external" => Ok(BootstrapOverrideLld::External),
"self-contained" => Ok(BootstrapOverrideLld::SelfContained),
_ => Err(E::custom(format!("unknown mode {v}"))),
}
}
@@ -311,7 +324,6 @@ macro_rules! warn {
lto,
stack_protector,
strip,
lld_mode,
jemalloc,
rpath,
channel,
@@ -359,6 +371,8 @@ macro_rules! warn {
frame_pointers: _,
break_on_ice: _,
parallel_frontend_threads: _,
bootstrap_override_lld: _,
bootstrap_override_lld_legacy: _,
} = ci_rust_config;
// There are two kinds of checks for CI rustc incompatible options:
@@ -374,7 +388,6 @@ macro_rules! warn {
err!(current_rust_config.debuginfo_level_rustc, debuginfo_level_rustc, "rust");
err!(current_rust_config.rpath, rpath, "rust");
err!(current_rust_config.strip, strip, "rust");
err!(current_rust_config.lld_mode, lld_mode, "rust");
err!(current_rust_config.llvm_tools, llvm_tools, "rust");
err!(current_rust_config.llvm_bitcode_linker, llvm_bitcode_linker, "rust");
err!(current_rust_config.jemalloc, jemalloc, "rust");
+6 -6
View File
@@ -35,7 +35,7 @@
use crate::core::builder;
use crate::core::builder::Kind;
use crate::core::config::{DryRun, LldMode, LlvmLibunwind, TargetSelection, flags};
use crate::core::config::{BootstrapOverrideLld, DryRun, LlvmLibunwind, TargetSelection, flags};
use crate::utils::exec::{BootstrapCommand, command};
use crate::utils::helpers::{self, dir_is_empty, exe, libdir, set_file_times, split_debuginfo};
@@ -1358,14 +1358,14 @@ fn linker(&self, target: TargetSelection) -> Option<PathBuf> {
&& !target.is_msvc()
{
Some(self.cc(target))
} else if self.config.lld_mode.is_used()
} else if self.config.bootstrap_override_lld.is_used()
&& self.is_lld_direct_linker(target)
&& self.host_target == target
{
match self.config.lld_mode {
LldMode::SelfContained => Some(self.initial_lld.clone()),
LldMode::External => Some("lld".into()),
LldMode::Unused => None,
match self.config.bootstrap_override_lld {
BootstrapOverrideLld::SelfContained => Some(self.initial_lld.clone()),
BootstrapOverrideLld::External => Some("lld".into()),
BootstrapOverrideLld::None => None,
}
} else {
None
@@ -556,4 +556,9 @@ pub fn human_readable_changes(changes: &[ChangeInfo]) -> String {
severity: ChangeSeverity::Info,
summary: "New option `build.windows-rc` that will override which resource compiler on Windows will be used to compile Rust.",
},
ChangeInfo {
change_id: 99999,
severity: ChangeSeverity::Warning,
summary: "The `rust.use-lld` option has been renamed to `rust.bootstrap-override-lld`. Note that it only serves for overriding the linker used when building Rust code in bootstrap to be LLD.",
},
];
+18 -10
View File
@@ -12,7 +12,7 @@
use object::read::archive::ArchiveFile;
use crate::LldMode;
use crate::BootstrapOverrideLld;
use crate::core::builder::Builder;
use crate::core::config::{Config, TargetSelection};
use crate::utils::exec::{BootstrapCommand, command};
@@ -357,15 +357,19 @@ pub fn get_clang_cl_resource_dir(builder: &Builder<'_>, clang_cl_path: &str) ->
/// Returns a flag that configures LLD to use only a single thread.
/// If we use an external LLD, we need to find out which version is it to know which flag should we
/// pass to it (LLD older than version 10 had a different flag).
fn lld_flag_no_threads(builder: &Builder<'_>, lld_mode: LldMode, is_windows: bool) -> &'static str {
fn lld_flag_no_threads(
builder: &Builder<'_>,
bootstrap_override_lld: BootstrapOverrideLld,
is_windows: bool,
) -> &'static str {
static LLD_NO_THREADS: OnceLock<(&'static str, &'static str)> = OnceLock::new();
let new_flags = ("/threads:1", "--threads=1");
let old_flags = ("/no-threads", "--no-threads");
let (windows_flag, other_flag) = LLD_NO_THREADS.get_or_init(|| {
let newer_version = match lld_mode {
LldMode::External => {
let newer_version = match bootstrap_override_lld {
BootstrapOverrideLld::External => {
let mut cmd = command("lld");
cmd.arg("-flavor").arg("ld").arg("--version");
let out = cmd.run_capture_stdout(builder).stdout();
@@ -422,24 +426,28 @@ pub fn linker_flags(
lld_threads: LldThreads,
) -> 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 => {
if !builder.is_lld_direct_linker(target) && builder.config.bootstrap_override_lld.is_used() {
match builder.config.bootstrap_override_lld {
BootstrapOverrideLld::External => {
args.push("-Clinker-features=+lld".to_string());
args.push("-Zunstable-options".to_string());
}
LldMode::SelfContained => {
BootstrapOverrideLld::SelfContained => {
args.push("-Clinker-features=+lld".to_string());
args.push("-Clink-self-contained=+linker".to_string());
args.push("-Zunstable-options".to_string());
}
LldMode::Unused => unreachable!(),
BootstrapOverrideLld::None => unreachable!(),
};
if matches!(lld_threads, LldThreads::No) {
args.push(format!(
"-Clink-arg=-Wl,{}",
lld_flag_no_threads(builder, builder.config.lld_mode, target.is_windows())
lld_flag_no_threads(
builder,
builder.config.bootstrap_override_lld,
target.is_windows()
)
));
}
}
@@ -91,7 +91,7 @@ ENV RUST_CONFIGURE_ARGS \
--set llvm.ninja=false \
--set rust.debug-assertions=false \
--set rust.jemalloc \
--set rust.use-lld=true \
--set rust.bootstrap-override-lld=true \
--set rust.lto=thin \
--set rust.codegen-units=1
@@ -92,7 +92,7 @@ ENV RUST_CONFIGURE_ARGS \
--set llvm.ninja=false \
--set llvm.libzstd=true \
--set rust.jemalloc \
--set rust.use-lld=true \
--set rust.bootstrap-override-lld=true \
--set rust.lto=thin \
--set rust.codegen-units=1