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, 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 ONLY_HOSTS: 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 ONLY_HOSTS: 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 ONLY_HOSTS: 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 const ONLY_HOSTS: bool = false;
111
112 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
113 run.path("src/tools/miri")
114 }
115
116 fn make_run(run: RunConfig<'_>) {
117 run.builder.ensure(Miri { target: run.target });
118 }
119
120 fn run(self, builder: &Builder<'_>) {
121 let host = builder.build.host_target;
122 let target = self.target;
123
124 let stage = if builder.config.is_explicit_stage() || builder.top_stage >= 1 {
127 builder.top_stage
128 } else {
129 1
130 };
131
132 if stage == 0 {
133 eprintln!("miri cannot be run at stage 0");
134 std::process::exit(1);
135 }
136
137 let target_compiler = builder.compiler(stage, target);
139 let miri_build = builder.ensure(tool::Miri { compiler: target_compiler, target });
140 let host_compiler = miri_build.build_compiler;
142
143 let miri_sysroot = test::Miri::build_miri_sysroot(builder, target_compiler, target);
145
146 let mut miri = tool::prepare_tool_cargo(
150 builder,
151 host_compiler,
152 Mode::ToolRustc,
153 host,
154 Kind::Run,
155 "src/tools/miri",
156 SourceType::InTree,
157 &[],
158 );
159 miri.add_rustc_lib_path(builder);
160 miri.arg("--").arg("--target").arg(target.rustc_target_arg());
161
162 miri.arg("--sysroot").arg(miri_sysroot);
164
165 miri.args(builder.config.args());
168
169 miri.into_cmd().run(builder);
170 }
171}
172
173#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
174pub struct CollectLicenseMetadata;
175
176impl Step for CollectLicenseMetadata {
177 type Output = PathBuf;
178 const ONLY_HOSTS: bool = true;
179
180 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
181 run.path("src/tools/collect-license-metadata")
182 }
183
184 fn make_run(run: RunConfig<'_>) {
185 run.builder.ensure(CollectLicenseMetadata);
186 }
187
188 fn run(self, builder: &Builder<'_>) -> Self::Output {
189 let Some(reuse) = &builder.config.reuse else {
190 panic!("REUSE is required to collect the license metadata");
191 };
192
193 let dest = builder.src.join("license-metadata.json");
194
195 let mut cmd = builder.tool_cmd(Tool::CollectLicenseMetadata);
196 cmd.env("REUSE_EXE", reuse);
197 cmd.env("DEST", &dest);
198 cmd.run(builder);
199
200 dest
201 }
202}
203
204#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
205pub struct GenerateCopyright;
206
207impl Step for GenerateCopyright {
208 type Output = Vec<PathBuf>;
209 const ONLY_HOSTS: bool = true;
210
211 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
212 run.path("src/tools/generate-copyright")
213 }
214
215 fn make_run(run: RunConfig<'_>) {
216 run.builder.ensure(GenerateCopyright);
217 }
218
219 fn run(self, builder: &Builder<'_>) -> Self::Output {
220 let license_metadata = builder.src.join("license-metadata.json");
221 let dest = builder.out.join("COPYRIGHT.html");
222 let dest_libstd = builder.out.join("COPYRIGHT-library.html");
223
224 let paths_to_vendor = default_paths_to_vendor(builder);
225 for (_, submodules) in &paths_to_vendor {
226 for submodule in submodules {
227 builder.build.require_submodule(submodule, None);
228 }
229 }
230 let cargo_manifests = paths_to_vendor
231 .into_iter()
232 .map(|(path, _submodules)| path.to_str().unwrap().to_string())
233 .inspect(|path| assert!(!path.contains(','), "{path} contains a comma in its name"))
234 .collect::<Vec<_>>()
235 .join(",");
236
237 let vendored_sources = if let Some(path) = builder.vendored_crates_path() {
238 path
239 } else {
240 let cache_dir = builder.out.join("tmp").join("generate-copyright-vendor");
241 builder.ensure(Vendor {
242 sync_args: Vec::new(),
243 versioned_dirs: true,
244 root_dir: builder.src.clone(),
245 output_dir: cache_dir.clone(),
246 });
247 cache_dir
248 };
249
250 let mut cmd = builder.tool_cmd(Tool::GenerateCopyright);
251 cmd.env("CARGO_MANIFESTS", &cargo_manifests);
252 cmd.env("LICENSE_METADATA", &license_metadata);
253 cmd.env("DEST", &dest);
254 cmd.env("DEST_LIBSTD", &dest_libstd);
255 cmd.env("SRC_DIR", &builder.src);
256 cmd.env("VENDOR_DIR", &vendored_sources);
257 cmd.env("CARGO", &builder.initial_cargo);
258 cmd.env("CARGO_HOME", t!(home::cargo_home()));
259 cmd.current_dir(&builder.src);
262 cmd.run(builder);
263
264 vec![dest, dest_libstd]
265 }
266}
267
268#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
269pub struct GenerateWindowsSys;
270
271impl Step for GenerateWindowsSys {
272 type Output = ();
273 const ONLY_HOSTS: bool = true;
274
275 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
276 run.path("src/tools/generate-windows-sys")
277 }
278
279 fn make_run(run: RunConfig<'_>) {
280 run.builder.ensure(GenerateWindowsSys);
281 }
282
283 fn run(self, builder: &Builder<'_>) {
284 let mut cmd = builder.tool_cmd(Tool::GenerateWindowsSys);
285 cmd.arg(&builder.src);
286 cmd.run(builder);
287 }
288}
289
290pub fn get_completion_paths(builder: &Builder<'_>) -> Vec<(&'static dyn Generator, PathBuf)> {
292 vec![
293 (&shells::Bash as &'static dyn Generator, builder.src.join("src/etc/completions/x.py.sh")),
294 (&shells::Zsh, builder.src.join("src/etc/completions/x.py.zsh")),
295 (&shells::Fish, builder.src.join("src/etc/completions/x.py.fish")),
296 (&shells::PowerShell, builder.src.join("src/etc/completions/x.py.ps1")),
297 (&shells::Bash, builder.src.join("src/etc/completions/x.sh")),
298 (&shells::Zsh, builder.src.join("src/etc/completions/x.zsh")),
299 (&shells::Fish, builder.src.join("src/etc/completions/x.fish")),
300 (&shells::PowerShell, builder.src.join("src/etc/completions/x.ps1")),
301 ]
302}
303
304#[derive(Debug, Clone, PartialEq, Eq, Hash)]
305pub struct GenerateCompletions;
306
307impl Step for GenerateCompletions {
308 type Output = ();
309
310 fn run(self, builder: &Builder<'_>) {
312 for (shell, path) in get_completion_paths(builder) {
313 if let Some(comp) = get_completion(shell, &path) {
314 std::fs::write(&path, comp).unwrap_or_else(|e| {
315 panic!("writing completion into {} failed: {e:?}", path.display())
316 });
317 }
318 }
319 }
320
321 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
322 run.alias("generate-completions")
323 }
324
325 fn make_run(run: RunConfig<'_>) {
326 run.builder.ensure(GenerateCompletions);
327 }
328}
329
330#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
331pub struct UnicodeTableGenerator;
332
333impl Step for UnicodeTableGenerator {
334 type Output = ();
335 const ONLY_HOSTS: bool = true;
336
337 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
338 run.path("src/tools/unicode-table-generator")
339 }
340
341 fn make_run(run: RunConfig<'_>) {
342 run.builder.ensure(UnicodeTableGenerator);
343 }
344
345 fn run(self, builder: &Builder<'_>) {
346 let mut cmd = builder.tool_cmd(Tool::UnicodeTableGenerator);
347 cmd.arg(builder.src.join("library/core/src/unicode/unicode_data.rs"));
348 cmd.run(builder);
349 }
350}
351
352#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
353pub struct FeaturesStatusDump;
354
355impl Step for FeaturesStatusDump {
356 type Output = ();
357 const ONLY_HOSTS: bool = true;
358
359 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
360 run.path("src/tools/features-status-dump")
361 }
362
363 fn make_run(run: RunConfig<'_>) {
364 run.builder.ensure(FeaturesStatusDump);
365 }
366
367 fn run(self, builder: &Builder<'_>) {
368 let mut cmd = builder.tool_cmd(Tool::FeaturesStatusDump);
369
370 cmd.arg("--library-path");
371 cmd.arg(builder.src.join("library"));
372
373 cmd.arg("--compiler-path");
374 cmd.arg(builder.src.join("compiler"));
375
376 cmd.arg("--output-path");
377 cmd.arg(builder.out.join("features-status-dump.json"));
378
379 cmd.run(builder);
380 }
381}
382
383#[derive(Clone, Debug, PartialEq, Eq, Hash)]
386pub struct CyclicStep {
387 n: u32,
388}
389
390impl Step for CyclicStep {
391 type Output = ();
392
393 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
394 run.alias("cyclic-step")
395 }
396
397 fn make_run(run: RunConfig<'_>) {
398 run.builder.ensure(CyclicStep { n: 2 })
400 }
401
402 fn run(self, builder: &Builder<'_>) -> Self::Output {
403 builder.ensure(CyclicStep { n: self.n.saturating_sub(1) })
405 }
406}
407
408#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
413pub struct CoverageDump;
414
415impl Step for CoverageDump {
416 type Output = ();
417
418 const DEFAULT: bool = false;
419 const ONLY_HOSTS: bool = true;
420
421 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
422 run.path("src/tools/coverage-dump")
423 }
424
425 fn make_run(run: RunConfig<'_>) {
426 run.builder.ensure(Self {});
427 }
428
429 fn run(self, builder: &Builder<'_>) {
430 let mut cmd = builder.tool_cmd(Tool::CoverageDump);
431 cmd.args(&builder.config.free_args);
432 cmd.run(builder);
433 }
434}
435
436#[derive(Debug, Clone, PartialEq, Eq, Hash)]
437pub struct Rustfmt;
438
439impl Step for Rustfmt {
440 type Output = ();
441 const ONLY_HOSTS: bool = true;
442
443 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
444 run.path("src/tools/rustfmt")
445 }
446
447 fn make_run(run: RunConfig<'_>) {
448 run.builder.ensure(Rustfmt);
449 }
450
451 fn run(self, builder: &Builder<'_>) {
452 let host = builder.build.host_target;
453
454 let stage = if builder.config.is_explicit_stage() || builder.top_stage >= 1 {
457 builder.top_stage
458 } else {
459 1
460 };
461
462 if stage == 0 {
463 eprintln!("rustfmt cannot be run at stage 0");
464 eprintln!("HELP: Use `x fmt` to use stage 0 rustfmt.");
465 std::process::exit(1);
466 }
467
468 let compiler = builder.compiler(stage, host);
469 let rustfmt_build = builder.ensure(tool::Rustfmt { compiler, target: host });
470
471 let mut rustfmt = tool::prepare_tool_cargo(
472 builder,
473 rustfmt_build.build_compiler,
474 Mode::ToolRustc,
475 host,
476 Kind::Run,
477 "src/tools/rustfmt",
478 SourceType::InTree,
479 &[],
480 );
481
482 rustfmt.args(["--bin", "rustfmt", "--"]);
483 rustfmt.args(builder.config.args());
484
485 rustfmt.into_cmd().run(builder);
486 }
487}