Skip to content

Commit 5508d36

Browse files
Rollup merge of #57286 - alexcrichton:less-thin-2-2, r=nikomatsakis
bootstrap: Link LLVM as a dylib with ThinLTO (take 2) When building a distributed compiler on Linux where we use ThinLTO to create the LLVM shared object this commit switches the compiler to dynamically linking that LLVM artifact instead of statically linking to LLVM. The primary goal here is to reduce CI compile times, avoiding two+ ThinLTO builds of all of LLVM. By linking dynamically to LLVM we'll reuse the one ThinLTO step done by LLVM's build itself. Lots of discussion about this change can be found [here] and down. A perf run will show whether this is worth it or not! [here]: #53245 (comment) --- This PR previously landed in #56944, caused #57111, and was reverted in #57116. I've added one more commit here which should fix the breakage that we saw.
2 parents e8472e4 + 71fed3a commit 5508d36

File tree

11 files changed

+30
-204
lines changed

11 files changed

+30
-204
lines changed

src/bootstrap/check.rs

-5
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ impl Step for Std {
3838
builder.info(&format!("Checking std artifacts ({} -> {})", &compiler.host, target));
3939
run_cargo(builder,
4040
&mut cargo,
41-
vec![],
4241
&libstd_stamp(builder, compiler, target),
4342
true);
4443

@@ -85,7 +84,6 @@ impl Step for Rustc {
8584
builder.info(&format!("Checking compiler artifacts ({} -> {})", &compiler.host, target));
8685
run_cargo(builder,
8786
&mut cargo,
88-
vec![],
8987
&librustc_stamp(builder, compiler, target),
9088
true);
9189

@@ -136,7 +134,6 @@ impl Step for CodegenBackend {
136134
let _folder = builder.fold_output(|| format!("stage{}-rustc_codegen_llvm", compiler.stage));
137135
run_cargo(builder,
138136
&mut cargo,
139-
vec![],
140137
&codegen_backend_stamp(builder, compiler, target, backend),
141138
true);
142139
}
@@ -174,7 +171,6 @@ impl Step for Test {
174171
builder.info(&format!("Checking test artifacts ({} -> {})", &compiler.host, target));
175172
run_cargo(builder,
176173
&mut cargo,
177-
vec![],
178174
&libtest_stamp(builder, compiler, target),
179175
true);
180176

@@ -222,7 +218,6 @@ impl Step for Rustdoc {
222218
println!("Checking rustdoc artifacts ({} -> {})", &compiler.host, target);
223219
run_cargo(builder,
224220
&mut cargo,
225-
vec![],
226221
&rustdoc_stamp(builder, compiler, target),
227222
true);
228223

src/bootstrap/compile.rs

+8-41
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use build_helper::{output, mtime, up_to_date};
1919
use filetime::FileTime;
2020
use serde_json;
2121

22+
use crate::dist;
2223
use crate::util::{exe, libdir, is_dylib};
2324
use crate::{Compiler, Mode, GitRepo};
2425
use crate::native;
@@ -104,7 +105,6 @@ impl Step for Std {
104105
&compiler.host, target));
105106
run_cargo(builder,
106107
&mut cargo,
107-
vec![],
108108
&libstd_stamp(builder, compiler, target),
109109
false);
110110

@@ -365,7 +365,6 @@ impl Step for Test {
365365
&compiler.host, target));
366366
run_cargo(builder,
367367
&mut cargo,
368-
vec![],
369368
&libtest_stamp(builder, compiler, target),
370369
false);
371370

@@ -493,7 +492,6 @@ impl Step for Rustc {
493492
compiler.stage, &compiler.host, target));
494493
run_cargo(builder,
495494
&mut cargo,
496-
vec![],
497495
&librustc_stamp(builder, compiler, target),
498496
false);
499497

@@ -636,47 +634,18 @@ impl Step for CodegenBackend {
636634

637635
let out_dir = builder.cargo_out(compiler, Mode::Codegen, target);
638636

639-
let mut cargo = builder.cargo(compiler, Mode::Codegen, target, "rustc");
637+
let mut cargo = builder.cargo(compiler, Mode::Codegen, target, "build");
640638
cargo.arg("--manifest-path")
641639
.arg(builder.src.join("src/librustc_codegen_llvm/Cargo.toml"));
642640
rustc_cargo_env(builder, &mut cargo);
643641

644642
let features = build_codegen_backend(&builder, &mut cargo, &compiler, target, backend);
645643

646-
let mut cargo_tails_args = vec![];
647-
648-
if builder.config.llvm_thin_lto {
649-
cargo_tails_args.push("--".to_string());
650-
651-
let num_jobs = builder.jobs();
652-
653-
if !target.contains("msvc") {
654-
// Here we assume that the linker is clang. If it's not, there'll
655-
// be linker errors.
656-
cargo_tails_args.push("-Clink-arg=-fuse-ld=lld".to_string());
657-
cargo_tails_args.push("-Clink-arg=-flto=thin".to_string());
658-
659-
if builder.config.llvm_optimize {
660-
cargo_tails_args.push("-Clink-arg=-O2".to_string());
661-
}
662-
663-
// Let's make LLD respect the `-j` option.
664-
let num_jobs_arg = format!("-Clink-arg=-Wl,--thinlto-jobs={}", num_jobs);
665-
cargo_tails_args.push(num_jobs_arg);
666-
} else {
667-
// Here we assume that the linker is lld-link.exe. lld-link.exe
668-
// does not need the extra arguments except for num_jobs
669-
let num_jobs_arg = format!("-Clink-arg=/opt:lldltojobs={}", num_jobs);
670-
cargo_tails_args.push(num_jobs_arg);
671-
}
672-
}
673-
674644
let tmp_stamp = out_dir.join(".tmp.stamp");
675645

676646
let _folder = builder.fold_output(|| format!("stage{}-rustc_codegen_llvm", compiler.stage));
677647
let files = run_cargo(builder,
678648
cargo.arg("--features").arg(features),
679-
cargo_tails_args,
680649
&tmp_stamp,
681650
false);
682651
if builder.config.dry_run {
@@ -749,7 +718,9 @@ pub fn build_codegen_backend(builder: &Builder,
749718
"libstdc++.a");
750719
cargo.env("LLVM_STATIC_STDCPP", file);
751720
}
752-
if builder.config.llvm_link_shared {
721+
if builder.config.llvm_link_shared ||
722+
(builder.config.llvm_thin_lto && backend != "emscripten")
723+
{
753724
cargo.env("LLVM_LINK_SHARED", "1");
754725
}
755726
}
@@ -989,6 +960,8 @@ impl Step for Assemble {
989960
copy_lld_to_sysroot(builder, target_compiler, &lld_install);
990961
}
991962

963+
dist::maybe_install_llvm_dylib(builder, target_compiler.host, &sysroot);
964+
992965
// Link the compiler binary itself into place
993966
let out_dir = builder.cargo_out(build_compiler, Mode::Rustc, host);
994967
let rustc = out_dir.join(exe("rustc_binary", &*host));
@@ -1015,7 +988,6 @@ pub fn add_to_sysroot(builder: &Builder, sysroot_dst: &Path, stamp: &Path) {
1015988

1016989
pub fn run_cargo(builder: &Builder,
1017990
cargo: &mut Command,
1018-
tail_args: Vec<String>,
1019991
stamp: &Path,
1020992
is_check: bool)
1021993
-> Vec<PathBuf>
@@ -1038,7 +1010,7 @@ pub fn run_cargo(builder: &Builder,
10381010
// files we need to probe for later.
10391011
let mut deps = Vec::new();
10401012
let mut toplevel = Vec::new();
1041-
let ok = stream_cargo(builder, cargo, tail_args, &mut |msg| {
1013+
let ok = stream_cargo(builder, cargo, &mut |msg| {
10421014
let filenames = match msg {
10431015
CargoMessage::CompilerArtifact { filenames, .. } => filenames,
10441016
_ => return,
@@ -1163,7 +1135,6 @@ pub fn run_cargo(builder: &Builder,
11631135
pub fn stream_cargo(
11641136
builder: &Builder,
11651137
cargo: &mut Command,
1166-
tail_args: Vec<String>,
11671138
cb: &mut dyn FnMut(CargoMessage),
11681139
) -> bool {
11691140
if builder.config.dry_run {
@@ -1174,10 +1145,6 @@ pub fn stream_cargo(
11741145
cargo.arg("--message-format").arg("json")
11751146
.stdout(Stdio::piped());
11761147

1177-
for arg in tail_args {
1178-
cargo.arg(arg);
1179-
}
1180-
11811148
builder.verbose(&format!("running: {:?}", cargo));
11821149
let mut child = match cargo.spawn() {
11831150
Ok(child) => child,

src/bootstrap/dist.rs

+16-8
Original file line numberDiff line numberDiff line change
@@ -671,10 +671,18 @@ impl Step for Std {
671671
let mut src = builder.sysroot_libdir(compiler, target).to_path_buf();
672672
src.pop(); // Remove the trailing /lib folder from the sysroot_libdir
673673
builder.cp_filtered(&src, &dst, &|path| {
674-
let name = path.file_name().and_then(|s| s.to_str());
675-
name != Some(builder.config.rust_codegen_backends_dir.as_str()) &&
676-
name != Some("bin")
677-
674+
if let Some(name) = path.file_name().and_then(|s| s.to_str()) {
675+
if name == builder.config.rust_codegen_backends_dir.as_str() {
676+
return false
677+
}
678+
if name == "bin" {
679+
return false
680+
}
681+
if name.contains("LLVM") {
682+
return false
683+
}
684+
}
685+
true
678686
});
679687

680688
let mut cmd = rust_installer(builder);
@@ -1877,13 +1885,13 @@ impl Step for HashSign {
18771885
// LLVM tools are linked dynamically.
18781886
// Note: This function does no yet support Windows but we also don't support
18791887
// linking LLVM tools dynamically on Windows yet.
1880-
fn maybe_install_llvm_dylib(builder: &Builder,
1881-
target: Interned<String>,
1882-
image: &Path) {
1888+
pub fn maybe_install_llvm_dylib(builder: &Builder,
1889+
target: Interned<String>,
1890+
sysroot: &Path) {
18831891
let src_libdir = builder
18841892
.llvm_out(target)
18851893
.join("lib");
1886-
let dst_libdir = image.join("lib/rustlib").join(&*target).join("lib");
1894+
let dst_libdir = sysroot.join("lib/rustlib").join(&*target).join("lib");
18871895
t!(fs::create_dir_all(&dst_libdir));
18881896

18891897
if target.contains("apple-darwin") {

src/bootstrap/tool.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ impl Step for ToolBuild {
7777
let _folder = builder.fold_output(|| format!("stage{}-{}", compiler.stage, tool));
7878
builder.info(&format!("Building stage{} tool {} ({})", compiler.stage, tool, target));
7979
let mut duplicates = Vec::new();
80-
let is_expected = compile::stream_cargo(builder, &mut cargo, vec![], &mut |msg| {
80+
let is_expected = compile::stream_cargo(builder, &mut cargo, &mut |msg| {
8181
// Only care about big things like the RLS/Cargo for now
8282
match tool {
8383
| "rls"

src/librustc_driver/lib.rs

+1-8
Original file line numberDiff line numberDiff line change
@@ -200,14 +200,7 @@ pub fn run<F>(run_compiler: F) -> isize
200200
}
201201

202202
fn load_backend_from_dylib(path: &Path) -> fn() -> Box<dyn CodegenBackend> {
203-
// Note that we're specifically using `open_global_now` here rather than
204-
// `open`, namely we want the behavior on Unix of RTLD_GLOBAL and RTLD_NOW,
205-
// where NOW means "bind everything right now" because we don't want
206-
// surprises later on and RTLD_GLOBAL allows the symbols to be made
207-
// available for future dynamic libraries opened. This is currently used by
208-
// loading LLVM and then making its symbols available for other dynamic
209-
// libraries.
210-
let lib = DynamicLibrary::open_global_now(path).unwrap_or_else(|err| {
203+
let lib = DynamicLibrary::open(Some(path)).unwrap_or_else(|err| {
211204
let err = format!("couldn't load codegen backend {:?}: {:?}", path, err);
212205
early_error(ErrorOutputType::default(), &err);
213206
});

src/librustc_llvm/build.rs

+4
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,10 @@ fn main() {
132132
continue;
133133
}
134134

135+
if flag.starts_with("-flto") {
136+
continue;
137+
}
138+
135139
// -Wdate-time is not supported by the netbsd cross compiler
136140
if is_crossed && target.contains("netbsd") && flag.contains("date-time") {
137141
continue;

src/test/run-make-fulldeps/llvm-pass/Makefile

-28
This file was deleted.

src/test/run-make-fulldeps/llvm-pass/llvm-function-pass.so.cc

-46
This file was deleted.

src/test/run-make-fulldeps/llvm-pass/llvm-module-pass.so.cc

-45
This file was deleted.

src/test/run-make-fulldeps/llvm-pass/main.rs

-4
This file was deleted.

src/test/run-make-fulldeps/llvm-pass/plugin.rs

-18
This file was deleted.

0 commit comments

Comments
 (0)