diff --git a/bootstrap.example.toml b/bootstrap.example.toml index 0cd571134ef15..0a39c6d8f247d 100644 --- a/bootstrap.example.toml +++ b/bootstrap.example.toml @@ -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 diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index e699922f4dc05..cdd9a44a199c9 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -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"); } diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 6d9e3b54156e0..271ce4cb950bb 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -41,7 +41,7 @@ use crate::core::config::toml::gcc::Gcc; 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, - 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 @@ impl Config { 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 @@ impl Config { 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 @@ impl Config { 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 @@ impl Config { 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 @@ impl Config { 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, diff --git a/src/bootstrap/src/core/config/mod.rs b/src/bootstrap/src/core/config/mod.rs index 05a5dfc0bc5a8..56b87823a3654 100644 --- a/src/bootstrap/src/core/config/mod.rs +++ b/src/bootstrap/src/core/config/mod.rs @@ -37,7 +37,7 @@ use serde_derive::Deserialize; 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; diff --git a/src/bootstrap/src/core/config/tests.rs b/src/bootstrap/src/core/config/tests.rs index 4f2df76a15658..e19604d4ab12f 100644 --- a/src/bootstrap/src/core/config/tests.rs +++ b/src/bootstrap/src/core/config/tests.rs @@ -17,7 +17,9 @@ use crate::core::build_steps::clippy::{LintConfig, get_clippy_rules_in_order}; 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] diff --git a/src/bootstrap/src/core/config/toml/rust.rs b/src/bootstrap/src/core/config/toml/rust.rs index e5987d7040aaf..ca9e0d0bc98e7 100644 --- a/src/bootstrap/src/core/config/toml/rust.rs +++ b/src/bootstrap/src/core/config/toml/rust.rs @@ -45,7 +45,9 @@ define_config! { codegen_backends: Option> = "codegen-backends", llvm_bitcode_linker: Option = "llvm-bitcode-linker", lld: Option = "lld", - lld_mode: Option = "use-lld", + bootstrap_override_lld: Option = "bootstrap-override-lld", + // FIXME: Remove this option in Spring 2026 + bootstrap_override_lld_legacy: Option = "use-lld", llvm_tools: Option = "llvm-tools", deny_warnings: Option = "deny-warnings", backtrace_on_ice: Option = "backtrace-on-ice", @@ -70,22 +72,33 @@ define_config! { } } -/// 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=` /// - 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(deserializer: D) -> Result where D: Deserializer<'de>, @@ -111,7 +124,7 @@ impl<'de> Deserialize<'de> for LldMode { 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 @@ impl<'de> Deserialize<'de> for LldMode { where E: serde::de::Error, { - Ok(if v { LldMode::External } else { LldMode::Unused }) + Ok(if v { BootstrapOverrideLld::External } else { BootstrapOverrideLld::None }) } fn visit_str(self, v: &str) -> Result @@ -129,8 +142,8 @@ impl<'de> Deserialize<'de> for LldMode { 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 @@ pub fn check_incompatible_options_for_ci_rustc( lto, stack_protector, strip, - lld_mode, jemalloc, rpath, channel, @@ -359,6 +371,8 @@ pub fn check_incompatible_options_for_ci_rustc( 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 @@ pub fn check_incompatible_options_for_ci_rustc( 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"); diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 4f4d35673d5d1..d798639cc967e 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -35,7 +35,7 @@ use utils::exec::ExecutionContext; 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 @@ impl Build { && !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 diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs index 6b187578c31ec..f311c84bec9b5 100644 --- a/src/bootstrap/src/utils/change_tracker.rs +++ b/src/bootstrap/src/utils/change_tracker.rs @@ -556,4 +556,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[ 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.", + }, ]; diff --git a/src/bootstrap/src/utils/helpers.rs b/src/bootstrap/src/utils/helpers.rs index e802c0214ddcb..faada9a111db8 100644 --- a/src/bootstrap/src/utils/helpers.rs +++ b/src/bootstrap/src/utils/helpers.rs @@ -12,7 +12,7 @@ use std::{env, fs, io, panic, str}; 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 { 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() + ) )); } } diff --git a/src/ci/docker/host-aarch64/dist-aarch64-linux/Dockerfile b/src/ci/docker/host-aarch64/dist-aarch64-linux/Dockerfile index e726329753f24..3abca36fe70db 100644 --- a/src/ci/docker/host-aarch64/dist-aarch64-linux/Dockerfile +++ b/src/ci/docker/host-aarch64/dist-aarch64-linux/Dockerfile @@ -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 diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile index 01f19eac1d2fa..cb57478761994 100644 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile @@ -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