Skip to content

Commit 5a8c051

Browse files
committed
Auto merge of rust-lang#124129 - lqd:enable-lld, r=<try>
Enable `rust-lld` on nightly `x86_64-unknown-linux-gnu` r? ghost Draft until final preparations are done (making a bootstrap change entry requires a PR number)
2 parents 0e15f5e + f63b7c5 commit 5a8c051

File tree

11 files changed

+127
-16
lines changed

11 files changed

+127
-16
lines changed

compiler/rustc_target/src/spec/mod.rs

+6
Original file line numberDiff line numberDiff line change
@@ -625,6 +625,12 @@ impl LinkSelfContainedDefault {
625625
_ => "crt-objects-fallback",
626626
}
627627
}
628+
629+
/// Creates a `LinkSelfContainedDefault` enabling the self-contained linker for target specs
630+
/// (the equivalent of `-Clink-self-contained=+linker` on the CLI).
631+
pub fn with_linker() -> LinkSelfContainedDefault {
632+
LinkSelfContainedDefault::WithComponents(LinkSelfContainedComponents::LINKER)
633+
}
628634
}
629635

630636
bitflags::bitflags! {

compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs

+8
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,14 @@ pub fn target() -> Target {
1818
| SanitizerSet::THREAD;
1919
base.supports_xray = true;
2020

21+
#[cfg(use_rust_lld)]
22+
{
23+
// When we're asked to use the `rust-lld` linker by default, set the appropriate lld-using
24+
// linker flavor, and self-contained linker component.
25+
base.linker_flavor = LinkerFlavor::Gnu(Cc::Yes, Lld::Yes);
26+
base.link_self_contained = crate::spec::LinkSelfContainedDefault::with_linker();
27+
}
28+
2129
Target {
2230
llvm_target: "x86_64-unknown-linux-gnu".into(),
2331
metadata: crate::spec::TargetMetadata {

config.example.toml

+6-3
Original file line numberDiff line numberDiff line change
@@ -652,9 +652,12 @@
652652
# when no explicit backend is specified.
653653
#codegen-backends = ["llvm"]
654654

655-
# Indicates whether LLD will be compiled and made available in the sysroot for
656-
# rustc to execute.
657-
#lld = false
655+
# Indicates whether LLD will be compiled and made available in the sysroot for rustc to execute, and
656+
# whether to set it as rustc's default linker on `x86_64-unknown-linux-gnu`. This will also only be
657+
# when *not* building an external LLVM (so only when using `download-ci-llvm` or building LLVM from
658+
# the in-tree source): setting `llvm-config` in the `[target.x86_64-unknown-linux-gnu]` section will
659+
# make this default to false.
660+
#lld = false in all cases, except on `x86_64-unknown-linux-gnu` as described above, where it is true
658661

659662
# Indicates whether LLD will be used to link Rust crates during bootstrap on
660663
# supported platforms.

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

+6
Original file line numberDiff line numberDiff line change
@@ -1129,6 +1129,12 @@ pub fn rustc_cargo_env(
11291129
cargo.env("CFG_DEFAULT_LINKER", s);
11301130
}
11311131

1132+
// Enable rustc's cfgs for `rust-lld` when requested.
1133+
if builder.config.lld_enabled {
1134+
cargo.rustflag("--cfg=use_rust_lld");
1135+
cargo.rustdocflag("--cfg=use_rust_lld");
1136+
}
1137+
11321138
if builder.config.rust_verify_llvm_ir {
11331139
cargo.env("RUSTC_VERIFY_LLVM_IR", "1");
11341140
}

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

+40-11
Original file line numberDiff line numberDiff line change
@@ -1551,6 +1551,7 @@ impl Config {
15511551
let mut debuginfo_level_tests = None;
15521552
let mut optimize = None;
15531553
let mut omit_git_hash = None;
1554+
let mut lld_enabled = None;
15541555

15551556
if let Some(rust) = toml.rust {
15561557
let Rust {
@@ -1584,7 +1585,7 @@ impl Config {
15841585
dist_src,
15851586
save_toolstates,
15861587
codegen_backends,
1587-
lld,
1588+
lld: lld_enabled_toml,
15881589
llvm_tools,
15891590
llvm_bitcode_linker,
15901591
deny_warnings,
@@ -1639,6 +1640,7 @@ impl Config {
16391640
debuginfo_level_std = debuginfo_level_std_toml;
16401641
debuginfo_level_tools = debuginfo_level_tools_toml;
16411642
debuginfo_level_tests = debuginfo_level_tests_toml;
1643+
lld_enabled = lld_enabled_toml;
16421644

16431645
config.rust_split_debuginfo_for_build_triple = split_debuginfo
16441646
.as_deref()
@@ -1672,18 +1674,8 @@ impl Config {
16721674
config.incremental = true;
16731675
}
16741676
set(&mut config.lld_mode, lld_mode);
1675-
set(&mut config.lld_enabled, lld);
16761677
set(&mut config.llvm_bitcode_linker_enabled, llvm_bitcode_linker);
16771678

1678-
if matches!(config.lld_mode, LldMode::SelfContained)
1679-
&& !config.lld_enabled
1680-
&& flags.stage.unwrap_or(0) > 0
1681-
{
1682-
panic!(
1683-
"Trying to use self-contained lld as a linker, but LLD is not being added to the sysroot. Enable it with rust.lld = true."
1684-
);
1685-
}
1686-
16871679
config.llvm_tools_enabled = llvm_tools.unwrap_or(true);
16881680
config.rustc_parallel =
16891681
parallel_compiler.unwrap_or(config.channel == "dev" || config.channel == "nightly");
@@ -1973,6 +1965,43 @@ impl Config {
19731965
config.llvm_plugins = llvm_plugins.unwrap_or(false);
19741966
config.rust_optimize = optimize.unwrap_or(RustOptimize::Bool(true));
19751967

1968+
// We make `x86_64-unknown-linux-gnu` use the self-contained linker by default, so we will
1969+
// build our internal lld and use it as the default linker, by setting the `rust.lld` config
1970+
// to true by default:
1971+
// - on the `x86_64-unknown-linux-gnu` target
1972+
// - on the `dev` and `nightly` channels
1973+
// - when building our in-tree llvm (i.e. the target has not set an `llvm-config`), so that
1974+
// we're also able to build the corresponding lld
1975+
// - or when using an external llvm that's downloaded from CI, which also contains our prebuilt
1976+
// lld
1977+
// - otherwise, we'd be using an external llvm, and lld would not necessarily available and
1978+
// thus, disabled
1979+
// - similarly, lld will not be built nor used by default when explicitly asked not to, e.g.
1980+
// when the config sets `rust.lld = false`
1981+
if config.build.triple == "x86_64-unknown-linux-gnu"
1982+
&& config.hosts == &[config.build]
1983+
&& (config.channel == "dev" || config.channel == "nightly")
1984+
{
1985+
let no_llvm_config = config
1986+
.target_config
1987+
.get(&config.build)
1988+
.is_some_and(|target_config| target_config.llvm_config.is_none());
1989+
let enable_lld = config.llvm_from_ci || no_llvm_config;
1990+
// Prefer the config setting in case an explicit opt-out is needed.
1991+
config.lld_enabled = lld_enabled.unwrap_or(enable_lld);
1992+
} else {
1993+
set(&mut config.lld_enabled, lld_enabled);
1994+
}
1995+
1996+
if matches!(config.lld_mode, LldMode::SelfContained)
1997+
&& !config.lld_enabled
1998+
&& flags.stage.unwrap_or(0) > 0
1999+
{
2000+
panic!(
2001+
"Trying to use self-contained lld as a linker, but LLD is not being added to the sysroot. Enable it with rust.lld = true."
2002+
);
2003+
}
2004+
19762005
let default = debug == Some(true);
19772006
config.rust_debug_assertions = debug_assertions.unwrap_or(default);
19782007
config.rust_debug_assertions_std =

src/bootstrap/src/lib.rs

+4
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,10 @@ const EXTRA_CHECK_CFGS: &[(Option<Mode>, &str, Option<&[&'static str]>)] = &[
114114
// Needed to avoid the need to copy windows.lib into the sysroot.
115115
(Some(Mode::Rustc), "windows_raw_dylib", None),
116116
(Some(Mode::ToolRustc), "windows_raw_dylib", None),
117+
// If rustc wants to use rust-lld as the default linker in a target spec.
118+
(Some(Mode::Rustc), "use_rust_lld", None),
119+
(Some(Mode::ToolRustc), "use_rust_lld", None),
120+
(Some(Mode::Codegen), "use_rust_lld", None),
117121
];
118122

119123
/// A structure representing a Rust compiler.

src/bootstrap/src/utils/change_tracker.rs

+5
Original file line numberDiff line numberDiff line change
@@ -175,4 +175,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[
175175
severity: ChangeSeverity::Warning,
176176
summary: "The deprecated field `changelog-seen` has been removed. Using that field in `config.toml` from now on will result in breakage.",
177177
},
178+
ChangeInfo {
179+
change_id: 124129,
180+
severity: ChangeSeverity::Warning,
181+
summary: "`rust.lld` has a new default value of `true` on `x86_64-unknown-linux-gnu`. Starting at stage1, `rust-lld` will thus be this target's default linker. No config changes should be necessary.",
182+
},
178183
];

src/ci/docker/host-x86_64/x86_64-gnu-llvm-17/Dockerfile

+2-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ ENV RUST_CONFIGURE_ARGS \
5454
--build=x86_64-unknown-linux-gnu \
5555
--llvm-root=/usr/lib/llvm-17 \
5656
--enable-llvm-link-shared \
57-
--set rust.thin-lto-import-instr-limit=10
57+
--set rust.thin-lto-import-instr-limit=10 \
58+
--set rust.lld=false
5859

5960
COPY host-x86_64/dist-x86_64-linux/shared.sh /scripts/
6061
COPY host-x86_64/dist-x86_64-linux/build-gccjit.sh /scripts/

src/ci/docker/host-x86_64/x86_64-gnu-llvm-18/Dockerfile

+2-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ ENV RUST_CONFIGURE_ARGS \
5151
--build=x86_64-unknown-linux-gnu \
5252
--llvm-root=/usr/lib/llvm-18 \
5353
--enable-llvm-link-shared \
54-
--set rust.thin-lto-import-instr-limit=10
54+
--set rust.thin-lto-import-instr-limit=10 \
55+
--set rust.lld=false
5556

5657
COPY host-x86_64/dist-x86_64-linux/shared.sh /scripts/
5758
COPY host-x86_64/dist-x86_64-linux/build-gccjit.sh /scripts/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// Test linking using `cc` with `rust-lld`, which is on by default on the x86_64-unknown-linux-gnu
2+
// target.
3+
// See https://github.com/rust-lang/compiler-team/issues/510 for more info
4+
5+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Ensure that rust-lld is used as the default linker on `x86_64-unknown-linux-gnu`, and that it can
2+
// also be turned off with a CLI flag.
3+
4+
//@ needs-rust-lld
5+
//@ only-x86_64-unknown-linux-gnu
6+
7+
extern crate run_make_support;
8+
9+
use run_make_support::regex::Regex;
10+
use run_make_support::rustc;
11+
use std::process::Output;
12+
13+
fn main() {
14+
// A regular compilation should use rust-lld by default. We'll check that by asking the linker
15+
// to display its version number with a link-arg.
16+
let output = rustc()
17+
.env("RUSTC_LOG", "rustc_codegen_ssa::back::link=info")
18+
.link_arg("-Wl,-v")
19+
.input("main.rs")
20+
.run();
21+
assert!(
22+
find_lld_version_in_logs(output),
23+
"the LLD version string should be present in the output logs"
24+
);
25+
26+
// But it can still be disabled by turning the linker feature off.
27+
let output = rustc()
28+
.env("RUSTC_LOG", "rustc_codegen_ssa::back::link=info")
29+
.link_arg("-Wl,-v")
30+
.arg("-Zlinker-features=-lld")
31+
.input("main.rs")
32+
.run();
33+
assert!(
34+
!find_lld_version_in_logs(output),
35+
"the LLD version string should not be present in the output logs"
36+
);
37+
}
38+
39+
fn find_lld_version_in_logs(output: Output) -> bool {
40+
let lld_version_re = Regex::new(r"^LLD [0-9]+\.[0-9]+\.[0-9]+").unwrap();
41+
let stderr = std::str::from_utf8(&output.stderr).unwrap();
42+
stderr.lines().any(|line| lld_version_re.is_match(line))
43+
}

0 commit comments

Comments
 (0)