1use crate::core::build_steps::compile;
4use crate::core::build_steps::compile::{
5 add_to_sysroot, run_cargo, rustc_cargo, rustc_cargo_env, std_cargo, std_crates_for_run_make,
6};
7use crate::core::build_steps::tool::{COMPILETEST_ALLOW_FEATURES, SourceType, prepare_tool_cargo};
8use crate::core::builder::{
9 self, Alias, Builder, Kind, RunConfig, ShouldRun, Step, crate_description,
10};
11use crate::core::config::TargetSelection;
12use crate::utils::build_stamp::{self, BuildStamp};
13use crate::{Mode, Subcommand};
14
15#[derive(Debug, Clone, PartialEq, Eq, Hash)]
16pub struct Std {
17 pub target: TargetSelection,
18 crates: Vec<String>,
24 override_build_kind: Option<Kind>,
31}
32
33impl Std {
34 pub fn new(target: TargetSelection) -> Self {
35 Self { target, crates: vec![], override_build_kind: None }
36 }
37
38 pub fn build_kind(mut self, kind: Option<Kind>) -> Self {
39 self.override_build_kind = kind;
40 self
41 }
42}
43
44impl Step for Std {
45 type Output = ();
46 const DEFAULT: bool = true;
47
48 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
49 let stage = run.builder.top_stage;
50 run.crate_or_deps("sysroot")
51 .crate_or_deps("coretests")
52 .crate_or_deps("alloctests")
53 .path("library")
54 .default_condition(stage != 0)
55 }
56
57 fn make_run(run: RunConfig<'_>) {
58 let crates = std_crates_for_run_make(&run);
59 run.builder.ensure(Std { target: run.target, crates, override_build_kind: None });
60 }
61
62 fn run(self, builder: &Builder<'_>) {
63 builder.require_submodule("library/stdarch", None);
64
65 let target = self.target;
66 let compiler = builder.compiler(builder.top_stage, builder.config.build);
67
68 if builder.top_stage == 0 {
69 builder.ensure(compile::Std::new(compiler, target));
71 return;
72 }
73
74 let mut cargo = builder::Cargo::new(
75 builder,
76 compiler,
77 Mode::Std,
78 SourceType::InTree,
79 target,
80 self.override_build_kind.unwrap_or(builder.kind),
81 );
82
83 std_cargo(builder, target, compiler.stage, &mut cargo);
84 if matches!(builder.config.cmd, Subcommand::Fix) {
85 cargo.arg("--lib");
87 }
88
89 for krate in &*self.crates {
90 cargo.arg("-p").arg(krate);
91 }
92
93 let _guard = builder.msg_check(
94 format_args!("library artifacts{}", crate_description(&self.crates)),
95 target,
96 );
97
98 let stamp = build_stamp::libstd_stamp(builder, compiler, target).with_prefix("check");
99 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
100
101 if compiler.stage == 0 {
104 let libdir = builder.sysroot_target_libdir(compiler, target);
105 let hostdir = builder.sysroot_target_libdir(compiler, compiler.host);
106 add_to_sysroot(builder, &libdir, &hostdir, &stamp);
107 }
108 drop(_guard);
109
110 if builder.kind == Kind::Clippy || !self.crates.iter().any(|krate| krate == "test") {
113 return;
114 }
115
116 let mut cargo = builder::Cargo::new(
123 builder,
124 compiler,
125 Mode::Std,
126 SourceType::InTree,
127 target,
128 self.override_build_kind.unwrap_or(builder.kind),
129 );
130
131 if compiler.stage == 0 {
135 cargo.arg("--all-targets");
136 }
137
138 std_cargo(builder, target, compiler.stage, &mut cargo);
139
140 for krate in &*self.crates {
144 cargo.arg("-p").arg(krate);
145 }
146
147 let stamp = build_stamp::libstd_stamp(builder, compiler, target).with_prefix("check-test");
148 let _guard = builder.msg_check("library test/bench/example targets", target);
149 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
150 }
151}
152
153#[derive(Debug, Clone, PartialEq, Eq, Hash)]
154pub struct Rustc {
155 pub target: TargetSelection,
156 crates: Vec<String>,
162 override_build_kind: Option<Kind>,
169}
170
171impl Rustc {
172 pub fn new(target: TargetSelection, builder: &Builder<'_>) -> Self {
173 let crates = builder
174 .in_tree_crates("rustc-main", Some(target))
175 .into_iter()
176 .map(|krate| krate.name.to_string())
177 .collect();
178 Self { target, crates, override_build_kind: None }
179 }
180
181 pub fn build_kind(mut self, build_kind: Option<Kind>) -> Self {
182 self.override_build_kind = build_kind;
183 self
184 }
185}
186
187impl Step for Rustc {
188 type Output = ();
189 const ONLY_HOSTS: bool = true;
190 const DEFAULT: bool = true;
191
192 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
193 run.crate_or_deps("rustc-main").path("compiler")
194 }
195
196 fn make_run(run: RunConfig<'_>) {
197 let crates = run.make_run_crates(Alias::Compiler);
198 run.builder.ensure(Rustc { target: run.target, crates, override_build_kind: None });
199 }
200
201 fn run(self, builder: &Builder<'_>) {
207 let compiler = builder.compiler(builder.top_stage, builder.config.build);
208 let target = self.target;
209
210 if compiler.stage != 0 {
211 builder.ensure(crate::core::build_steps::compile::Std::new(compiler, compiler.host));
217 builder.ensure(crate::core::build_steps::compile::Std::new(compiler, target));
218 } else {
219 builder.ensure(Std::new(target).build_kind(self.override_build_kind));
220 }
221
222 let mut cargo = builder::Cargo::new(
223 builder,
224 compiler,
225 Mode::Rustc,
226 SourceType::InTree,
227 target,
228 self.override_build_kind.unwrap_or(builder.kind),
229 );
230
231 rustc_cargo(builder, &mut cargo, target, &compiler, &self.crates);
232
233 if builder.kind != Kind::Clippy {
236 cargo.arg("--all-targets");
237 }
238
239 for krate in &*self.crates {
243 cargo.arg("-p").arg(krate);
244 }
245
246 let _guard = builder.msg_check(
247 format_args!("compiler artifacts{}", crate_description(&self.crates)),
248 target,
249 );
250
251 let stamp = build_stamp::librustc_stamp(builder, compiler, target).with_prefix("check");
252
253 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
254
255 let libdir = builder.sysroot_target_libdir(compiler, target);
256 let hostdir = builder.sysroot_target_libdir(compiler, compiler.host);
257 add_to_sysroot(builder, &libdir, &hostdir, &stamp);
258 }
259}
260
261#[derive(Debug, Clone, PartialEq, Eq, Hash)]
262pub struct CodegenBackend {
263 pub target: TargetSelection,
264 pub backend: &'static str,
265}
266
267impl Step for CodegenBackend {
268 type Output = ();
269 const ONLY_HOSTS: bool = true;
270 const DEFAULT: bool = true;
271
272 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
273 run.paths(&["compiler/rustc_codegen_cranelift", "compiler/rustc_codegen_gcc"])
274 }
275
276 fn make_run(run: RunConfig<'_>) {
277 for &backend in &["cranelift", "gcc"] {
278 run.builder.ensure(CodegenBackend { target: run.target, backend });
279 }
280 }
281
282 fn run(self, builder: &Builder<'_>) {
283 if builder.build.config.vendor && self.backend == "gcc" {
285 println!("Skipping checking of `rustc_codegen_gcc` with vendoring enabled.");
286 return;
287 }
288
289 let compiler = builder.compiler(builder.top_stage, builder.config.build);
290 let target = self.target;
291 let backend = self.backend;
292
293 builder.ensure(Rustc::new(target, builder));
294
295 let mut cargo = builder::Cargo::new(
296 builder,
297 compiler,
298 Mode::Codegen,
299 SourceType::InTree,
300 target,
301 builder.kind,
302 );
303
304 cargo
305 .arg("--manifest-path")
306 .arg(builder.src.join(format!("compiler/rustc_codegen_{backend}/Cargo.toml")));
307 rustc_cargo_env(builder, &mut cargo, target, compiler.stage);
308
309 let _guard = builder.msg_check(backend, target);
310
311 let stamp = build_stamp::codegen_backend_stamp(builder, compiler, target, backend)
312 .with_prefix("check");
313
314 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
315 }
316}
317
318#[derive(Debug, Clone, PartialEq, Eq, Hash)]
319pub struct RustAnalyzer {
320 pub target: TargetSelection,
321}
322
323impl Step for RustAnalyzer {
324 type Output = ();
325 const ONLY_HOSTS: bool = true;
326 const DEFAULT: bool = true;
327
328 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
329 let builder = run.builder;
330 run.path("src/tools/rust-analyzer").default_condition(
331 builder
332 .config
333 .tools
334 .as_ref()
335 .is_none_or(|tools| tools.iter().any(|tool| tool == "rust-analyzer")),
336 )
337 }
338
339 fn make_run(run: RunConfig<'_>) {
340 run.builder.ensure(RustAnalyzer { target: run.target });
341 }
342
343 fn run(self, builder: &Builder<'_>) {
344 let compiler = builder.compiler(builder.top_stage, builder.config.build);
345 let target = self.target;
346
347 builder.ensure(Rustc::new(target, builder));
348
349 let mut cargo = prepare_tool_cargo(
350 builder,
351 compiler,
352 Mode::ToolRustc,
353 target,
354 builder.kind,
355 "src/tools/rust-analyzer",
356 SourceType::InTree,
357 &["in-rust-tree".to_owned()],
358 );
359
360 cargo.allow_features(crate::core::build_steps::tool::RustAnalyzer::ALLOW_FEATURES);
361
362 if builder.kind != Kind::Clippy {
365 cargo.arg("--bins");
367 cargo.arg("--tests");
368 cargo.arg("--benches");
369 }
370
371 let stamp = BuildStamp::new(&builder.cargo_out(compiler, Mode::ToolRustc, target))
374 .with_prefix("rust-analyzer-check");
375
376 let _guard = builder.msg_check("rust-analyzer artifacts", target);
377 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
378 }
379}
380
381#[derive(Debug, Clone, PartialEq, Eq, Hash)]
384pub struct Compiletest {
385 pub target: TargetSelection,
386}
387
388impl Step for Compiletest {
389 type Output = ();
390 const ONLY_HOSTS: bool = true;
391 const DEFAULT: bool = false;
392
393 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
394 run.path("src/tools/compiletest")
395 }
396
397 fn make_run(run: RunConfig<'_>) {
398 run.builder.ensure(Compiletest { target: run.target });
399 }
400
401 fn run(self, builder: &Builder<'_>) {
402 let mode = if builder.config.compiletest_use_stage0_libtest {
403 Mode::ToolBootstrap
404 } else {
405 Mode::ToolStd
406 };
407
408 let compiler = builder.compiler(
409 if mode == Mode::ToolBootstrap { 0 } else { builder.top_stage },
410 builder.config.build,
411 );
412
413 if mode != Mode::ToolBootstrap {
414 builder.ensure(Rustc::new(self.target, builder));
415 }
416
417 let mut cargo = prepare_tool_cargo(
418 builder,
419 compiler,
420 mode,
421 self.target,
422 builder.kind,
423 "src/tools/compiletest",
424 SourceType::InTree,
425 &[],
426 );
427
428 cargo.allow_features(COMPILETEST_ALLOW_FEATURES);
429
430 if builder.kind != Kind::Clippy {
433 cargo.arg("--all-targets");
434 }
435
436 let stamp = BuildStamp::new(&builder.cargo_out(compiler, mode, self.target))
437 .with_prefix("compiletest-check");
438
439 let _guard = builder.msg_check("compiletest artifacts", self.target);
440 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
441 }
442}
443
444macro_rules! tool_check_step {
445 (
446 $name:ident {
447 path: $path:literal
449 $(, alt_path: $alt_path:literal )*
450 $(, default: $default:literal )?
451 $( , )?
452 }
453 ) => {
454 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
455 pub struct $name {
456 pub target: TargetSelection,
457 }
458
459 impl Step for $name {
460 type Output = ();
461 const ONLY_HOSTS: bool = true;
462 const DEFAULT: bool = true $( && $default )?;
464
465 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
466 run.paths(&[ $path, $( $alt_path ),* ])
467 }
468
469 fn make_run(run: RunConfig<'_>) {
470 run.builder.ensure($name { target: run.target });
471 }
472
473 fn run(self, builder: &Builder<'_>) {
474 let Self { target } = self;
475 run_tool_check_step(builder, target, stringify!($name), $path);
476 }
477 }
478 }
479}
480
481fn run_tool_check_step(
483 builder: &Builder<'_>,
484 target: TargetSelection,
485 step_type_name: &str,
486 path: &str,
487) {
488 let display_name = path.rsplit('/').next().unwrap();
489 let compiler = builder.compiler(builder.top_stage, builder.config.build);
490
491 builder.ensure(Rustc::new(target, builder));
492
493 let mut cargo = prepare_tool_cargo(
494 builder,
495 compiler,
496 Mode::ToolRustc,
497 target,
498 builder.kind,
499 path,
500 SourceType::InTree,
505 &[],
506 );
507
508 if builder.kind != Kind::Clippy {
511 cargo.arg("--all-targets");
512 }
513
514 let stamp = BuildStamp::new(&builder.cargo_out(compiler, Mode::ToolRustc, target))
515 .with_prefix(&format!("{}-check", step_type_name.to_lowercase()));
516
517 let _guard = builder.msg_check(format!("{display_name} artifacts"), target);
518 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
519}
520
521tool_check_step!(Rustdoc { path: "src/tools/rustdoc", alt_path: "src/librustdoc" });
522tool_check_step!(Clippy { path: "src/tools/clippy" });
527tool_check_step!(Miri { path: "src/tools/miri" });
528tool_check_step!(CargoMiri { path: "src/tools/miri/cargo-miri" });
529tool_check_step!(Rustfmt { path: "src/tools/rustfmt" });
530tool_check_step!(MiroptTestTools { path: "src/tools/miropt-test-tools" });
531tool_check_step!(TestFloatParse { path: "src/etc/test-float-parse" });
532tool_check_step!(FeaturesStatusDump { path: "src/tools/features-status-dump" });
533
534tool_check_step!(Bootstrap { path: "src/bootstrap", default: false });
535
536tool_check_step!(RunMakeSupport { path: "src/tools/run-make-support", default: false });
539
540#[derive(Debug, Clone, PartialEq, Eq, Hash)]
550pub(crate) struct CoverageDump;
551
552impl CoverageDump {
553 const PATH: &str = "src/tools/coverage-dump";
554}
555
556impl Step for CoverageDump {
557 type Output = ();
558
559 const DEFAULT: bool = false;
562 const ONLY_HOSTS: bool = true;
563
564 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
565 run.path(Self::PATH)
566 }
567
568 fn make_run(run: RunConfig<'_>) {
569 run.builder.ensure(Self {});
570 }
571
572 fn run(self, builder: &Builder<'_>) -> Self::Output {
573 let Self {} = self;
575 let display_name = "coverage-dump";
576 let host = builder.config.build;
577 let target = host;
578 let mode = Mode::ToolBootstrap;
579
580 let compiler = builder.compiler(0, host);
581 let cargo = prepare_tool_cargo(
582 builder,
583 compiler,
584 mode,
585 target,
586 builder.kind,
587 Self::PATH,
588 SourceType::InTree,
589 &[],
590 );
591
592 let stamp = BuildStamp::new(&builder.cargo_out(compiler, mode, target))
593 .with_prefix(&format!("{display_name}-check"));
594
595 let _guard = builder.msg_tool(
596 builder.kind,
597 mode,
598 display_name,
599 compiler.stage,
600 &compiler.host,
601 &target,
602 );
603 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
604 }
605}