Skip to content

Commit e8e8983

Browse files
committed
Build the stdlib from rust-src sources.
1 parent 090817d commit e8e8983

File tree

1 file changed

+107
-2
lines changed

1 file changed

+107
-2
lines changed

collector/src/bin/rustc-perf-collector/sysroot.rs

Lines changed: 107 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,116 @@ impl Sysroot {
3939
};
4040

4141
download.get_and_extract(ModuleVariant::Rustc)?;
42-
download.get_and_extract(ModuleVariant::Std)?;
42+
// HACK(eddyb) commented out because we build our own stdlib
43+
// (see `fn build_std` below).
44+
// download.get_and_extract(ModuleVariant::Std)?;
4345
download.get_and_extract(ModuleVariant::Cargo)?;
4446
download.get_and_extract(ModuleVariant::RustSrc)?;
4547

46-
download.into_sysroot()
48+
let sysroot_dir = download.directory.join(&download.rust_sha);
49+
let sysroot = download.into_sysroot()?;
50+
51+
// FIXME(eddyb) remove this once we no longer need to
52+
// build our own stdlib (see `fn build_std` below).
53+
sysroot.build_std(sysroot_dir)?;
54+
55+
Ok(sysroot)
56+
}
57+
58+
/// Build `std`+`test`+`proc_macro` in a similar way to Cargo's `-Zbuild-std`
59+
/// feature, but only once, and move the resulting libraries into the sysroot.
60+
///
61+
/// We only need this until https://github.com/rust-lang/cargo/pull/8073
62+
/// reaches beta, because then `rust-lang/rust` builds will have that
63+
/// treatment. For now, we only have access to that Cargo change here,
64+
/// using the newly built Cargo.
65+
///
66+
/// For more background on why we need this, see this comment:
67+
/// https://github.com/rust-lang/rust/issues/69060#issuecomment-604928032
68+
/// (in short, Cargo used to include `rustc -vV` output, which contains
69+
/// the commit hash, into `-Cmetadata`, producing different `std`s,
70+
/// and making the perf runs incomparable, up to several % of difference).
71+
fn build_std(&self, sysroot_dir: PathBuf) -> anyhow::Result<()> {
72+
// Make sure everything below gets absolute directories.
73+
let sysroot_dir = sysroot_dir.canonicalize()?;
74+
75+
let sysroot_rustlib_dir = sysroot_dir.join("lib/rustlib");
76+
let rust_src_dir = sysroot_rustlib_dir.join("src/rust");
77+
78+
// HACK(eddyb) add a top-level `Cargo.toml` that has the necessary
79+
// `patch.crates-io` entries for `rustc-std-workspace-{core,alloc,std}`.
80+
// (maybe `rust-src` should include such a `Cargo.toml`?)
81+
fs::write(
82+
rust_src_dir.join("Cargo.toml"),
83+
"\
84+
[workspace]
85+
members = ['src/libtest']
86+
87+
[patch.crates-io]
88+
# See comments in `tools/rustc-std-workspace-core/README.md` for what's going on
89+
# here
90+
rustc-std-workspace-core = { path = 'src/tools/rustc-std-workspace-core' }
91+
rustc-std-workspace-alloc = { path = 'src/tools/rustc-std-workspace-alloc' }
92+
rustc-std-workspace-std = { path = 'src/tools/rustc-std-workspace-std' }
93+
",
94+
)?;
95+
96+
// HACK(eddyb) we need `std` to run the build scripts to build `std`.
97+
let vanilla_sysroot_dir = {
98+
let vanilla_download = SysrootDownload {
99+
directory: sysroot_dir.join("vanilla-sysroot"),
100+
rust_sha: self.sha.clone(),
101+
triple: self.triple.clone(),
102+
};
103+
vanilla_download.get_and_extract(ModuleVariant::Std)?;
104+
vanilla_download.directory.join(vanilla_download.rust_sha)
105+
};
106+
107+
let rustflags = format!(
108+
"--sysroot={sysroot} --remap-path-prefix={remap_from}={remap_to}",
109+
sysroot = vanilla_sysroot_dir.display(),
110+
remap_from = rust_src_dir.display(),
111+
remap_to = "/rustc/REDACTED_SHA_HASH/"
112+
);
113+
114+
// Run Cargo to produce `$local_build_target_dir/release/deps/lib*.rlib`.
115+
let local_build_target_dir = sysroot_dir.join("build-std-target");
116+
let cargo_status = std::process::Command::new(&self.cargo)
117+
.env("RUSTC", &self.rustc)
118+
.env("RUSTFLAGS", rustflags)
119+
.env("__CARGO_DEFAULT_LIB_METADATA", "rustc-perf-std")
120+
.args(&["build", "--release"])
121+
.arg("--target-dir")
122+
.arg(&local_build_target_dir)
123+
.args(&["--features", "panic-unwind", "--features", "backtrace"])
124+
.arg("--manifest-path")
125+
.arg(rust_src_dir.join("src/libtest/Cargo.toml"))
126+
.status()?;
127+
if !cargo_status.success() {
128+
return Err(anyhow!(
129+
"unable to build stdlib for {} triple {}",
130+
self.sha,
131+
self.triple
132+
));
133+
}
134+
135+
// Move all of the `rlib` files into the main sysroot.
136+
let sysroot_target_lib_dir = sysroot_rustlib_dir.join(&self.triple).join("lib");
137+
for entry in fs::read_dir(local_build_target_dir.join("release/deps"))? {
138+
let entry = entry?;
139+
let path = entry.path();
140+
if let (Some(name), Some(ext)) = (path.file_name(), path.extension()) {
141+
if ext == "rlib" {
142+
fs::rename(&path, sysroot_target_lib_dir.join(name))?;
143+
}
144+
}
145+
}
146+
147+
// Clean up, to avoid accidental usage of these directories.
148+
fs::remove_dir_all(vanilla_sysroot_dir)?;
149+
fs::remove_dir_all(local_build_target_dir)?;
150+
151+
Ok(())
47152
}
48153
}
49154

0 commit comments

Comments
 (0)