bootstrap/core/build_steps/
run.rs1use std::path::PathBuf;
7
8use clap_complete::{Generator, shells};
9
10use crate::core::build_steps::dist::distdir;
11use crate::core::build_steps::test;
12use crate::core::build_steps::tool::{self, RustcPrivateCompilers, SourceType, Tool};
13use crate::core::build_steps::vendor::{Vendor, default_paths_to_vendor};
14use crate::core::builder::{Builder, Kind, RunConfig, ShouldRun, Step};
15use crate::core::config::TargetSelection;
16use crate::core::config::flags::get_completion;
17use crate::utils::exec::command;
18use crate::{Mode, t};
19
20#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
21pub struct BuildManifest;
22
23impl Step for BuildManifest {
24 type Output = ();
25 const IS_HOST: bool = true;
26
27 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
28 run.path("src/tools/build-manifest")
29 }
30
31 fn make_run(run: RunConfig<'_>) {
32 run.builder.ensure(BuildManifest);
33 }
34
35 fn run(self, builder: &Builder<'_>) {
36 let mut cmd = builder.tool_cmd(Tool::BuildManifest);
39 let sign = builder.config.dist_sign_folder.as_ref().unwrap_or_else(|| {
40 panic!("\n\nfailed to specify `dist.sign-folder` in `bootstrap.toml`\n\n")
41 });
42 let addr = builder.config.dist_upload_addr.as_ref().unwrap_or_else(|| {
43 panic!("\n\nfailed to specify `dist.upload-addr` in `bootstrap.toml`\n\n")
44 });
45
46 let today = command("date").arg("+%Y-%m-%d").run_capture_stdout(builder).stdout();
47
48 cmd.arg(sign);
49 cmd.arg(distdir(builder));
50 cmd.arg(today.trim());
51 cmd.arg(addr);
52 cmd.arg(&builder.config.channel);
53
54 builder.create_dir(&distdir(builder));
55 cmd.run(builder);
56 }
57}
58
59#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
60pub struct BumpStage0;
61
62impl Step for BumpStage0 {
63 type Output = ();
64 const IS_HOST: bool = true;
65
66 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
67 run.path("src/tools/bump-stage0")
68 }
69
70 fn make_run(run: RunConfig<'_>) {
71 run.builder.ensure(BumpStage0);
72 }
73
74 fn run(self, builder: &Builder<'_>) -> Self::Output {
75 let mut cmd = builder.tool_cmd(Tool::BumpStage0);
76 cmd.args(builder.config.args());
77 cmd.run(builder);
78 }
79}
80
81#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
82pub struct ReplaceVersionPlaceholder;
83
84impl Step for ReplaceVersionPlaceholder {
85 type Output = ();
86 const IS_HOST: bool = true;
87
88 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
89 run.path("src/tools/replace-version-placeholder")
90 }
91
92 fn make_run(run: RunConfig<'_>) {
93 run.builder.ensure(ReplaceVersionPlaceholder);
94 }
95
96 fn run(self, builder: &Builder<'_>) -> Self::Output {
97 let mut cmd = builder.tool_cmd(Tool::ReplaceVersionPlaceholder);
98 cmd.arg(&builder.src);
99 cmd.run(builder);
100 }
101}
102
103#[derive(Debug, Clone, PartialEq, Eq, Hash)]
104pub struct Miri {
105 target: TargetSelection,
106}
107
108impl Step for Miri {
109 type Output = ();
110
111 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
112 run.path("src/tools/miri")
113 }
114
115 fn make_run(run: RunConfig<'_>) {
116 run.builder.ensure(Miri { target: run.target });
117 }
118
119 fn run(self, builder: &Builder<'_>) {
120 let host = builder.build.host_target;
121 let target = self.target;
122
123 let stage = if builder.config.is_explicit_stage() || builder.top_stage >= 1 {
126 builder.top_stage
127 } else {
128 1
129 };
130
131 if stage == 0 {
132 eprintln!("miri cannot be run at stage 0");
133 std::process::exit(1);
134 }
135
136 let compilers = RustcPrivateCompilers::new(builder, stage, target);
138 let miri_build = builder.ensure(tool::Miri::from_compilers(compilers));
139 let host_compiler = miri_build.build_compiler;
140
141 let miri_sysroot =
143 test::Miri::build_miri_sysroot(builder, compilers.target_compiler(), target);
144
145 let mut miri = tool::prepare_tool_cargo(
149 builder,
150 host_compiler,
151 Mode::ToolRustc,
152 host,
153 Kind::Run,
154 "src/tools/miri",
155 SourceType::InTree,
156 &[],
157 );
158 miri.add_rustc_lib_path(builder);
159 miri.arg("--").arg("--target").arg(target.rustc_target_arg());
160
161 miri.arg("--sysroot").arg(miri_sysroot);
163
164 miri.args(builder.config.args());
167
168 miri.into_cmd().run(builder);
169 }
170}
171
172#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
173pub struct CollectLicenseMetadata;
174
175impl Step for CollectLicenseMetadata {
176 type Output = PathBuf;
177 const IS_HOST: bool = true;
178
179 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
180 run.path("src/tools/collect-license-metadata")
181 }
182
183 fn make_run(run: RunConfig<'_>) {
184 run.builder.ensure(CollectLicenseMetadata);
185 }
186
187 fn run(self, builder: &Builder<'_>) -> Self::Output {
188 let Some(reuse) = &builder.config.reuse else {
189 panic!("REUSE is required to collect the license metadata");
190 };
191
192 let dest = builder.src.join("license-metadata.json");
193
194 let mut cmd = builder.tool_cmd(Tool::CollectLicenseMetadata);
195 cmd.env("REUSE_EXE", reuse);
196 cmd.env("DEST", &dest);
197 cmd.run(builder);
198
199 dest
200 }
201}
202
203#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
204pub struct GenerateCopyright;
205
206impl Step for GenerateCopyright {
207 type Output = Vec<PathBuf>;
208 const IS_HOST: bool = true;
209
210 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
211 run.path("src/tools/generate-copyright")
212 }
213
214 fn make_run(run: RunConfig<'_>) {
215 run.builder.ensure(GenerateCopyright);
216 }
217
218 fn run(self, builder: &Builder<'_>) -> Self::Output {
219 let license_metadata = builder.src.join("license-metadata.json");
220 let dest = builder.out.join("COPYRIGHT.html");
221 let dest_libstd = builder.out.join("COPYRIGHT-library.html");
222
223 let paths_to_vendor = default_paths_to_vendor(builder);
224 for (_, submodules) in &paths_to_vendor {
225 for submodule in submodules {
226 builder.build.require_submodule(submodule, None);
227 }
228 }
229 let cargo_manifests = paths_to_vendor
230 .into_iter()
231 .map(|(path, _submodules)| path.to_str().unwrap().to_string())
232 .inspect(|path| assert!(!path.contains(','), "{path} contains a comma in its name"))
233 .collect::<Vec<_>>()
234 .join(",");
235
236 let vendored_sources = if let Some(path) = builder.vendored_crates_path() {
237 path
238 } else {
239 let cache_dir = builder.out.join("tmp").join("generate-copyright-vendor");
240 builder.ensure(Vendor {
241 sync_args: Vec::new(),
242 versioned_dirs: true,
243 root_dir: builder.src.clone(),
244 output_dir: cache_dir.clone(),
245 });
246 cache_dir
247 };
248
249 let mut cmd = builder.tool_cmd(Tool::GenerateCopyright);
250 cmd.env("CARGO_MANIFESTS", &cargo_manifests);
251 cmd.env("LICENSE_METADATA", &license_metadata);
252 cmd.env("DEST", &dest);
253 cmd.env("DEST_LIBSTD", &dest_libstd);
254 cmd.env("SRC_DIR", &builder.src);
255 cmd.env("VENDOR_DIR", &vendored_sources);
256 cmd.env("CARGO", &builder.initial_cargo);
257 cmd.env("CARGO_HOME", t!(home::cargo_home()));
258 cmd.current_dir(&builder.src);
261 cmd.run(builder);
262
263 vec![dest, dest_libstd]
264 }
265}
266
267#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
268pub struct GenerateWindowsSys;
269
270impl Step for GenerateWindowsSys {
271 type Output = ();
272 const IS_HOST: bool = true;
273
274 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
275 run.path("src/tools/generate-windows-sys")
276 }
277
278 fn make_run(run: RunConfig<'_>) {
279 run.builder.ensure(GenerateWindowsSys);
280 }
281
282 fn run(self, builder: &Builder<'_>) {
283 let mut cmd = builder.tool_cmd(Tool::GenerateWindowsSys);
284 cmd.arg(&builder.src);
285 cmd.run(builder);
286 }
287}
288
289pub fn get_completion_paths(builder: &Builder<'_>) -> Vec<(&'static dyn Generator, PathBuf)> {
291 vec![
292 (&shells::Bash as &'static dyn Generator, builder.src.join("src/etc/completions/x.py.sh")),
293 (&shells::Zsh, builder.src.join("src/etc/completions/x.py.zsh")),
294 (&shells::Fish, builder.src.join("src/etc/completions/x.py.fish")),
295 (&shells::PowerShell, builder.src.join("src/etc/completions/x.py.ps1")),
296 (&shells::Bash, builder.src.join("src/etc/completions/x.sh")),
297 (&shells::Zsh, builder.src.join("src/etc/completions/x.zsh")),
298 (&shells::Fish, builder.src.join("src/etc/completions/x.fish")),
299 (&shells::PowerShell, builder.src.join("src/etc/completions/x.ps1")),
300 ]
301}
302
303#[derive(Debug, Clone, PartialEq, Eq, Hash)]
304pub struct GenerateCompletions;
305
306impl Step for GenerateCompletions {
307 type Output = ();
308
309 fn run(self, builder: &Builder<'_>) {
311 for (shell, path) in get_completion_paths(builder) {
312 if let Some(comp) = get_completion(shell, &path) {
313 std::fs::write(&path, comp).unwrap_or_else(|e| {
314 panic!("writing completion into {} failed: {e:?}", path.display())
315 });
316 }
317 }
318 }
319
320 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
321 run.alias("generate-completions")
322 }
323
324 fn make_run(run: RunConfig<'_>) {
325 run.builder.ensure(GenerateCompletions);
326 }
327}
328
329#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
330pub struct UnicodeTableGenerator;
331
332impl Step for UnicodeTableGenerator {
333 type Output = ();
334 const IS_HOST: bool = true;
335
336 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
337 run.path("src/tools/unicode-table-generator")
338 }
339
340 fn make_run(run: RunConfig<'_>) {
341 run.builder.ensure(UnicodeTableGenerator);
342 }
343
344 fn run(self, builder: &Builder<'_>) {
345 let mut cmd = builder.tool_cmd(Tool::UnicodeTableGenerator);
346 cmd.arg(builder.src.join("library/core/src/unicode/unicode_data.rs"));
347 cmd.run(builder);
348 }
349}
350
351#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
352pub struct FeaturesStatusDump;
353
354impl Step for FeaturesStatusDump {
355 type Output = ();
356 const IS_HOST: bool = true;
357
358 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
359 run.path("src/tools/features-status-dump")
360 }
361
362 fn make_run(run: RunConfig<'_>) {
363 run.builder.ensure(FeaturesStatusDump);
364 }
365
366 fn run(self, builder: &Builder<'_>) {
367 let mut cmd = builder.tool_cmd(Tool::FeaturesStatusDump);
368
369 cmd.arg("--library-path");
370 cmd.arg(builder.src.join("library"));
371
372 cmd.arg("--compiler-path");
373 cmd.arg(builder.src.join("compiler"));
374
375 cmd.arg("--output-path");
376 cmd.arg(builder.out.join("features-status-dump.json"));
377
378 cmd.run(builder);
379 }
380}
381
382#[derive(Clone, Debug, PartialEq, Eq, Hash)]
385pub struct CyclicStep {
386 n: u32,
387}
388
389impl Step for CyclicStep {
390 type Output = ();
391
392 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
393 run.alias("cyclic-step")
394 }
395
396 fn make_run(run: RunConfig<'_>) {
397 run.builder.ensure(CyclicStep { n: 2 })
399 }
400
401 fn run(self, builder: &Builder<'_>) -> Self::Output {
402 builder.ensure(CyclicStep { n: self.n.saturating_sub(1) })
404 }
405}
406
407#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
412pub struct CoverageDump;
413
414impl Step for CoverageDump {
415 type Output = ();
416
417 const DEFAULT: bool = false;
418 const IS_HOST: bool = true;
419
420 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
421 run.path("src/tools/coverage-dump")
422 }
423
424 fn make_run(run: RunConfig<'_>) {
425 run.builder.ensure(Self {});
426 }
427
428 fn run(self, builder: &Builder<'_>) {
429 let mut cmd = builder.tool_cmd(Tool::CoverageDump);
430 cmd.args(&builder.config.free_args);
431 cmd.run(builder);
432 }
433}
434
435#[derive(Debug, Clone, PartialEq, Eq, Hash)]
436pub struct Rustfmt;
437
438impl Step for Rustfmt {
439 type Output = ();
440 const IS_HOST: bool = true;
441
442 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
443 run.path("src/tools/rustfmt")
444 }
445
446 fn make_run(run: RunConfig<'_>) {
447 run.builder.ensure(Rustfmt);
448 }
449
450 fn run(self, builder: &Builder<'_>) {
451 let host = builder.build.host_target;
452
453 let stage = if builder.config.is_explicit_stage() || builder.top_stage >= 1 {
456 builder.top_stage
457 } else {
458 1
459 };
460
461 if stage == 0 {
462 eprintln!("rustfmt cannot be run at stage 0");
463 eprintln!("HELP: Use `x fmt` to use stage 0 rustfmt.");
464 std::process::exit(1);
465 }
466
467 let compilers = RustcPrivateCompilers::new(builder, stage, host);
468 let rustfmt_build = builder.ensure(tool::Rustfmt::from_compilers(compilers));
469
470 let mut rustfmt = tool::prepare_tool_cargo(
471 builder,
472 rustfmt_build.build_compiler,
473 Mode::ToolRustc,
474 host,
475 Kind::Run,
476 "src/tools/rustfmt",
477 SourceType::InTree,
478 &[],
479 );
480
481 rustfmt.args(["--bin", "rustfmt", "--"]);
482 rustfmt.args(builder.config.args());
483
484 rustfmt.into_cmd().run(builder);
485 }
486}