bootstrap/core/build_steps/
run.rs
1use std::path::PathBuf;
7
8use crate::Mode;
9use crate::core::build_steps::dist::distdir;
10use crate::core::build_steps::test;
11use crate::core::build_steps::tool::{self, SourceType, Tool};
12use crate::core::build_steps::vendor::{Vendor, default_paths_to_vendor};
13use crate::core::builder::{Builder, Kind, RunConfig, ShouldRun, Step};
14use crate::core::config::TargetSelection;
15use crate::core::config::flags::get_completion;
16use crate::utils::exec::command;
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 let stage = builder.top_stage;
122 if stage == 0 {
123 eprintln!("miri cannot be run at stage 0");
124 std::process::exit(1);
125 }
126
127 let target_compiler = builder.compiler(stage, host);
129 let host_compiler = tool::get_tool_rustc_compiler(builder, target_compiler);
130
131 let miri_sysroot = test::Miri::build_miri_sysroot(builder, target_compiler, target);
133
134 let mut miri = tool::prepare_tool_cargo(
138 builder,
139 host_compiler,
140 Mode::ToolRustc,
141 host,
142 Kind::Run,
143 "src/tools/miri",
144 SourceType::InTree,
145 &[],
146 );
147 miri.add_rustc_lib_path(builder);
148 miri.arg("--").arg("--target").arg(target.rustc_target_arg());
149
150 miri.arg("--sysroot").arg(miri_sysroot);
152
153 miri.args(builder.config.args());
156
157 miri.into_cmd().run(builder);
158 }
159}
160
161#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
162pub struct CollectLicenseMetadata;
163
164impl Step for CollectLicenseMetadata {
165 type Output = PathBuf;
166 const ONLY_HOSTS: bool = true;
167
168 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
169 run.path("src/tools/collect-license-metadata")
170 }
171
172 fn make_run(run: RunConfig<'_>) {
173 run.builder.ensure(CollectLicenseMetadata);
174 }
175
176 fn run(self, builder: &Builder<'_>) -> Self::Output {
177 let Some(reuse) = &builder.config.reuse else {
178 panic!("REUSE is required to collect the license metadata");
179 };
180
181 let dest = builder.src.join("license-metadata.json");
182
183 let mut cmd = builder.tool_cmd(Tool::CollectLicenseMetadata);
184 cmd.env("REUSE_EXE", reuse);
185 cmd.env("DEST", &dest);
186 cmd.run(builder);
187
188 dest
189 }
190}
191
192#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
193pub struct GenerateCopyright;
194
195impl Step for GenerateCopyright {
196 type Output = Vec<PathBuf>;
197 const ONLY_HOSTS: bool = true;
198
199 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
200 run.path("src/tools/generate-copyright")
201 }
202
203 fn make_run(run: RunConfig<'_>) {
204 run.builder.ensure(GenerateCopyright);
205 }
206
207 fn run(self, builder: &Builder<'_>) -> Self::Output {
208 let license_metadata = builder.src.join("license-metadata.json");
209 let dest = builder.out.join("COPYRIGHT.html");
210 let dest_libstd = builder.out.join("COPYRIGHT-library.html");
211
212 let paths_to_vendor = default_paths_to_vendor(builder);
213 for (_, submodules) in &paths_to_vendor {
214 for submodule in submodules {
215 builder.build.require_submodule(submodule, None);
216 }
217 }
218 let cargo_manifests = paths_to_vendor
219 .into_iter()
220 .map(|(path, _submodules)| path.to_str().unwrap().to_string())
221 .inspect(|path| assert!(!path.contains(','), "{path} contains a comma in its name"))
222 .collect::<Vec<_>>()
223 .join(",");
224
225 let vendored_sources = if let Some(path) = builder.vendored_crates_path() {
226 path
227 } else {
228 let cache_dir = builder.out.join("tmp").join("generate-copyright-vendor");
229 builder.ensure(Vendor {
230 sync_args: Vec::new(),
231 versioned_dirs: true,
232 root_dir: builder.src.clone(),
233 output_dir: cache_dir.clone(),
234 });
235 cache_dir
236 };
237
238 let mut cmd = builder.tool_cmd(Tool::GenerateCopyright);
239 cmd.env("CARGO_MANIFESTS", &cargo_manifests);
240 cmd.env("LICENSE_METADATA", &license_metadata);
241 cmd.env("DEST", &dest);
242 cmd.env("DEST_LIBSTD", &dest_libstd);
243 cmd.env("SRC_DIR", &builder.src);
244 cmd.env("VENDOR_DIR", &vendored_sources);
245 cmd.env("CARGO", &builder.initial_cargo);
246 cmd.current_dir(&builder.src);
249 cmd.run(builder);
250
251 vec![dest, dest_libstd]
252 }
253}
254
255#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
256pub struct GenerateWindowsSys;
257
258impl Step for GenerateWindowsSys {
259 type Output = ();
260 const ONLY_HOSTS: bool = true;
261
262 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
263 run.path("src/tools/generate-windows-sys")
264 }
265
266 fn make_run(run: RunConfig<'_>) {
267 run.builder.ensure(GenerateWindowsSys);
268 }
269
270 fn run(self, builder: &Builder<'_>) {
271 let mut cmd = builder.tool_cmd(Tool::GenerateWindowsSys);
272 cmd.arg(&builder.src);
273 cmd.run(builder);
274 }
275}
276
277#[derive(Debug, Clone, PartialEq, Eq, Hash)]
278pub struct GenerateCompletions;
279
280macro_rules! generate_completions {
281 ( $( ( $shell:ident, $filename:expr ) ),* ) => {
282 $(
283 if let Some(comp) = get_completion($shell, &$filename) {
284 std::fs::write(&$filename, comp).expect(&format!("writing {} completion", stringify!($shell)));
285 }
286 )*
287 };
288}
289
290impl Step for GenerateCompletions {
291 type Output = ();
292
293 fn run(self, builder: &Builder<'_>) {
295 use clap_complete::shells::{Bash, Fish, PowerShell, Zsh};
296
297 generate_completions!(
298 (Bash, builder.src.join("src/etc/completions/x.py.sh")),
299 (Zsh, builder.src.join("src/etc/completions/x.py.zsh")),
300 (Fish, builder.src.join("src/etc/completions/x.py.fish")),
301 (PowerShell, builder.src.join("src/etc/completions/x.py.ps1")),
302 (Bash, builder.src.join("src/etc/completions/x.sh")),
303 (Zsh, builder.src.join("src/etc/completions/x.zsh")),
304 (Fish, builder.src.join("src/etc/completions/x.fish")),
305 (PowerShell, builder.src.join("src/etc/completions/x.ps1"))
306 );
307 }
308
309 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
310 run.alias("generate-completions")
311 }
312
313 fn make_run(run: RunConfig<'_>) {
314 run.builder.ensure(GenerateCompletions);
315 }
316}
317
318#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
319pub struct UnicodeTableGenerator;
320
321impl Step for UnicodeTableGenerator {
322 type Output = ();
323 const ONLY_HOSTS: bool = true;
324
325 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
326 run.path("src/tools/unicode-table-generator")
327 }
328
329 fn make_run(run: RunConfig<'_>) {
330 run.builder.ensure(UnicodeTableGenerator);
331 }
332
333 fn run(self, builder: &Builder<'_>) {
334 let mut cmd = builder.tool_cmd(Tool::UnicodeTableGenerator);
335 cmd.arg(builder.src.join("library/core/src/unicode/unicode_data.rs"));
336 cmd.run(builder);
337 }
338}
339
340#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
341pub struct FeaturesStatusDump;
342
343impl Step for FeaturesStatusDump {
344 type Output = ();
345 const ONLY_HOSTS: bool = true;
346
347 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
348 run.path("src/tools/features-status-dump")
349 }
350
351 fn make_run(run: RunConfig<'_>) {
352 run.builder.ensure(FeaturesStatusDump);
353 }
354
355 fn run(self, builder: &Builder<'_>) {
356 let mut cmd = builder.tool_cmd(Tool::FeaturesStatusDump);
357
358 cmd.arg("--library-path");
359 cmd.arg(builder.src.join("library"));
360
361 cmd.arg("--compiler-path");
362 cmd.arg(builder.src.join("compiler"));
363
364 cmd.arg("--output-path");
365 cmd.arg(builder.out.join("features-status-dump.json"));
366
367 cmd.run(builder);
368 }
369}
370
371#[derive(Clone, Debug, PartialEq, Eq, Hash)]
374pub struct CyclicStep {
375 n: u32,
376}
377
378impl Step for CyclicStep {
379 type Output = ();
380
381 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
382 run.alias("cyclic-step")
383 }
384
385 fn make_run(run: RunConfig<'_>) {
386 run.builder.ensure(CyclicStep { n: 2 })
388 }
389
390 fn run(self, builder: &Builder<'_>) -> Self::Output {
391 builder.ensure(CyclicStep { n: self.n.saturating_sub(1) })
393 }
394}