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