Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit fc2a4c1

Browse files
committed
Introduce LldMode and generalize parsing of use-lld
1 parent ede763a commit fc2a4c1

File tree

5 files changed

+99
-12
lines changed

5 files changed

+99
-12
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -870,7 +870,7 @@ impl Step for Rustc {
870870
// is already on by default in MSVC optimized builds, which is interpreted as --icf=all:
871871
// https://github.com/llvm/llvm-project/blob/3329cec2f79185bafd678f310fafadba2a8c76d2/lld/COFF/Driver.cpp#L1746
872872
// https://github.com/rust-lang/rust/blob/f22819bcce4abaff7d1246a56eec493418f9f4ee/compiler/rustc_codegen_ssa/src/back/linker.rs#L827
873-
if builder.config.use_lld && !compiler.host.is_msvc() {
873+
if builder.config.lld_mode.is_used() && !compiler.host.is_msvc() {
874874
cargo.rustflag("-Clink-args=-Wl,--icf=all");
875875
}
876876

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

Lines changed: 74 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,39 @@ impl Display for DebuginfoLevel {
105105
}
106106
}
107107

108+
/// LLD in bootstrap works like this:
109+
/// - Self-contained lld: use `rust-lld` from the compiler's sysroot
110+
/// - External: use an external `lld` binary
111+
///
112+
/// It is configured depending on the target:
113+
/// 1) Everything except MSVC
114+
/// - Self-contained: -Clinker-flavor=gnu-lld-cc -Clink-self-contained=+linker
115+
/// - External: -Clinker-flavor=gnu-lld-cc
116+
/// 2) MSVC
117+
/// - Self-contained: -Clinker=<path to rust-lld>
118+
/// - External: -Clinker=lld
119+
#[derive(Default, Clone)]
120+
pub enum LldMode {
121+
/// Do not use LLD
122+
#[default]
123+
Unused,
124+
/// Use `rust-lld` from the compiler's sysroot
125+
SelfContained,
126+
/// Use an externally provided `lld` binary.
127+
/// Note that the linker name cannot be overridden, the binary has to be named `lld` and it has
128+
/// to be in $PATH.
129+
External,
130+
}
131+
132+
impl LldMode {
133+
pub fn is_used(&self) -> bool {
134+
match self {
135+
LldMode::SelfContained | LldMode::External => true,
136+
LldMode::Unused => false,
137+
}
138+
}
139+
}
140+
108141
/// Global configuration for the entire build and/or bootstrap.
109142
///
110143
/// This structure is parsed from `config.toml`, and some of the fields are inferred from `git` or build-time parameters.
@@ -198,7 +231,7 @@ pub struct Config {
198231
pub llvm_from_ci: bool,
199232
pub llvm_build_config: HashMap<String, String>,
200233

201-
pub use_lld: bool,
234+
pub lld_mode: LldMode,
202235
pub lld_enabled: bool,
203236
pub llvm_tools_enabled: bool,
204237

@@ -978,6 +1011,44 @@ enum StringOrInt<'a> {
9781011
String(&'a str),
9791012
Int(i64),
9801013
}
1014+
1015+
impl<'de> Deserialize<'de> for LldMode {
1016+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1017+
where
1018+
D: Deserializer<'de>,
1019+
{
1020+
struct LldModeVisitor;
1021+
1022+
impl<'de> serde::de::Visitor<'de> for LldModeVisitor {
1023+
type Value = LldMode;
1024+
1025+
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1026+
formatter.write_str("one of true, 'self-contained' or 'external'")
1027+
}
1028+
1029+
fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
1030+
where
1031+
E: serde::de::Error,
1032+
{
1033+
Ok(if v { LldMode::External } else { LldMode::Unused })
1034+
}
1035+
1036+
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
1037+
where
1038+
E: serde::de::Error,
1039+
{
1040+
match v {
1041+
"external" => Ok(LldMode::External),
1042+
"self-contained" => Ok(LldMode::SelfContained),
1043+
_ => Err(E::custom("unknown mode {v}")),
1044+
}
1045+
}
1046+
}
1047+
1048+
deserializer.deserialize_any(LldModeVisitor)
1049+
}
1050+
}
1051+
9811052
define_config! {
9821053
/// TOML representation of how the Rust build is configured.
9831054
struct Rust {
@@ -1013,7 +1084,7 @@ define_config! {
10131084
save_toolstates: Option<String> = "save-toolstates",
10141085
codegen_backends: Option<Vec<String>> = "codegen-backends",
10151086
lld: Option<bool> = "lld",
1016-
use_lld: Option<bool> = "use-lld",
1087+
lld_mode: Option<LldMode> = "use-lld",
10171088
llvm_tools: Option<bool> = "llvm-tools",
10181089
deny_warnings: Option<bool> = "deny-warnings",
10191090
backtrace_on_ice: Option<bool> = "backtrace-on-ice",
@@ -1436,7 +1507,7 @@ impl Config {
14361507
if let Some(true) = rust.incremental {
14371508
config.incremental = true;
14381509
}
1439-
set(&mut config.use_lld, rust.use_lld);
1510+
set(&mut config.lld_mode, rust.lld_mode);
14401511
set(&mut config.lld_enabled, rust.lld);
14411512
set(&mut config.llvm_tools_enabled, rust.llvm_tools);
14421513
config.rustc_parallel = rust

src/bootstrap/src/lib.rs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ use utils::channel::GitInfo;
3737

3838
use crate::core::builder;
3939
use crate::core::builder::Kind;
40-
use crate::core::config::flags;
40+
use crate::core::config::{flags, LldMode};
4141
use crate::core::config::{DryRun, Target};
4242
use crate::core::config::{LlvmLibunwind, TargetSelection};
4343
use crate::utils::cache::{Interned, INTERNER};
@@ -1260,17 +1260,24 @@ impl Build {
12601260
&& !target.is_msvc()
12611261
{
12621262
Some(self.cc(target))
1263-
} else if self.config.use_lld && !self.is_fuse_ld_lld(target) && self.build == target {
1264-
Some(self.initial_lld.clone())
1263+
} else if self.config.lld_mode.is_used()
1264+
&& self.is_lld_direct_linker(target)
1265+
&& self.build == target
1266+
{
1267+
match self.config.lld_mode {
1268+
LldMode::SelfContained => Some(self.initial_lld.clone()),
1269+
LldMode::External => Some("lld".into()),
1270+
LldMode::Unused => None,
1271+
}
12651272
} else {
12661273
None
12671274
}
12681275
}
12691276

1270-
// LLD is used through `-fuse-ld=lld` rather than directly.
1277+
// Is LLD configured directly through `-Clinker`?
12711278
// Only MSVC targets use LLD directly at the moment.
1272-
fn is_fuse_ld_lld(&self, target: TargetSelection) -> bool {
1273-
self.config.use_lld && !target.is_msvc()
1279+
fn is_lld_direct_linker(&self, target: TargetSelection) -> bool {
1280+
target.is_msvc()
12741281
}
12751282

12761283
/// Returns if this target should statically link the C runtime, if specified

src/bootstrap/src/tests/config.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
use crate::core::config::TomlConfig;
21
use super::{Config, Flags};
2+
use crate::core::config::{LldMode, TomlConfig};
33

44
use clap::CommandFactory;
55
use serde::Deserialize;
@@ -217,3 +217,12 @@ fn verify_file_integrity() {
217217

218218
remove_file(tempfile).unwrap();
219219
}
220+
221+
#[test]
222+
fn rust_lld() {
223+
assert!(matches!(parse("").lld_mode, LldMode::Unused));
224+
assert!(matches!(parse("rust.use-lld = \"self-contained\"").lld_mode, LldMode::SelfContained));
225+
assert!(matches!(parse("rust.use-lld = \"external\"").lld_mode, LldMode::External));
226+
assert!(matches!(parse("rust.use-lld = true").lld_mode, LldMode::External));
227+
assert!(matches!(parse("rust.use-lld = false").lld_mode, LldMode::Unused));
228+
}

src/bootstrap/src/utils/helpers.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -499,7 +499,7 @@ pub fn linker_flags(
499499
lld_threads: LldThreads,
500500
) -> Vec<String> {
501501
let mut args = vec![];
502-
if builder.is_fuse_ld_lld(target) {
502+
if !builder.is_lld_direct_linker(target) && builder.config.lld_mode.is_used() {
503503
args.push(String::from("-Clink-arg=-fuse-ld=lld"));
504504

505505
if matches!(lld_threads, LldThreads::No) {

0 commit comments

Comments
 (0)