Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit cbcf9a5

Browse files
committedSep 18, 2023
Auto merge of #115795 - Kobzol:opt-dist-custom, r=Mark-Simulacrum
Refactor `opt-dist` to simplify local building This PR refactors the `opt-dist` tool to make it easier to invoke it locally, outside of CI, and thus simplify building PGO/BOLT optimized `rustc` builds e.g. for distro maintainers. It should also make it easier to run the PGO/BOLT workflow locally e.g. to profile performance or debug issues (looking at you, #115554).
2 parents de68911 + ee451f8 commit cbcf9a5

File tree

15 files changed

+423
-277
lines changed

15 files changed

+423
-277
lines changed
 

‎.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,7 @@ jobs:
393393
- name: dist-x86_64-msvc
394394
env:
395395
RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --host=x86_64-pc-windows-msvc --target=x86_64-pc-windows-msvc --enable-full-tools --enable-profiler"
396-
SCRIPT: python x.py build --set rust.debug=true opt-dist && PGO_HOST=x86_64-pc-windows-msvc ./build/x86_64-pc-windows-msvc/stage0-tools-bin/opt-dist python x.py dist bootstrap --include-default-paths
396+
SCRIPT: python x.py build --set rust.debug=true opt-dist && PGO_HOST=x86_64-pc-windows-msvc ./build/x86_64-pc-windows-msvc/stage0-tools-bin/opt-dist windows-ci -- python x.py dist bootstrap --include-default-paths
397397
DIST_REQUIRE_ALL_TOOLS: 1
398398
os: windows-2019-8core-32gb
399399
- name: dist-i686-msvc

‎Cargo.lock

Lines changed: 72 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -858,14 +858,38 @@ dependencies = [
858858
"winapi",
859859
]
860860

861+
[[package]]
862+
name = "darling"
863+
version = "0.14.4"
864+
source = "registry+https://github.com/rust-lang/crates.io-index"
865+
checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850"
866+
dependencies = [
867+
"darling_core 0.14.4",
868+
"darling_macro 0.14.4",
869+
]
870+
861871
[[package]]
862872
name = "darling"
863873
version = "0.20.3"
864874
source = "registry+https://github.com/rust-lang/crates.io-index"
865875
checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e"
866876
dependencies = [
867-
"darling_core",
868-
"darling_macro",
877+
"darling_core 0.20.3",
878+
"darling_macro 0.20.3",
879+
]
880+
881+
[[package]]
882+
name = "darling_core"
883+
version = "0.14.4"
884+
source = "registry+https://github.com/rust-lang/crates.io-index"
885+
checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0"
886+
dependencies = [
887+
"fnv",
888+
"ident_case",
889+
"proc-macro2",
890+
"quote",
891+
"strsim",
892+
"syn 1.0.109",
869893
]
870894

871895
[[package]]
@@ -882,13 +906,24 @@ dependencies = [
882906
"syn 2.0.29",
883907
]
884908

909+
[[package]]
910+
name = "darling_macro"
911+
version = "0.14.4"
912+
source = "registry+https://github.com/rust-lang/crates.io-index"
913+
checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e"
914+
dependencies = [
915+
"darling_core 0.14.4",
916+
"quote",
917+
"syn 1.0.109",
918+
]
919+
885920
[[package]]
886921
name = "darling_macro"
887922
version = "0.20.3"
888923
source = "registry+https://github.com/rust-lang/crates.io-index"
889924
checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5"
890925
dependencies = [
891-
"darling_core",
926+
"darling_core 0.20.3",
892927
"quote",
893928
"syn 2.0.29",
894929
]
@@ -919,6 +954,37 @@ dependencies = [
919954
"syn 1.0.109",
920955
]
921956

957+
[[package]]
958+
name = "derive_builder"
959+
version = "0.12.0"
960+
source = "registry+https://github.com/rust-lang/crates.io-index"
961+
checksum = "8d67778784b508018359cbc8696edb3db78160bab2c2a28ba7f56ef6932997f8"
962+
dependencies = [
963+
"derive_builder_macro",
964+
]
965+
966+
[[package]]
967+
name = "derive_builder_core"
968+
version = "0.12.0"
969+
source = "registry+https://github.com/rust-lang/crates.io-index"
970+
checksum = "c11bdc11a0c47bc7d37d582b5285da6849c96681023680b906673c5707af7b0f"
971+
dependencies = [
972+
"darling 0.14.4",
973+
"proc-macro2",
974+
"quote",
975+
"syn 1.0.109",
976+
]
977+
978+
[[package]]
979+
name = "derive_builder_macro"
980+
version = "0.12.0"
981+
source = "registry+https://github.com/rust-lang/crates.io-index"
982+
checksum = "ebcda35c7a396850a55ffeac740804b40ffec779b98fffbb1738f4033f0ee79e"
983+
dependencies = [
984+
"derive_builder_core",
985+
"syn 1.0.109",
986+
]
987+
922988
[[package]]
923989
name = "derive_more"
924990
version = "0.99.17"
@@ -938,7 +1004,7 @@ version = "0.1.6"
9381004
source = "registry+https://github.com/rust-lang/crates.io-index"
9391005
checksum = "4e8ef033054e131169b8f0f9a7af8f5533a9436fadf3c500ed547f730f07090d"
9401006
dependencies = [
941-
"darling",
1007+
"darling 0.20.3",
9421008
"proc-macro2",
9431009
"quote",
9441010
"syn 2.0.29",
@@ -2584,6 +2650,8 @@ dependencies = [
25842650
"anyhow",
25852651
"build_helper",
25862652
"camino",
2653+
"clap",
2654+
"derive_builder",
25872655
"env_logger 0.10.0",
25882656
"fs_extra",
25892657
"glob",

‎src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ ENV RUST_CONFIGURE_ARGS \
8787
--set rust.lto=thin
8888

8989
ENV SCRIPT python3 ../x.py build --set rust.debug=true opt-dist && \
90-
./build/$HOSTS/stage0-tools-bin/opt-dist python3 ../x.py dist \
90+
./build/$HOSTS/stage0-tools-bin/opt-dist linux-ci -- python3 ../x.py dist \
9191
--host $HOSTS --target $HOSTS \
9292
--include-default-paths \
9393
build-manifest bootstrap

‎src/ci/github-actions/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -624,7 +624,7 @@ jobs:
624624
--target=x86_64-pc-windows-msvc
625625
--enable-full-tools
626626
--enable-profiler
627-
SCRIPT: python x.py build --set rust.debug=true opt-dist && PGO_HOST=x86_64-pc-windows-msvc ./build/x86_64-pc-windows-msvc/stage0-tools-bin/opt-dist python x.py dist bootstrap --include-default-paths
627+
SCRIPT: python x.py build --set rust.debug=true opt-dist && PGO_HOST=x86_64-pc-windows-msvc ./build/x86_64-pc-windows-msvc/stage0-tools-bin/opt-dist windows-ci -- python x.py dist bootstrap --include-default-paths
628628
DIST_REQUIRE_ALL_TOOLS: 1
629629
<<: *job-windows-8c
630630

‎src/tools/opt-dist/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,5 @@ serde = { version = "1", features = ["derive"] }
2121
serde_json = "1"
2222
glob = "0.3"
2323
tempfile = "3.5"
24+
derive_builder = "0.12"
25+
clap = { version = "4", features = ["derive"] }

‎src/tools/opt-dist/src/environment.rs

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
use camino::Utf8PathBuf;
2+
use derive_builder::Builder;
3+
4+
#[derive(Builder)]
5+
pub struct Environment {
6+
host_triple: String,
7+
python_binary: String,
8+
/// The rustc checkout, where the compiler source is located.
9+
checkout_dir: Utf8PathBuf,
10+
/// The main directory where the build occurs. Stage0 rustc and cargo have to be available in
11+
/// this directory before `opt-dist` is started.
12+
build_dir: Utf8PathBuf,
13+
/// Directory where the optimization artifacts (PGO/BOLT profiles, etc.)
14+
/// will be stored.
15+
artifact_dir: Utf8PathBuf,
16+
/// Path to the host LLVM used to compile LLVM in `src/llvm-project`.
17+
host_llvm_dir: Utf8PathBuf,
18+
/// List of test paths that should be skipped when testing the optimized artifacts.
19+
skipped_tests: Vec<String>,
20+
/// Directory containing a pre-built rustc-perf checkout.
21+
#[builder(default)]
22+
prebuilt_rustc_perf: Option<Utf8PathBuf>,
23+
use_bolt: bool,
24+
shared_llvm: bool,
25+
}
26+
27+
impl Environment {
28+
pub fn host_triple(&self) -> &str {
29+
&self.host_triple
30+
}
31+
32+
pub fn python_binary(&self) -> &str {
33+
&self.python_binary
34+
}
35+
36+
pub fn checkout_path(&self) -> Utf8PathBuf {
37+
self.checkout_dir.clone()
38+
}
39+
40+
pub fn build_root(&self) -> Utf8PathBuf {
41+
self.build_dir.clone()
42+
}
43+
44+
pub fn build_artifacts(&self) -> Utf8PathBuf {
45+
self.build_root().join("build").join(&self.host_triple)
46+
}
47+
48+
pub fn artifact_dir(&self) -> Utf8PathBuf {
49+
self.artifact_dir.clone()
50+
}
51+
52+
pub fn cargo_stage_0(&self) -> Utf8PathBuf {
53+
self.build_artifacts()
54+
.join("stage0")
55+
.join("bin")
56+
.join(format!("cargo{}", executable_extension()))
57+
}
58+
59+
pub fn rustc_stage_0(&self) -> Utf8PathBuf {
60+
self.build_artifacts()
61+
.join("stage0")
62+
.join("bin")
63+
.join(format!("rustc{}", executable_extension()))
64+
}
65+
66+
pub fn rustc_stage_2(&self) -> Utf8PathBuf {
67+
self.build_artifacts()
68+
.join("stage2")
69+
.join("bin")
70+
.join(format!("rustc{}", executable_extension()))
71+
}
72+
73+
pub fn prebuilt_rustc_perf(&self) -> Option<Utf8PathBuf> {
74+
self.prebuilt_rustc_perf.clone()
75+
}
76+
77+
/// Path to the built rustc-perf benchmark suite.
78+
pub fn rustc_perf_dir(&self) -> Utf8PathBuf {
79+
self.artifact_dir.join("rustc-perf")
80+
}
81+
82+
pub fn host_llvm_dir(&self) -> Utf8PathBuf {
83+
self.host_llvm_dir.clone()
84+
}
85+
86+
pub fn use_bolt(&self) -> bool {
87+
self.use_bolt
88+
}
89+
90+
pub fn supports_shared_llvm(&self) -> bool {
91+
self.shared_llvm
92+
}
93+
94+
pub fn skipped_tests(&self) -> &[String] {
95+
&self.skipped_tests
96+
}
97+
}
98+
99+
/// What is the extension of binary executables on this platform?
100+
#[cfg(target_family = "unix")]
101+
pub fn executable_extension() -> &'static str {
102+
""
103+
}
104+
105+
#[cfg(target_family = "windows")]
106+
pub fn executable_extension() -> &'static str {
107+
".exe"
108+
}

‎src/tools/opt-dist/src/environment/linux.rs

Lines changed: 0 additions & 58 deletions
This file was deleted.

‎src/tools/opt-dist/src/environment/mod.rs

Lines changed: 0 additions & 77 deletions
This file was deleted.

‎src/tools/opt-dist/src/environment/windows.rs

Lines changed: 0 additions & 92 deletions
This file was deleted.

‎src/tools/opt-dist/src/exec.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ pub struct Bootstrap {
9696
}
9797

9898
impl Bootstrap {
99-
pub fn build(env: &dyn Environment) -> Self {
99+
pub fn build(env: &Environment) -> Self {
100100
let metrics_path = env.build_root().join("build").join("metrics.json");
101101
let cmd = cmd(&[
102102
env.python_binary(),
@@ -114,7 +114,7 @@ impl Bootstrap {
114114
Self { cmd, metrics_path }
115115
}
116116

117-
pub fn dist(env: &dyn Environment, dist_args: &[String]) -> Self {
117+
pub fn dist(env: &Environment, dist_args: &[String]) -> Self {
118118
let metrics_path = env.build_root().join("build").join("metrics.json");
119119
let cmd = cmd(&dist_args.iter().map(|arg| arg.as_str()).collect::<Vec<_>>())
120120
.env("RUST_BACKTRACE", "full");

‎src/tools/opt-dist/src/main.rs

Lines changed: 212 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,22 @@
11
use crate::bolt::{bolt_optimize, with_bolt_instrumented};
22
use anyhow::Context;
3+
use camino::{Utf8Path, Utf8PathBuf};
4+
use clap::Parser;
35
use log::LevelFilter;
6+
use std::io::Cursor;
7+
use std::time::Duration;
48
use utils::io;
9+
use zip::ZipArchive;
510

6-
use crate::environment::{create_environment, Environment};
7-
use crate::exec::Bootstrap;
11+
use crate::environment::{Environment, EnvironmentBuilder};
12+
use crate::exec::{cmd, Bootstrap};
813
use crate::tests::run_tests;
914
use crate::timer::Timer;
1015
use crate::training::{gather_llvm_bolt_profiles, gather_llvm_profiles, gather_rustc_profiles};
11-
use crate::utils::io::reset_directory;
16+
use crate::utils::io::{copy_directory, move_directory, reset_directory};
1217
use crate::utils::{
1318
clear_llvm_files, format_env_variables, print_binary_sizes, print_free_disk_space,
14-
with_log_group,
19+
retry_action, with_log_group,
1520
};
1621

1722
mod bolt;
@@ -23,24 +28,169 @@ mod timer;
2328
mod training;
2429
mod utils;
2530

31+
#[derive(clap::Parser, Debug)]
32+
struct Args {
33+
#[clap(subcommand)]
34+
env: EnvironmentCmd,
35+
}
36+
37+
#[derive(clap::Parser, Clone, Debug)]
38+
struct SharedArgs {
39+
// Arguments passed to `x` to perform the final (dist) build.
40+
build_args: Vec<String>,
41+
}
42+
43+
#[derive(clap::Parser, Clone, Debug)]
44+
enum EnvironmentCmd {
45+
/// Perform a custom local PGO/BOLT optimized build.
46+
Local {
47+
/// Target triple of the host.
48+
#[arg(long)]
49+
target_triple: String,
50+
51+
/// Checkout directory of `rustc`.
52+
#[arg(long)]
53+
checkout_dir: Utf8PathBuf,
54+
55+
/// Host LLVM installation directory.
56+
#[arg(long)]
57+
llvm_dir: Utf8PathBuf,
58+
59+
/// Python binary to use in bootstrap invocations.
60+
#[arg(long, default_value = "python3")]
61+
python: String,
62+
63+
/// Directory where artifacts (like PGO profiles or rustc-perf) of this workflow
64+
/// will be stored.
65+
#[arg(long, default_value = "opt-artifacts")]
66+
artifact_dir: Utf8PathBuf,
67+
68+
/// Is LLVM for `rustc` built in shared library mode?
69+
#[arg(long, default_value_t = true)]
70+
llvm_shared: bool,
71+
72+
/// Should BOLT optimization be used? If yes, host LLVM must have BOLT binaries
73+
/// (`llvm-bolt` and `merge-fdata`) available.
74+
#[arg(long, default_value_t = false)]
75+
use_bolt: bool,
76+
77+
/// Tests that should be skipped when testing the optimized compiler.
78+
#[arg(long)]
79+
skipped_tests: Vec<String>,
80+
81+
#[clap(flatten)]
82+
shared: SharedArgs,
83+
},
84+
/// Perform an optimized build on Linux CI, from inside Docker.
85+
LinuxCi {
86+
#[clap(flatten)]
87+
shared: SharedArgs,
88+
},
89+
/// Perform an optimized build on Windows CI, directly inside Github Actions.
90+
WindowsCi {
91+
#[clap(flatten)]
92+
shared: SharedArgs,
93+
},
94+
}
95+
2696
fn is_try_build() -> bool {
2797
std::env::var("DIST_TRY_BUILD").unwrap_or_else(|_| "0".to_string()) != "0"
2898
}
2999

100+
fn create_environment(args: Args) -> anyhow::Result<(Environment, Vec<String>)> {
101+
let (env, args) = match args.env {
102+
EnvironmentCmd::Local {
103+
target_triple,
104+
checkout_dir,
105+
llvm_dir,
106+
python,
107+
artifact_dir,
108+
llvm_shared,
109+
use_bolt,
110+
skipped_tests,
111+
shared,
112+
} => {
113+
let env = EnvironmentBuilder::default()
114+
.host_triple(target_triple)
115+
.python_binary(python)
116+
.checkout_dir(checkout_dir.clone())
117+
.host_llvm_dir(llvm_dir)
118+
.artifact_dir(artifact_dir)
119+
.build_dir(checkout_dir)
120+
.shared_llvm(llvm_shared)
121+
.use_bolt(use_bolt)
122+
.skipped_tests(skipped_tests)
123+
.build()?;
124+
125+
(env, shared.build_args)
126+
}
127+
EnvironmentCmd::LinuxCi { shared } => {
128+
let target_triple =
129+
std::env::var("PGO_HOST").expect("PGO_HOST environment variable missing");
130+
131+
let checkout_dir = Utf8PathBuf::from("/checkout");
132+
let env = EnvironmentBuilder::default()
133+
.host_triple(target_triple)
134+
.python_binary("python3".to_string())
135+
.checkout_dir(checkout_dir.clone())
136+
.host_llvm_dir(Utf8PathBuf::from("/rustroot"))
137+
.artifact_dir(Utf8PathBuf::from("/tmp/tmp-multistage/opt-artifacts"))
138+
.build_dir(checkout_dir.join("obj"))
139+
// /tmp/rustc-perf comes from the x64 dist Dockerfile
140+
.prebuilt_rustc_perf(Some(Utf8PathBuf::from("/tmp/rustc-perf")))
141+
.shared_llvm(true)
142+
.use_bolt(true)
143+
.skipped_tests(vec![
144+
// Fails because of linker errors, as of June 2023.
145+
"tests/ui/process/nofile-limit.rs".to_string(),
146+
])
147+
.build()?;
148+
149+
(env, shared.build_args)
150+
}
151+
EnvironmentCmd::WindowsCi { shared } => {
152+
let target_triple =
153+
std::env::var("PGO_HOST").expect("PGO_HOST environment variable missing");
154+
155+
let checkout_dir: Utf8PathBuf = std::env::current_dir()?.try_into()?;
156+
let env = EnvironmentBuilder::default()
157+
.host_triple(target_triple)
158+
.python_binary("python".to_string())
159+
.checkout_dir(checkout_dir.clone())
160+
.host_llvm_dir(checkout_dir.join("citools").join("clang-rust"))
161+
.artifact_dir(checkout_dir.join("opt-artifacts"))
162+
.build_dir(checkout_dir)
163+
.shared_llvm(false)
164+
.use_bolt(false)
165+
.skipped_tests(vec![
166+
// Fails as of June 2023.
167+
"tests\\codegen\\vec-shrink-panik.rs".to_string(),
168+
])
169+
.build()?;
170+
171+
(env, shared.build_args)
172+
}
173+
};
174+
Ok((env, args))
175+
}
176+
30177
fn execute_pipeline(
31-
env: &dyn Environment,
178+
env: &Environment,
32179
timer: &mut Timer,
33180
dist_args: Vec<String>,
34181
) -> anyhow::Result<()> {
35-
reset_directory(&env.opt_artifacts())?;
182+
reset_directory(&env.artifact_dir())?;
36183

37-
with_log_group("Building rustc-perf", || env.prepare_rustc_perf())?;
184+
with_log_group("Building rustc-perf", || match env.prebuilt_rustc_perf() {
185+
Some(dir) => copy_rustc_perf(env, &dir),
186+
None => download_rustc_perf(env),
187+
})?;
38188

39189
// Stage 1: Build PGO instrumented rustc
40190
// We use a normal build of LLVM, because gathering PGO profiles for LLVM and `rustc` at the
41191
// same time can cause issues, because the host and in-tree LLVM versions can diverge.
42192
let rustc_pgo_profile = timer.section("Stage 1 (Rustc PGO)", |stage| {
43-
let rustc_profile_dir_root = env.opt_artifacts().join("rustc-pgo");
193+
let rustc_profile_dir_root = env.artifact_dir().join("rustc-pgo");
44194

45195
stage.section("Build PGO instrumented rustc and LLVM", |section| {
46196
let mut builder = Bootstrap::build(env).rustc_pgo_instrument(&rustc_profile_dir_root);
@@ -74,7 +224,7 @@ fn execute_pipeline(
74224
// Remove the previous, uninstrumented build of LLVM.
75225
clear_llvm_files(env)?;
76226

77-
let llvm_profile_dir_root = env.opt_artifacts().join("llvm-pgo");
227+
let llvm_profile_dir_root = env.artifact_dir().join("llvm-pgo");
78228

79229
stage.section("Build PGO instrumented LLVM", |section| {
80230
Bootstrap::build(env)
@@ -95,7 +245,7 @@ fn execute_pipeline(
95245
Ok(profile)
96246
})?;
97247

98-
let llvm_bolt_profile = if env.supports_bolt() {
248+
let llvm_bolt_profile = if env.use_bolt() {
99249
// Stage 3: Build BOLT instrumented LLVM
100250
// We build a PGO optimized LLVM in this step, then instrument it with BOLT and gather BOLT profiles.
101251
// Note that we don't remove LLVM artifacts after this step, so that they are reused in the final dist build.
@@ -171,8 +321,9 @@ fn main() -> anyhow::Result<()> {
171321
.parse_default_env()
172322
.init();
173323

174-
let mut build_args: Vec<String> = std::env::args().skip(1).collect();
175-
println!("Running optimized build pipeline with args `{}`", build_args.join(" "));
324+
let args = Args::parse();
325+
326+
println!("Running optimized build pipeline with args `{:?}`", args);
176327

177328
with_log_group("Environment values", || {
178329
println!("Environment values\n{}", format_env_variables());
@@ -184,6 +335,8 @@ fn main() -> anyhow::Result<()> {
184335
}
185336
});
186337

338+
let (env, mut build_args) = create_environment(args).context("Cannot create environment")?;
339+
187340
// Skip components that are not needed for try builds to speed them up
188341
if is_try_build() {
189342
log::info!("Skipping building of unimportant components for a try build");
@@ -202,14 +355,58 @@ fn main() -> anyhow::Result<()> {
202355
}
203356

204357
let mut timer = Timer::new();
205-
let env = create_environment();
206358

207-
let result = execute_pipeline(env.as_ref(), &mut timer, build_args);
359+
let result = execute_pipeline(&env, &mut timer, build_args);
208360
log::info!("Timer results\n{}", timer.format_stats());
209361

210362
print_free_disk_space()?;
211363
result.context("Optimized build pipeline has failed")?;
212-
print_binary_sizes(env.as_ref())?;
364+
print_binary_sizes(&env)?;
365+
366+
Ok(())
367+
}
368+
369+
// Copy rustc-perf from the given path into the environment and build it.
370+
fn copy_rustc_perf(env: &Environment, dir: &Utf8Path) -> anyhow::Result<()> {
371+
copy_directory(dir, &env.rustc_perf_dir())?;
372+
build_rustc_perf(env)
373+
}
374+
375+
// Download and build rustc-perf into the given environment.
376+
fn download_rustc_perf(env: &Environment) -> anyhow::Result<()> {
377+
reset_directory(&env.rustc_perf_dir())?;
378+
379+
// FIXME: add some mechanism for synchronization of this commit SHA with
380+
// Linux (which builds rustc-perf in a Dockerfile)
381+
// rustc-perf version from 2023-05-30
382+
const PERF_COMMIT: &str = "8b2ac3042e1ff2c0074455a0a3618adef97156b1";
383+
384+
let url = format!("https://ci-mirrors.rust-lang.org/rustc/rustc-perf-{PERF_COMMIT}.zip");
385+
let client = reqwest::blocking::Client::builder()
386+
.timeout(Duration::from_secs(60 * 2))
387+
.connect_timeout(Duration::from_secs(60 * 2))
388+
.build()?;
389+
let response = retry_action(
390+
|| Ok(client.get(&url).send()?.error_for_status()?.bytes()?.to_vec()),
391+
"Download rustc-perf archive",
392+
5,
393+
)?;
394+
395+
let mut archive = ZipArchive::new(Cursor::new(response))?;
396+
archive.extract(env.rustc_perf_dir())?;
397+
move_directory(
398+
&env.rustc_perf_dir().join(format!("rustc-perf-{PERF_COMMIT}")),
399+
&env.rustc_perf_dir(),
400+
)?;
401+
402+
build_rustc_perf(env)
403+
}
213404

405+
fn build_rustc_perf(env: &Environment) -> anyhow::Result<()> {
406+
cmd(&[env.cargo_stage_0().as_str(), "build", "-p", "collector"])
407+
.workdir(&env.rustc_perf_dir())
408+
.env("RUSTC", &env.rustc_stage_0().into_string())
409+
.env("RUSTC_BOOTSTRAP", "1")
410+
.run()?;
214411
Ok(())
215412
}

‎src/tools/opt-dist/src/tests.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
use crate::environment::Environment;
1+
use crate::environment::{executable_extension, Environment};
22
use crate::exec::cmd;
33
use crate::utils::io::{copy_directory, find_file_in_dir, unpack_archive};
44
use anyhow::Context;
55
use camino::{Utf8Path, Utf8PathBuf};
66

77
/// Run tests on optimized dist artifacts.
8-
pub fn run_tests(env: &dyn Environment) -> anyhow::Result<()> {
8+
pub fn run_tests(env: &Environment) -> anyhow::Result<()> {
99
// After `dist` is executed, we extract its archived components into a sysroot directory,
1010
// and then use that extracted rustc as a stage0 compiler.
1111
// Then we run a subset of tests using that compiler, to have a basic smoke test which checks
@@ -33,8 +33,8 @@ pub fn run_tests(env: &dyn Environment) -> anyhow::Result<()> {
3333

3434
// We need to manually copy libstd to the extracted rustc sysroot
3535
copy_directory(
36-
&libstd_dir.join("lib").join("rustlib").join(&host_triple).join("lib"),
37-
&rustc_dir.join("lib").join("rustlib").join(&host_triple).join("lib"),
36+
&libstd_dir.join("lib").join("rustlib").join(host_triple).join("lib"),
37+
&rustc_dir.join("lib").join("rustlib").join(host_triple).join("lib"),
3838
)?;
3939

4040
// Extract sources - they aren't in the `rustc-nightly-{host}` tarball, so we need to manually copy libstd
@@ -45,9 +45,9 @@ pub fn run_tests(env: &dyn Environment) -> anyhow::Result<()> {
4545
&rustc_dir.join("lib").join("rustlib").join("src"),
4646
)?;
4747

48-
let rustc_path = rustc_dir.join("bin").join(format!("rustc{}", env.executable_extension()));
48+
let rustc_path = rustc_dir.join("bin").join(format!("rustc{}", executable_extension()));
4949
assert!(rustc_path.is_file());
50-
let cargo_path = cargo_dir.join("bin").join(format!("cargo{}", env.executable_extension()));
50+
let cargo_path = cargo_dir.join("bin").join(format!("cargo{}", executable_extension()));
5151
assert!(cargo_path.is_file());
5252

5353
// Specify path to a LLVM config so that LLVM is not rebuilt.
@@ -56,7 +56,7 @@ pub fn run_tests(env: &dyn Environment) -> anyhow::Result<()> {
5656
.build_artifacts()
5757
.join("llvm")
5858
.join("bin")
59-
.join(format!("llvm-config{}", env.executable_extension()));
59+
.join(format!("llvm-config{}", executable_extension()));
6060
assert!(llvm_config.is_file());
6161

6262
let config_content = format!(
@@ -109,6 +109,6 @@ fn find_dist_version(directory: &Utf8Path) -> anyhow::Result<String> {
109109
.unwrap()
110110
.to_string();
111111
let (version, _) =
112-
archive.strip_prefix("reproducible-artifacts-").unwrap().split_once("-").unwrap();
112+
archive.strip_prefix("reproducible-artifacts-").unwrap().split_once('-').unwrap();
113113
Ok(version.to_string())
114114
}

‎src/tools/opt-dist/src/training.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::environment::Environment;
1+
use crate::environment::{executable_extension, Environment};
22
use crate::exec::{cmd, CmdBuilder};
33
use crate::utils::io::{count_files, delete_directory};
44
use crate::utils::with_log_group;
@@ -30,7 +30,7 @@ const RUSTC_PGO_CRATES: &[&str] = &[
3030
const LLVM_BOLT_CRATES: &[&str] = LLVM_PGO_CRATES;
3131

3232
fn init_compiler_benchmarks(
33-
env: &dyn Environment,
33+
env: &Environment,
3434
profiles: &[&str],
3535
scenarios: &[&str],
3636
crates: &[&str],
@@ -75,7 +75,7 @@ enum LlvmProfdata {
7575
}
7676

7777
fn merge_llvm_profiles(
78-
env: &dyn Environment,
78+
env: &Environment,
7979
merged_path: &Utf8Path,
8080
profile_dir: &Utf8Path,
8181
profdata: LlvmProfdata,
@@ -86,7 +86,7 @@ fn merge_llvm_profiles(
8686
.build_artifacts()
8787
.join("llvm")
8888
.join("build")
89-
.join(format!("bin/llvm-profdata{}", env.executable_extension())),
89+
.join(format!("bin/llvm-profdata{}", executable_extension())),
9090
};
9191

9292
cmd(&[llvm_profdata.as_str(), "merge", "-o", merged_path.as_str(), profile_dir.as_str()])
@@ -116,7 +116,7 @@ fn log_profile_stats(
116116
pub struct LlvmPGOProfile(pub Utf8PathBuf);
117117

118118
pub fn gather_llvm_profiles(
119-
env: &dyn Environment,
119+
env: &Environment,
120120
profile_root: &Utf8Path,
121121
) -> anyhow::Result<LlvmPGOProfile> {
122122
log::info!("Running benchmarks with PGO instrumented LLVM");
@@ -127,7 +127,7 @@ pub fn gather_llvm_profiles(
127127
.context("Cannot gather LLVM PGO profiles")
128128
})?;
129129

130-
let merged_profile = env.opt_artifacts().join("llvm-pgo.profdata");
130+
let merged_profile = env.artifact_dir().join("llvm-pgo.profdata");
131131
log::info!("Merging LLVM PGO profiles to {merged_profile}");
132132

133133
merge_llvm_profiles(env, &merged_profile, profile_root, LlvmProfdata::Host)?;
@@ -143,7 +143,7 @@ pub fn gather_llvm_profiles(
143143
pub struct RustcPGOProfile(pub Utf8PathBuf);
144144

145145
pub fn gather_rustc_profiles(
146-
env: &dyn Environment,
146+
env: &Environment,
147147
profile_root: &Utf8Path,
148148
) -> anyhow::Result<RustcPGOProfile> {
149149
log::info!("Running benchmarks with PGO instrumented rustc");
@@ -163,7 +163,7 @@ pub fn gather_rustc_profiles(
163163
.context("Cannot gather rustc PGO profiles")
164164
})?;
165165

166-
let merged_profile = env.opt_artifacts().join("rustc-pgo.profdata");
166+
let merged_profile = env.artifact_dir().join("rustc-pgo.profdata");
167167
log::info!("Merging Rustc PGO profiles to {merged_profile}");
168168

169169
merge_llvm_profiles(env, &merged_profile, profile_root, LlvmProfdata::Target)?;
@@ -178,7 +178,7 @@ pub fn gather_rustc_profiles(
178178

179179
pub struct LlvmBoltProfile(pub Utf8PathBuf);
180180

181-
pub fn gather_llvm_bolt_profiles(env: &dyn Environment) -> anyhow::Result<LlvmBoltProfile> {
181+
pub fn gather_llvm_bolt_profiles(env: &Environment) -> anyhow::Result<LlvmBoltProfile> {
182182
log::info!("Running benchmarks with BOLT instrumented LLVM");
183183

184184
with_log_group("Running benchmarks", || {
@@ -187,12 +187,12 @@ pub fn gather_llvm_bolt_profiles(env: &dyn Environment) -> anyhow::Result<LlvmBo
187187
.context("Cannot gather LLVM BOLT profiles")
188188
})?;
189189

190-
let merged_profile = env.opt_artifacts().join("llvm-bolt.profdata");
190+
let merged_profile = env.artifact_dir().join("llvm-bolt.profdata");
191191
let profile_root = Utf8PathBuf::from("/tmp/prof.fdata");
192192
log::info!("Merging LLVM BOLT profiles to {merged_profile}");
193193

194194
let profiles: Vec<_> =
195-
glob::glob(&format!("{profile_root}*"))?.into_iter().collect::<Result<Vec<_>, _>>()?;
195+
glob::glob(&format!("{profile_root}*"))?.collect::<Result<Vec<_>, _>>()?;
196196

197197
let mut merge_args = vec!["merge-fdata"];
198198
merge_args.extend(profiles.iter().map(|p| p.to_str().unwrap()));

‎src/tools/opt-dist/src/utils/io.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use std::path::Path;
77
/// Delete and re-create the directory.
88
pub fn reset_directory(path: &Utf8Path) -> anyhow::Result<()> {
99
log::info!("Resetting directory {path}");
10-
let _ = std::fs::remove_dir(path);
10+
let _ = std::fs::remove_dir_all(path);
1111
std::fs::create_dir_all(path)?;
1212
Ok(())
1313
}
@@ -63,7 +63,6 @@ pub fn get_files_from_dir(
6363
let path = format!("{dir}/*{}", suffix.unwrap_or(""));
6464

6565
Ok(glob::glob(&path)?
66-
.into_iter()
6766
.map(|p| p.map(|p| Utf8PathBuf::from_path_buf(p).unwrap()))
6867
.collect::<Result<Vec<_>, _>>()?)
6968
}
@@ -74,9 +73,8 @@ pub fn find_file_in_dir(
7473
prefix: &str,
7574
suffix: &str,
7675
) -> anyhow::Result<Utf8PathBuf> {
77-
let files = glob::glob(&format!("{directory}/{prefix}*{suffix}"))?
78-
.into_iter()
79-
.collect::<Result<Vec<_>, _>>()?;
76+
let files =
77+
glob::glob(&format!("{directory}/{prefix}*{suffix}"))?.collect::<Result<Vec<_>, _>>()?;
8078
match files.len() {
8179
0 => Err(anyhow::anyhow!("No file with prefix {prefix} found in {directory}")),
8280
1 => Ok(Utf8PathBuf::from_path_buf(files[0].clone()).unwrap()),

‎src/tools/opt-dist/src/utils/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ pub fn print_free_disk_space() -> anyhow::Result<()> {
2626
Ok(())
2727
}
2828

29-
pub fn print_binary_sizes(env: &dyn Environment) -> anyhow::Result<()> {
29+
pub fn print_binary_sizes(env: &Environment) -> anyhow::Result<()> {
3030
use std::fmt::Write;
3131

3232
let root = env.build_artifacts().join("stage2");
@@ -48,7 +48,7 @@ pub fn print_binary_sizes(env: &dyn Environment) -> anyhow::Result<()> {
4848
Ok(())
4949
}
5050

51-
pub fn clear_llvm_files(env: &dyn Environment) -> anyhow::Result<()> {
51+
pub fn clear_llvm_files(env: &Environment) -> anyhow::Result<()> {
5252
// Bootstrap currently doesn't support rebuilding LLVM when PGO options
5353
// change (or any other llvm-related options); so just clear out the relevant
5454
// directories ourselves.

0 commit comments

Comments
 (0)
Please sign in to comment.