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