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