Skip to content

Commit 45497e3

Browse files
bootstrap: Allow for building LLVM with ThinLTO.
1 parent 34a654c commit 45497e3

File tree

6 files changed

+64
-4
lines changed

6 files changed

+64
-4
lines changed

config.toml.example

+6
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@
2121
# Indicates whether the LLVM build is a Release or Debug build
2222
#optimize = true
2323

24+
# Indicates whether LLVM should be built with ThinLTO. Note that this will
25+
# only succeed if you use clang, lld, llvm-ar, and llvm-ranlib in your C/C++
26+
# toolchain (see the `cc`, `cxx`, `linker`, `ar`, and `ranlib` options below).
27+
# More info at: https://clang.llvm.org/docs/ThinLTO.html#clang-bootstrap
28+
#thin-lto = false
29+
2430
# Indicates whether an LLVM Release build should include debug info
2531
#release-debuginfo = false
2632

src/bootstrap/check.rs

+5
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ impl Step for Std {
5050
println!("Checking std artifacts ({} -> {})", &compiler.host, target);
5151
run_cargo(builder,
5252
&mut cargo,
53+
vec![],
5354
&libstd_stamp(builder, compiler, target),
5455
true);
5556

@@ -98,6 +99,7 @@ impl Step for Rustc {
9899
println!("Checking compiler artifacts ({} -> {})", &compiler.host, target);
99100
run_cargo(builder,
100101
&mut cargo,
102+
vec![],
101103
&librustc_stamp(builder, compiler, target),
102104
true);
103105

@@ -149,6 +151,7 @@ impl Step for CodegenBackend {
149151
let _folder = builder.fold_output(|| format!("stage{}-rustc_codegen_llvm", compiler.stage));
150152
run_cargo(builder,
151153
&mut cargo,
154+
vec![],
152155
&codegen_backend_stamp(builder, compiler, target, backend),
153156
true);
154157
}
@@ -187,6 +190,7 @@ impl Step for Test {
187190
println!("Checking test artifacts ({} -> {})", &compiler.host, target);
188191
run_cargo(builder,
189192
&mut cargo,
193+
vec![],
190194
&libtest_stamp(builder, compiler, target),
191195
true);
192196

@@ -236,6 +240,7 @@ impl Step for Rustdoc {
236240
println!("Checking rustdoc artifacts ({} -> {})", &compiler.host, target);
237241
run_cargo(builder,
238242
&mut cargo,
243+
vec![],
239244
&rustdoc_stamp(builder, compiler, target),
240245
true);
241246

src/bootstrap/compile.rs

+44-3
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ impl Step for Std {
117117
&compiler.host, target));
118118
run_cargo(builder,
119119
&mut cargo,
120+
vec![],
120121
&libstd_stamp(builder, compiler, target),
121122
false);
122123

@@ -396,6 +397,7 @@ impl Step for Test {
396397
&compiler.host, target));
397398
run_cargo(builder,
398399
&mut cargo,
400+
vec![],
399401
&libtest_stamp(builder, compiler, target),
400402
false);
401403

@@ -529,6 +531,7 @@ impl Step for Rustc {
529531
compiler.stage, &compiler.host, target));
530532
run_cargo(builder,
531533
&mut cargo,
534+
vec![],
532535
&librustc_stamp(builder, compiler, target),
533536
false);
534537

@@ -673,18 +676,47 @@ impl Step for CodegenBackend {
673676
let out_dir = builder.cargo_out(compiler, Mode::Codegen, target);
674677
builder.clear_if_dirty(&out_dir, &librustc_stamp(builder, compiler, target));
675678

676-
let mut cargo = builder.cargo(compiler, Mode::Codegen, target, "build");
679+
let mut cargo = builder.cargo(compiler, Mode::Codegen, target, "rustc");
677680
cargo.arg("--manifest-path")
678681
.arg(builder.src.join("src/librustc_codegen_llvm/Cargo.toml"));
679682
rustc_cargo_env(builder, &mut cargo);
680683

681684
let features = build_codegen_backend(&builder, &mut cargo, &compiler, target, backend);
682685

686+
let mut cargo_tails_args = vec![];
687+
688+
if builder.config.llvm_thin_lto {
689+
cargo_tails_args.push("--".to_string());
690+
691+
let num_jobs = builder.jobs();
692+
693+
if !target.contains("msvc") {
694+
// Here we assume that the linker is clang. If it's not, there'll
695+
// be linker errors.
696+
cargo_tails_args.push("-Clink-arg=-fuse-ld=lld".to_string());
697+
cargo_tails_args.push("-Clink-arg=-flto=thin".to_string());
698+
699+
if builder.config.llvm_optimize {
700+
cargo_tails_args.push("-Clink-arg=-O2".to_string());
701+
}
702+
703+
// Let's make LLD respect the `-j` option.
704+
let num_jobs_arg = format!("-Clink-arg=-Wl,--thinlto-jobs={}", num_jobs);
705+
cargo_tails_args.push(num_jobs_arg);
706+
} else {
707+
// Here we assume that the linker is lld-link.exe. lld-link.exe
708+
// does not need the extra arguments except for num_jobs
709+
let num_jobs_arg = format!("-Clink-arg=/opt:lldltojobs={}", num_jobs);
710+
cargo_tails_args.push(num_jobs_arg);
711+
}
712+
}
713+
683714
let tmp_stamp = out_dir.join(".tmp.stamp");
684715

685716
let _folder = builder.fold_output(|| format!("stage{}-rustc_codegen_llvm", compiler.stage));
686717
let files = run_cargo(builder,
687718
cargo.arg("--features").arg(features),
719+
cargo_tails_args,
688720
&tmp_stamp,
689721
false);
690722
if builder.config.dry_run {
@@ -1045,7 +1077,11 @@ fn stderr_isatty() -> bool {
10451077
}
10461078
}
10471079

1048-
pub fn run_cargo(builder: &Builder, cargo: &mut Command, stamp: &Path, is_check: bool)
1080+
pub fn run_cargo(builder: &Builder,
1081+
cargo: &mut Command,
1082+
tail_args: Vec<String>,
1083+
stamp: &Path,
1084+
is_check: bool)
10491085
-> Vec<PathBuf>
10501086
{
10511087
if builder.config.dry_run {
@@ -1066,7 +1102,7 @@ pub fn run_cargo(builder: &Builder, cargo: &mut Command, stamp: &Path, is_check:
10661102
// files we need to probe for later.
10671103
let mut deps = Vec::new();
10681104
let mut toplevel = Vec::new();
1069-
let ok = stream_cargo(builder, cargo, &mut |msg| {
1105+
let ok = stream_cargo(builder, cargo, tail_args, &mut |msg| {
10701106
let filenames = match msg {
10711107
CargoMessage::CompilerArtifact { filenames, .. } => filenames,
10721108
_ => return,
@@ -1191,6 +1227,7 @@ pub fn run_cargo(builder: &Builder, cargo: &mut Command, stamp: &Path, is_check:
11911227
pub fn stream_cargo(
11921228
builder: &Builder,
11931229
cargo: &mut Command,
1230+
tail_args: Vec<String>,
11941231
cb: &mut dyn FnMut(CargoMessage),
11951232
) -> bool {
11961233
if builder.config.dry_run {
@@ -1210,6 +1247,10 @@ pub fn stream_cargo(
12101247
cargo.env("RUSTC_COLOR", "1");
12111248
}
12121249

1250+
for arg in tail_args {
1251+
cargo.arg(arg);
1252+
}
1253+
12131254
builder.verbose(&format!("running: {:?}", cargo));
12141255
let mut child = match cargo.spawn() {
12151256
Ok(child) => child,

src/bootstrap/config.rs

+3
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ pub struct Config {
7777
pub llvm_enabled: bool,
7878
pub llvm_assertions: bool,
7979
pub llvm_optimize: bool,
80+
pub llvm_thin_lto: bool,
8081
pub llvm_release_debuginfo: bool,
8182
pub llvm_version_check: bool,
8283
pub llvm_static_stdcpp: bool,
@@ -247,6 +248,7 @@ struct Llvm {
247248
ninja: Option<bool>,
248249
assertions: Option<bool>,
249250
optimize: Option<bool>,
251+
thin_lto: Option<bool>,
250252
release_debuginfo: Option<bool>,
251253
version_check: Option<bool>,
252254
static_libstdcpp: Option<bool>,
@@ -505,6 +507,7 @@ impl Config {
505507
set(&mut config.llvm_enabled, llvm.enabled);
506508
llvm_assertions = llvm.assertions;
507509
set(&mut config.llvm_optimize, llvm.optimize);
510+
set(&mut config.llvm_thin_lto, llvm.thin_lto);
508511
set(&mut config.llvm_release_debuginfo, llvm.release_debuginfo);
509512
set(&mut config.llvm_version_check, llvm.version_check);
510513
set(&mut config.llvm_static_stdcpp, llvm.static_libstdcpp);

src/bootstrap/native.rs

+5
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,11 @@ impl Step for Llvm {
153153
.define("LLVM_TARGET_ARCH", target.split('-').next().unwrap())
154154
.define("LLVM_DEFAULT_TARGET_TRIPLE", target);
155155

156+
if builder.config.llvm_thin_lto {
157+
cfg.define("LLVM_ENABLE_LTO", "Thin")
158+
.define("LLVM_ENABLE_LLD", "ON");
159+
}
160+
156161
// By default, LLVM will automatically find OCaml and, if it finds it,
157162
// install the LLVM bindings in LLVM_OCAML_INSTALL_PATH, which defaults
158163
// to /usr/bin/ocaml.

src/bootstrap/tool.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ impl Step for ToolBuild {
136136
let _folder = builder.fold_output(|| format!("stage{}-{}", compiler.stage, tool));
137137
builder.info(&format!("Building stage{} tool {} ({})", compiler.stage, tool, target));
138138
let mut duplicates = Vec::new();
139-
let is_expected = compile::stream_cargo(builder, &mut cargo, &mut |msg| {
139+
let is_expected = compile::stream_cargo(builder, &mut cargo, vec![], &mut |msg| {
140140
// Only care about big things like the RLS/Cargo for now
141141
match tool {
142142
| "rls"

0 commit comments

Comments
 (0)