bootstrap/core/build_steps/
run.rs1use std::path::PathBuf;
7
8use crate::core::build_steps::dist::distdir;
9use crate::core::build_steps::test;
10use crate::core::build_steps::tool::{self, SourceType, Tool};
11use crate::core::build_steps::vendor::{Vendor, default_paths_to_vendor};
12use crate::core::builder::{Builder, Kind, RunConfig, ShouldRun, Step};
13use crate::core::config::TargetSelection;
14use crate::core::config::flags::get_completion;
15use crate::utils::exec::command;
16use crate::{Mode, t};
17
18#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
19pub struct BuildManifest;
20
21impl Step for BuildManifest {
22 type Output = ();
23 const ONLY_HOSTS: bool = true;
24
25 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
26 run.path("src/tools/build-manifest")
27 }
28
29 fn make_run(run: RunConfig<'_>) {
30 run.builder.ensure(BuildManifest);
31 }
32
33 fn run(self, builder: &Builder<'_>) {
34 let mut cmd = builder.tool_cmd(Tool::BuildManifest);
37 let sign = builder.config.dist_sign_folder.as_ref().unwrap_or_else(|| {
38 panic!("\n\nfailed to specify `dist.sign-folder` in `bootstrap.toml`\n\n")
39 });
40 let addr = builder.config.dist_upload_addr.as_ref().unwrap_or_else(|| {
41 panic!("\n\nfailed to specify `dist.upload-addr` in `bootstrap.toml`\n\n")
42 });
43
44 let today = command("date").arg("+%Y-%m-%d").run_capture_stdout(builder).stdout();
45
46 cmd.arg(sign);
47 cmd.arg(distdir(builder));
48 cmd.arg(today.trim());
49 cmd.arg(addr);
50 cmd.arg(&builder.config.channel);
51
52 builder.create_dir(&distdir(builder));
53 cmd.run(builder);
54 }
55}
56
57#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
58pub struct BumpStage0;
59
60impl Step for BumpStage0 {
61 type Output = ();
62 const ONLY_HOSTS: bool = true;
63
64 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
65 run.path("src/tools/bump-stage0")
66 }
67
68 fn make_run(run: RunConfig<'_>) {
69 run.builder.ensure(BumpStage0);
70 }
71
72 fn run(self, builder: &Builder<'_>) -> Self::Output {
73 let mut cmd = builder.tool_cmd(Tool::BumpStage0);
74 cmd.args(builder.config.args());
75 cmd.run(builder);
76 }
77}
78
79#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
80pub struct ReplaceVersionPlaceholder;
81
82impl Step for ReplaceVersionPlaceholder {
83 type Output = ();
84 const ONLY_HOSTS: bool = true;
85
86 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
87 run.path("src/tools/replace-version-placeholder")
88 }
89
90 fn make_run(run: RunConfig<'_>) {
91 run.builder.ensure(ReplaceVersionPlaceholder);
92 }
93
94 fn run(self, builder: &Builder<'_>) -> Self::Output {
95 let mut cmd = builder.tool_cmd(Tool::ReplaceVersionPlaceholder);
96 cmd.arg(&builder.src);
97 cmd.run(builder);
98 }
99}
100
101#[derive(Debug, Clone, PartialEq, Eq, Hash)]
102pub struct Miri {
103 target: TargetSelection,
104}
105
106impl Step for Miri {
107 type Output = ();
108 const ONLY_HOSTS: bool = false;
109
110 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
111 run.path("src/tools/miri")
112 }
113
114 fn make_run(run: RunConfig<'_>) {
115 run.builder.ensure(Miri { target: run.target });
116 }
117
118 fn run(self, builder: &Builder<'_>) {
119 let host = builder.build.build;
120 let target = self.target;
121
122 let stage = if builder.config.is_explicit_stage() || builder.top_stage >= 1 {
125 builder.top_stage
126 } else {
127 1
128 };
129
130 if stage == 0 {
131 eprintln!("miri cannot be run at stage 0");
132 std::process::exit(1);
133 }
134
135 let target_compiler = builder.compiler(stage, target);
137 let miri_build = builder.ensure(tool::Miri { compiler: target_compiler, target });
138 let host_compiler = miri_build.build_compiler;
140
141 let miri_sysroot = test::Miri::build_miri_sysroot(builder, target_compiler, target);
143
144 let mut miri = tool::prepare_tool_cargo(
148 builder,
149 host_compiler,
150 Mode::ToolRustc,
151 host,
152 Kind::Run,
153 "src/tools/miri",
154 SourceType::InTree,
155 &[],
156 );
157 miri.add_rustc_lib_path(builder);
158 miri.arg("--").arg("--target").arg(target.rustc_target_arg());
159
160 miri.arg("--sysroot").arg(miri_sysroot);
162
163 miri.args(builder.config.args());
166
167 miri.into_cmd().run(builder);
168 }
169}
170
171#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
172pub struct CollectLicenseMetadata;
173
174impl Step for CollectLicenseMetadata {
175 type Output = PathBuf;
176 const ONLY_HOSTS: bool = true;
177
178 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
179 run.path("src/tools/collect-license-metadata")
180 }
181
182 fn make_run(run: RunConfig<'_>) {
183 run.builder.ensure(CollectLicenseMetadata);
184 }
185
186 fn run(self, builder: &Builder<'_>) -> Self::Output {
187 let Some(reuse) = &builder.config.reuse else {
188 panic!("REUSE is required to collect the license metadata");
189 };
190
191 let dest = builder.src.join("license-metadata.json");
192
193 let mut cmd = builder.tool_cmd(Tool::CollectLicenseMetadata);
194 cmd.env("REUSE_EXE", reuse);
195 cmd.env("DEST", &dest);
196 cmd.run(builder);
197
198 dest
199 }
200}
201
202#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
203pub struct GenerateCopyright;
204
205impl Step for GenerateCopyright {
206 type Output = Vec<PathBuf>;
207 const ONLY_HOSTS: bool = true;
208
209 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
210 run.path("src/tools/generate-copyright")
211 }
212
213 fn make_run(run: RunConfig<'_>) {
214 run.builder.ensure(GenerateCopyright);
215 }
216
217 fn run(self, builder: &Builder<'_>) -> Self::Output {
218 let license_metadata = builder.src.join("license-metadata.json");
219 let dest = builder.out.join("COPYRIGHT.html");
220 let dest_libstd = builder.out.join("COPYRIGHT-library.html");
221
222 let paths_to_vendor = default_paths_to_vendor(builder);
223 for (_, submodules) in &paths_to_vendor {
224 for submodule in submodules {
225 builder.build.require_submodule(submodule, None);
226 }
227 }
228 let cargo_manifests = paths_to_vendor
229 .into_iter()
230 .map(|(path, _submodules)| path.to_str().unwrap().to_string())
231 .inspect(|path| assert!(!path.contains(','), "{path} contains a comma in its name"))
232 .collect::<Vec<_>>()
233 .join(",");
234
235 let vendored_sources = if let Some(path) = builder.vendored_crates_path() {
236 path
237 } else {
238 let cache_dir = builder.out.join("tmp").join("generate-copyright-vendor");
239 builder.ensure(Vendor {
240 sync_args: Vec::new(),
241 versioned_dirs: true,
242 root_dir: builder.src.clone(),
243 output_dir: cache_dir.clone(),
244 });
245 cache_dir
246 };
247
248 let mut cmd = builder.tool_cmd(Tool::GenerateCopyright);
249 cmd.env("CARGO_MANIFESTS", &cargo_manifests);
250 cmd.env("LICENSE_METADATA", &license_metadata);
251 cmd.env("DEST", &dest);
252 cmd.env("DEST_LIBSTD", &dest_libstd);
253 cmd.env("SRC_DIR", &builder.src);
254 cmd.env("VENDOR_DIR", &vendored_sources);
255 cmd.env("CARGO", &builder.initial_cargo);
256 cmd.env("CARGO_HOME", t!(home::cargo_home()));
257 cmd.current_dir(&builder.src);
260 cmd.run(builder);
261
262 vec![dest, dest_libstd]
263 }
264}
265
266#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
267pub struct GenerateWindowsSys;
268
269impl Step for GenerateWindowsSys {
270 type Output = ();
271 const ONLY_HOSTS: bool = true;
272
273 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
274 run.path("src/tools/generate-windows-sys")
275 }
276
277 fn make_run(run: RunConfig<'_>) {
278 run.builder.ensure(GenerateWindowsSys);
279 }
280
281 fn run(self, builder: &Builder<'_>) {
282 let mut cmd = builder.tool_cmd(Tool::GenerateWindowsSys);
283 cmd.arg(&builder.src);
284 cmd.run(builder);
285 }
286}
287
288#[derive(Debug, Clone, PartialEq, Eq, Hash)]
289pub struct GenerateCompletions;
290
291macro_rules! generate_completions {
292 ( $( ( $shell:ident, $filename:expr ) ),* ) => {
293 $(
294 if let Some(comp) = get_completion($shell, &$filename) {
295 std::fs::write(&$filename, comp).expect(&format!("writing {} completion", stringify!($shell)));
296 }
297 )*
298 };
299}
300
301impl Step for GenerateCompletions {
302 type Output = ();
303
304 fn run(self, builder: &Builder<'_>) {
306 use clap_complete::shells::{Bash, Fish, PowerShell, Zsh};
307
308 generate_completions!(
309 (Bash, builder.src.join("src/etc/completions/x.py.sh")),
310 (Zsh, builder.src.join("src/etc/completions/x.py.zsh")),
311 (Fish, builder.src.join("src/etc/completions/x.py.fish")),
312 (PowerShell, builder.src.join("src/etc/completions/x.py.ps1")),
313 (Bash, builder.src.join("src/etc/completions/x.sh")),
314 (Zsh, builder.src.join("src/etc/completions/x.zsh")),
315 (Fish, builder.src.join("src/etc/completions/x.fish")),
316 (PowerShell, builder.src.join("src/etc/completions/x.ps1"))
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 ONLY_HOSTS: 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 ONLY_HOSTS: 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 ONLY_HOSTS: 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 ONLY_HOSTS: 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.build;
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 compiler = builder.compiler(stage, host);
468 let rustfmt_build = builder.ensure(tool::Rustfmt { compiler, target: host });
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}