1use crate::core::build_steps::compile::{
4 add_to_sysroot, run_cargo, rustc_cargo, rustc_cargo_env, std_cargo, std_crates_for_run_make,
5};
6use crate::core::build_steps::tool;
7use crate::core::build_steps::tool::{
8 COMPILETEST_ALLOW_FEATURES, SourceType, ToolTargetBuildMode, get_tool_target_compiler,
9 prepare_tool_cargo,
10};
11use crate::core::builder::{
12 self, Alias, Builder, Kind, RunConfig, ShouldRun, Step, StepMetadata, crate_description,
13};
14use crate::core::config::TargetSelection;
15use crate::utils::build_stamp::{self, BuildStamp};
16use crate::{CodegenBackendKind, Compiler, Mode, Subcommand};
17
18#[derive(Debug, Clone, PartialEq, Eq, Hash)]
19pub struct Std {
20 pub build_compiler: Compiler,
22 pub target: TargetSelection,
23 crates: Vec<String>,
29}
30
31impl Std {
32 const CRATE_OR_DEPS: &[&str] = &["sysroot", "coretests", "alloctests"];
33
34 pub fn new(build_compiler: Compiler, target: TargetSelection) -> Self {
35 Self { build_compiler, target, crates: vec![] }
36 }
37}
38
39impl Step for Std {
40 type Output = ();
41 const DEFAULT: bool = true;
42
43 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
44 let mut run = run;
45 for c in Std::CRATE_OR_DEPS {
46 run = run.crate_or_deps(c);
47 }
48
49 run.path("library")
50 }
51
52 fn make_run(run: RunConfig<'_>) {
53 if !run.builder.download_rustc() && run.builder.config.skip_std_check_if_no_download_rustc {
54 eprintln!(
55 "WARNING: `--skip-std-check-if-no-download-rustc` flag was passed and `rust.download-rustc` is not available. Skipping."
56 );
57 return;
58 }
59
60 if run.builder.config.compile_time_deps {
61 return;
63 }
64
65 let crates = std_crates_for_run_make(&run);
66 run.builder.ensure(Std {
67 build_compiler: prepare_compiler_for_check(run.builder, run.target, Mode::Std),
68 target: run.target,
69 crates,
70 });
71 }
72
73 fn run(self, builder: &Builder<'_>) {
74 let build_compiler = self.build_compiler;
75 let stage = build_compiler.stage;
76 let target = self.target;
77
78 let mut cargo = builder::Cargo::new(
79 builder,
80 build_compiler,
81 Mode::Std,
82 SourceType::InTree,
83 target,
84 Kind::Check,
85 );
86
87 std_cargo(builder, target, stage, &mut cargo);
88 if matches!(builder.config.cmd, Subcommand::Fix) {
89 cargo.arg("--lib");
91 }
92
93 for krate in &*self.crates {
94 cargo.arg("-p").arg(krate);
95 }
96
97 let _guard = builder.msg_check(
98 format_args!("library artifacts{}", crate_description(&self.crates)),
99 target,
100 Some(stage),
101 );
102
103 let stamp = build_stamp::libstd_stamp(builder, build_compiler, target).with_prefix("check");
104 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
105
106 drop(_guard);
107
108 if !self.crates.iter().any(|krate| krate == "test") {
110 return;
111 }
112
113 let mut cargo = builder::Cargo::new(
120 builder,
121 build_compiler,
122 Mode::Std,
123 SourceType::InTree,
124 target,
125 Kind::Check,
126 );
127
128 std_cargo(builder, target, build_compiler.stage, &mut cargo);
129
130 for krate in &*self.crates {
134 cargo.arg("-p").arg(krate);
135 }
136
137 let stamp =
138 build_stamp::libstd_stamp(builder, build_compiler, target).with_prefix("check-test");
139 let _guard = builder.msg_check("library test/bench/example targets", target, Some(stage));
140 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
141 }
142
143 fn metadata(&self) -> Option<StepMetadata> {
144 Some(StepMetadata::check("std", self.target).built_by(self.build_compiler))
145 }
146}
147
148#[derive(Debug, Clone, PartialEq, Eq, Hash)]
151pub struct Rustc {
152 pub build_compiler: Compiler,
154 pub target: TargetSelection,
155 crates: Vec<String>,
161}
162
163impl Rustc {
164 pub fn new(builder: &Builder<'_>, build_compiler: Compiler, target: TargetSelection) -> Self {
165 let crates = builder
166 .in_tree_crates("rustc-main", Some(target))
167 .into_iter()
168 .map(|krate| krate.name.to_string())
169 .collect();
170 Self { build_compiler, target, crates }
171 }
172}
173
174impl Step for Rustc {
175 type Output = ();
176 const ONLY_HOSTS: bool = true;
177 const DEFAULT: bool = true;
178
179 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
180 run.crate_or_deps("rustc-main").path("compiler")
181 }
182
183 fn make_run(run: RunConfig<'_>) {
184 let crates = run.make_run_crates(Alias::Compiler);
185 run.builder.ensure(Rustc {
186 target: run.target,
187 build_compiler: prepare_compiler_for_check(run.builder, run.target, Mode::Rustc),
188 crates,
189 });
190 }
191
192 fn run(self, builder: &Builder<'_>) {
200 let build_compiler = self.build_compiler;
201 let target = self.target;
202
203 builder.std(build_compiler, build_compiler.host);
205
206 builder.std(build_compiler, target);
211
212 let mut cargo = builder::Cargo::new(
213 builder,
214 build_compiler,
215 Mode::Rustc,
216 SourceType::InTree,
217 target,
218 Kind::Check,
219 );
220
221 rustc_cargo(builder, &mut cargo, target, &build_compiler, &self.crates);
222
223 for krate in &*self.crates {
227 cargo.arg("-p").arg(krate);
228 }
229
230 let _guard = builder.msg_check(
231 format_args!("compiler artifacts{}", crate_description(&self.crates)),
232 target,
233 None,
234 );
235
236 let stamp =
237 build_stamp::librustc_stamp(builder, build_compiler, target).with_prefix("check");
238
239 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
240
241 let libdir = builder.sysroot_target_libdir(build_compiler, target);
242 let hostdir = builder.sysroot_target_libdir(build_compiler, build_compiler.host);
243 add_to_sysroot(builder, &libdir, &hostdir, &stamp);
244 }
245
246 fn metadata(&self) -> Option<StepMetadata> {
247 Some(StepMetadata::check("rustc", self.target).built_by(self.build_compiler))
248 }
249}
250
251fn prepare_compiler_for_check(
253 builder: &Builder<'_>,
254 target: TargetSelection,
255 mode: Mode,
256) -> Compiler {
257 let host = builder.host_target;
258
259 match mode {
260 Mode::ToolBootstrap => builder.compiler(0, host),
261 Mode::ToolTarget => get_tool_target_compiler(builder, ToolTargetBuildMode::Build(target)),
262 Mode::ToolStd => {
263 if builder.config.compile_time_deps {
264 return builder.compiler(0, host);
268 }
269
270 let build_compiler = builder.compiler(builder.top_stage, host);
272
273 builder.std(build_compiler, host);
276 builder.std(build_compiler, target);
280 build_compiler
281 }
282 Mode::ToolRustc | Mode::Codegen => {
283 let stage = if host == target { builder.top_stage - 1 } else { builder.top_stage };
285 let build_compiler = builder.compiler(stage, host);
287 builder.ensure(Rustc::new(builder, build_compiler, target));
288 build_compiler
289 }
290 Mode::Rustc => {
291 let stage = if host == target { builder.top_stage - 1 } else { builder.top_stage };
299 builder.compiler(stage, host)
300 }
301 Mode::Std => {
302 builder.compiler(builder.top_stage, host)
306 }
307 }
308}
309
310#[derive(Debug, Clone, PartialEq, Eq, Hash)]
312pub struct CodegenBackend {
313 pub build_compiler: Compiler,
314 pub target: TargetSelection,
315 pub backend: CodegenBackendKind,
316}
317
318impl Step for CodegenBackend {
319 type Output = ();
320 const ONLY_HOSTS: bool = true;
321 const DEFAULT: bool = true;
322
323 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
324 run.paths(&["compiler/rustc_codegen_cranelift", "compiler/rustc_codegen_gcc"])
325 }
326
327 fn make_run(run: RunConfig<'_>) {
328 let build_compiler = prepare_compiler_for_check(run.builder, run.target, Mode::Codegen);
330 for backend in [CodegenBackendKind::Cranelift, CodegenBackendKind::Gcc] {
331 run.builder.ensure(CodegenBackend { build_compiler, target: run.target, backend });
332 }
333 }
334
335 fn run(self, builder: &Builder<'_>) {
336 if builder.build.config.vendor && self.backend.is_gcc() {
338 println!("Skipping checking of `rustc_codegen_gcc` with vendoring enabled.");
339 return;
340 }
341
342 let build_compiler = self.build_compiler;
343 let target = self.target;
344 let backend = self.backend;
345
346 let mut cargo = builder::Cargo::new(
347 builder,
348 build_compiler,
349 Mode::Codegen,
350 SourceType::InTree,
351 target,
352 builder.kind,
353 );
354
355 cargo
356 .arg("--manifest-path")
357 .arg(builder.src.join(format!("compiler/{}/Cargo.toml", backend.crate_name())));
358 rustc_cargo_env(builder, &mut cargo, target);
359
360 let _guard = builder.msg_check(backend.crate_name(), target, None);
361
362 let stamp = build_stamp::codegen_backend_stamp(builder, build_compiler, target, &backend)
363 .with_prefix("check");
364
365 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
366 }
367
368 fn metadata(&self) -> Option<StepMetadata> {
369 Some(
370 StepMetadata::check(&self.backend.crate_name(), self.target)
371 .built_by(self.build_compiler),
372 )
373 }
374}
375
376macro_rules! tool_check_step {
377 (
378 $name:ident {
379 path: $path:literal
381 $(, alt_path: $alt_path:literal )*
382 , mode: $mode:expr
384 $(, allow_features: $allow_features:expr )?
386 $(, enable_features: [$($enable_features:expr),*] )?
388 $(, default: $default:literal )?
389 $( , )?
390 }
391 ) => {
392 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
393 pub struct $name {
394 pub build_compiler: Compiler,
395 pub target: TargetSelection,
396 }
397
398 impl Step for $name {
399 type Output = ();
400 const ONLY_HOSTS: bool = true;
401 const DEFAULT: bool = true $( && $default )?;
403
404 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
405 run.paths(&[ $path, $( $alt_path ),* ])
406 }
407
408 fn make_run(run: RunConfig<'_>) {
409 let target = run.target;
410 let builder = run.builder;
411 let mode = $mode(builder);
412
413 let build_compiler = prepare_compiler_for_check(run.builder, target, mode);
414
415 if mode == Mode::ToolBootstrap && target != run.builder.host_target {
417 println!("WARNING: not checking bootstrap tool {} for target {target} as it is a bootstrap (host-only) tool", stringify!($path));
418 return;
419 };
420
421 run.builder.ensure($name { target, build_compiler });
422 }
423
424 fn run(self, builder: &Builder<'_>) {
425 let Self { target, build_compiler } = self;
426 let allow_features = {
427 let mut _value = "";
428 $( _value = $allow_features; )?
429 _value
430 };
431 let extra_features: &[&str] = &[$($($enable_features),*)?];
432 let mode = $mode(builder);
433 run_tool_check_step(builder, build_compiler, target, $path, mode, allow_features, extra_features);
434 }
435
436 fn metadata(&self) -> Option<StepMetadata> {
437 Some(StepMetadata::check(stringify!($name), self.target).built_by(self.build_compiler))
438 }
439 }
440 }
441}
442
443fn run_tool_check_step(
445 builder: &Builder<'_>,
446 build_compiler: Compiler,
447 target: TargetSelection,
448 path: &str,
449 mode: Mode,
450 allow_features: &str,
451 extra_features: &[&str],
452) {
453 let display_name = path.rsplit('/').next().unwrap();
454
455 let extra_features = extra_features.iter().map(|f| f.to_string()).collect::<Vec<String>>();
456 let mut cargo = prepare_tool_cargo(
457 builder,
458 build_compiler,
459 mode,
460 target,
461 builder.kind,
462 path,
463 SourceType::InTree,
468 &extra_features,
469 );
470 cargo.allow_features(allow_features);
471
472 if display_name == "rust-analyzer" {
475 cargo.arg("--bins");
476 cargo.arg("--tests");
477 cargo.arg("--benches");
478 } else {
479 cargo.arg("--all-targets");
480 }
481
482 let stamp = BuildStamp::new(&builder.cargo_out(build_compiler, mode, target))
483 .with_prefix(&format!("{display_name}-check"));
484
485 let stage = match mode {
486 Mode::Std | Mode::ToolRustc => build_compiler.stage,
488 _ => build_compiler.stage + 1,
489 };
490
491 let _guard =
492 builder.msg_tool(builder.kind, mode, display_name, stage, &build_compiler.host, &target);
493 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
494}
495
496tool_check_step!(Rustdoc {
497 path: "src/tools/rustdoc",
498 alt_path: "src/librustdoc",
499 mode: |_builder| Mode::ToolRustc
500});
501tool_check_step!(Clippy { path: "src/tools/clippy", mode: |_builder| Mode::ToolRustc });
506tool_check_step!(Miri { path: "src/tools/miri", mode: |_builder| Mode::ToolRustc });
507tool_check_step!(CargoMiri { path: "src/tools/miri/cargo-miri", mode: |_builder| Mode::ToolRustc });
508tool_check_step!(Rustfmt { path: "src/tools/rustfmt", mode: |_builder| Mode::ToolRustc });
509tool_check_step!(RustAnalyzer {
510 path: "src/tools/rust-analyzer",
511 mode: |_builder| Mode::ToolRustc,
512 allow_features: tool::RustAnalyzer::ALLOW_FEATURES,
513 enable_features: ["in-rust-tree"],
514});
515tool_check_step!(MiroptTestTools {
516 path: "src/tools/miropt-test-tools",
517 mode: |_builder| Mode::ToolBootstrap
518});
519tool_check_step!(TestFloatParse {
521 path: "src/tools/test-float-parse",
522 mode: |_builder| Mode::ToolStd,
523 allow_features: tool::TestFloatParse::ALLOW_FEATURES
524});
525tool_check_step!(FeaturesStatusDump {
526 path: "src/tools/features-status-dump",
527 mode: |_builder| Mode::ToolBootstrap
528});
529
530tool_check_step!(Bootstrap {
531 path: "src/bootstrap",
532 mode: |_builder| Mode::ToolBootstrap,
533 default: false
534});
535
536tool_check_step!(RunMakeSupport {
539 path: "src/tools/run-make-support",
540 mode: |_builder| Mode::ToolBootstrap,
541 default: false
542});
543
544tool_check_step!(CoverageDump {
545 path: "src/tools/coverage-dump",
546 mode: |_builder| Mode::ToolBootstrap,
547 default: false
548});
549
550tool_check_step!(Compiletest {
553 path: "src/tools/compiletest",
554 mode: |builder: &Builder<'_>| if builder.config.compiletest_use_stage0_libtest {
555 Mode::ToolBootstrap
556 } else {
557 Mode::ToolStd
558 },
559 allow_features: COMPILETEST_ALLOW_FEATURES,
560 default: false,
561});
562
563tool_check_step!(Linkchecker {
564 path: "src/tools/linkchecker",
565 mode: |_builder| Mode::ToolBootstrap,
566 default: false
567});