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
35impl Step for Std {
36 type Output = ();
37 const DEFAULT: bool = true;
38
39 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
40 let mut run = run;
41 for c in Std::CRATE_OR_DEPS {
42 run = run.crate_or_deps(c);
43 }
44
45 run.path("library")
46 }
47
48 fn make_run(run: RunConfig<'_>) {
49 if !run.builder.download_rustc() && run.builder.config.skip_std_check_if_no_download_rustc {
50 eprintln!(
51 "WARNING: `--skip-std-check-if-no-download-rustc` flag was passed and `rust.download-rustc` is not available. Skipping."
52 );
53 return;
54 }
55
56 if run.builder.config.compile_time_deps {
57 return;
59 }
60
61 let crates = std_crates_for_run_make(&run);
62 run.builder.ensure(Std {
63 build_compiler: prepare_compiler_for_check(run.builder, run.target, Mode::Std),
64 target: run.target,
65 crates,
66 });
67 }
68
69 fn run(self, builder: &Builder<'_>) {
70 let build_compiler = self.build_compiler;
71 let target = self.target;
72
73 let mut cargo = builder::Cargo::new(
74 builder,
75 build_compiler,
76 Mode::Std,
77 SourceType::InTree,
78 target,
79 Kind::Check,
80 );
81
82 std_cargo(builder, target, &mut cargo);
83 if matches!(builder.config.cmd, Subcommand::Fix) {
84 cargo.arg("--lib");
86 }
87
88 for krate in &*self.crates {
89 cargo.arg("-p").arg(krate);
90 }
91
92 let _guard = builder.msg(
93 Kind::Check,
94 format_args!("library artifacts{}", crate_description(&self.crates)),
95 Mode::Std,
96 self.build_compiler,
97 target,
98 );
99
100 let stamp = build_stamp::libstd_stamp(builder, build_compiler, target).with_prefix("check");
101 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
102
103 drop(_guard);
104
105 if !self.crates.iter().any(|krate| krate == "test") {
107 return;
108 }
109
110 let mut cargo = builder::Cargo::new(
117 builder,
118 build_compiler,
119 Mode::Std,
120 SourceType::InTree,
121 target,
122 Kind::Check,
123 );
124
125 std_cargo(builder, target, &mut cargo);
126
127 for krate in &*self.crates {
131 cargo.arg("-p").arg(krate);
132 }
133
134 let stamp =
135 build_stamp::libstd_stamp(builder, build_compiler, target).with_prefix("check-test");
136 let _guard = builder.msg(
137 Kind::Check,
138 "library test/bench/example targets",
139 Mode::Std,
140 self.build_compiler,
141 target,
142 );
143 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
144 }
145
146 fn metadata(&self) -> Option<StepMetadata> {
147 Some(StepMetadata::check("std", self.target).built_by(self.build_compiler))
148 }
149}
150
151#[derive(Debug, Clone, PartialEq, Eq, Hash)]
154pub struct Rustc {
155 pub build_compiler: Compiler,
157 pub target: TargetSelection,
158 crates: Vec<String>,
164}
165
166impl Rustc {
167 pub fn new(builder: &Builder<'_>, target: TargetSelection, crates: Vec<String>) -> Self {
168 let build_compiler = prepare_compiler_for_check(builder, target, Mode::Rustc);
169 Self { build_compiler, target, crates }
170 }
171}
172
173impl Step for Rustc {
174 type Output = ();
175 const ONLY_HOSTS: bool = true;
176 const DEFAULT: bool = true;
177
178 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
179 run.crate_or_deps("rustc-main").path("compiler")
180 }
181
182 fn make_run(run: RunConfig<'_>) {
183 let crates = run.make_run_crates(Alias::Compiler);
184 run.builder.ensure(Rustc::new(run.builder, run.target, crates));
185 }
186
187 fn run(self, builder: &Builder<'_>) {
195 let build_compiler = self.build_compiler;
196 let target = self.target;
197
198 let mut cargo = builder::Cargo::new(
199 builder,
200 build_compiler,
201 Mode::Rustc,
202 SourceType::InTree,
203 target,
204 Kind::Check,
205 );
206
207 rustc_cargo(builder, &mut cargo, target, &build_compiler, &self.crates);
208
209 for krate in &*self.crates {
213 cargo.arg("-p").arg(krate);
214 }
215
216 let _guard = builder.msg(
217 Kind::Check,
218 format_args!("compiler artifacts{}", crate_description(&self.crates)),
219 Mode::Rustc,
220 self.build_compiler,
221 target,
222 );
223
224 let stamp =
225 build_stamp::librustc_stamp(builder, build_compiler, target).with_prefix("check");
226
227 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
228
229 let libdir = builder.sysroot_target_libdir(build_compiler, target);
230 let hostdir = builder.sysroot_target_libdir(build_compiler, build_compiler.host);
231 add_to_sysroot(builder, &libdir, &hostdir, &stamp);
232 }
233
234 fn metadata(&self) -> Option<StepMetadata> {
235 let metadata = StepMetadata::check("rustc", self.target).built_by(self.build_compiler);
236 let metadata = if self.crates.is_empty() {
237 metadata
238 } else {
239 metadata.with_metadata(format!("({} crates)", self.crates.len()))
240 };
241 Some(metadata)
242 }
243}
244
245pub fn prepare_compiler_for_check(
247 builder: &Builder<'_>,
248 target: TargetSelection,
249 mode: Mode,
250) -> Compiler {
251 let host = builder.host_target;
252
253 match mode {
254 Mode::ToolBootstrap => builder.compiler(0, host),
255 Mode::ToolTarget => get_tool_target_compiler(builder, ToolTargetBuildMode::Build(target)),
256 Mode::ToolStd => {
257 if builder.config.compile_time_deps {
258 return builder.compiler(0, host);
262 }
263
264 let build_compiler = builder.compiler(builder.top_stage, host);
266
267 builder.std(build_compiler, host);
270 builder.std(build_compiler, target);
274 build_compiler
275 }
276 Mode::ToolRustc | Mode::Codegen => {
277 let check = Rustc::new(builder, target, vec![]);
282 let build_compiler = check.build_compiler;
283 builder.ensure(check);
284 build_compiler
285 }
286 Mode::Rustc => {
287 let stage = if host == target { builder.top_stage - 1 } else { builder.top_stage };
295 let build_compiler = builder.compiler(stage, host);
296
297 builder.std(build_compiler, build_compiler.host);
299
300 builder.std(build_compiler, target);
305
306 build_compiler
307 }
308 Mode::Std => {
309 builder.compiler(builder.top_stage, host)
313 }
314 }
315}
316
317#[derive(Debug, Clone, PartialEq, Eq, Hash)]
319pub struct CodegenBackend {
320 pub build_compiler: Compiler,
321 pub target: TargetSelection,
322 pub backend: CodegenBackendKind,
323}
324
325impl Step for CodegenBackend {
326 type Output = ();
327 const ONLY_HOSTS: bool = true;
328 const DEFAULT: bool = true;
329
330 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
331 run.paths(&["compiler/rustc_codegen_cranelift", "compiler/rustc_codegen_gcc"])
332 }
333
334 fn make_run(run: RunConfig<'_>) {
335 let build_compiler = prepare_compiler_for_check(run.builder, run.target, Mode::Codegen);
337 for backend in [CodegenBackendKind::Cranelift, CodegenBackendKind::Gcc] {
338 run.builder.ensure(CodegenBackend { build_compiler, target: run.target, backend });
339 }
340 }
341
342 fn run(self, builder: &Builder<'_>) {
343 if builder.build.config.vendor && self.backend.is_gcc() {
345 println!("Skipping checking of `rustc_codegen_gcc` with vendoring enabled.");
346 return;
347 }
348
349 let build_compiler = self.build_compiler;
350 let target = self.target;
351 let backend = self.backend;
352
353 let mut cargo = builder::Cargo::new(
354 builder,
355 build_compiler,
356 Mode::Codegen,
357 SourceType::InTree,
358 target,
359 builder.kind,
360 );
361
362 cargo
363 .arg("--manifest-path")
364 .arg(builder.src.join(format!("compiler/{}/Cargo.toml", backend.crate_name())));
365 rustc_cargo_env(builder, &mut cargo, target);
366
367 let _guard = builder.msg(
368 Kind::Check,
369 backend.crate_name(),
370 Mode::Codegen,
371 self.build_compiler,
372 target,
373 );
374
375 let stamp = build_stamp::codegen_backend_stamp(builder, build_compiler, target, &backend)
376 .with_prefix("check");
377
378 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
379 }
380
381 fn metadata(&self) -> Option<StepMetadata> {
382 Some(
383 StepMetadata::check(&self.backend.crate_name(), self.target)
384 .built_by(self.build_compiler),
385 )
386 }
387}
388
389macro_rules! tool_check_step {
390 (
391 $name:ident {
392 path: $path:literal
394 $(, alt_path: $alt_path:literal )*
395 , mode: $mode:expr
397 $(, allow_features: $allow_features:expr )?
399 $(, enable_features: [$($enable_features:expr),*] )?
401 $(, default: $default:literal )?
402 $( , )?
403 }
404 ) => {
405 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
406 pub struct $name {
407 pub build_compiler: Compiler,
408 pub target: TargetSelection,
409 }
410
411 impl Step for $name {
412 type Output = ();
413 const ONLY_HOSTS: bool = true;
414 const DEFAULT: bool = true $( && $default )?;
416
417 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
418 run.paths(&[ $path, $( $alt_path ),* ])
419 }
420
421 fn make_run(run: RunConfig<'_>) {
422 let target = run.target;
423 let builder = run.builder;
424 let mode = $mode(builder);
425
426 let build_compiler = prepare_compiler_for_check(run.builder, target, mode);
427
428 if mode == Mode::ToolBootstrap && target != run.builder.host_target {
430 println!("WARNING: not checking bootstrap tool {} for target {target} as it is a bootstrap (host-only) tool", stringify!($path));
431 return;
432 };
433
434 run.builder.ensure($name { target, build_compiler });
435 }
436
437 fn run(self, builder: &Builder<'_>) {
438 let Self { target, build_compiler } = self;
439 let allow_features = {
440 let mut _value = "";
441 $( _value = $allow_features; )?
442 _value
443 };
444 let extra_features: &[&str] = &[$($($enable_features),*)?];
445 let mode = $mode(builder);
446 run_tool_check_step(builder, build_compiler, target, $path, mode, allow_features, extra_features);
447 }
448
449 fn metadata(&self) -> Option<StepMetadata> {
450 Some(StepMetadata::check(stringify!($name), self.target).built_by(self.build_compiler))
451 }
452 }
453 }
454}
455
456fn run_tool_check_step(
458 builder: &Builder<'_>,
459 build_compiler: Compiler,
460 target: TargetSelection,
461 path: &str,
462 mode: Mode,
463 allow_features: &str,
464 extra_features: &[&str],
465) {
466 let display_name = path.rsplit('/').next().unwrap();
467
468 let extra_features = extra_features.iter().map(|f| f.to_string()).collect::<Vec<String>>();
469 let mut cargo = prepare_tool_cargo(
470 builder,
471 build_compiler,
472 mode,
473 target,
474 builder.kind,
475 path,
476 SourceType::InTree,
481 &extra_features,
482 );
483 cargo.allow_features(allow_features);
484
485 if display_name == "rust-analyzer" {
488 cargo.arg("--bins");
489 cargo.arg("--tests");
490 cargo.arg("--benches");
491 } else {
492 cargo.arg("--all-targets");
493 }
494
495 let stamp = BuildStamp::new(&builder.cargo_out(build_compiler, mode, target))
496 .with_prefix(&format!("{display_name}-check"));
497
498 let _guard = builder.msg(builder.kind, display_name, mode, build_compiler, target);
499 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
500}
501
502tool_check_step!(Rustdoc {
503 path: "src/tools/rustdoc",
504 alt_path: "src/librustdoc",
505 mode: |_builder| Mode::ToolRustc
506});
507tool_check_step!(Clippy { path: "src/tools/clippy", mode: |_builder| Mode::ToolRustc });
512tool_check_step!(Miri { path: "src/tools/miri", mode: |_builder| Mode::ToolRustc });
513tool_check_step!(CargoMiri { path: "src/tools/miri/cargo-miri", mode: |_builder| Mode::ToolRustc });
514tool_check_step!(Rustfmt { path: "src/tools/rustfmt", mode: |_builder| Mode::ToolRustc });
515tool_check_step!(RustAnalyzer {
516 path: "src/tools/rust-analyzer",
517 mode: |_builder| Mode::ToolRustc,
518 allow_features: tool::RustAnalyzer::ALLOW_FEATURES,
519 enable_features: ["in-rust-tree"],
520});
521tool_check_step!(MiroptTestTools {
522 path: "src/tools/miropt-test-tools",
523 mode: |_builder| Mode::ToolBootstrap
524});
525tool_check_step!(TestFloatParse {
527 path: "src/tools/test-float-parse",
528 mode: |_builder| Mode::ToolStd,
529 allow_features: tool::TestFloatParse::ALLOW_FEATURES
530});
531tool_check_step!(FeaturesStatusDump {
532 path: "src/tools/features-status-dump",
533 mode: |_builder| Mode::ToolBootstrap
534});
535
536tool_check_step!(Bootstrap {
537 path: "src/bootstrap",
538 mode: |_builder| Mode::ToolBootstrap,
539 default: false
540});
541
542tool_check_step!(RunMakeSupport {
545 path: "src/tools/run-make-support",
546 mode: |_builder| Mode::ToolBootstrap,
547 default: false
548});
549
550tool_check_step!(CoverageDump {
551 path: "src/tools/coverage-dump",
552 mode: |_builder| Mode::ToolBootstrap,
553 default: false
554});
555
556tool_check_step!(Compiletest {
559 path: "src/tools/compiletest",
560 mode: |builder: &Builder<'_>| if builder.config.compiletest_use_stage0_libtest {
561 Mode::ToolBootstrap
562 } else {
563 Mode::ToolStd
564 },
565 allow_features: COMPILETEST_ALLOW_FEATURES,
566 default: false,
567});
568
569tool_check_step!(Linkchecker {
570 path: "src/tools/linkchecker",
571 mode: |_builder| Mode::ToolBootstrap,
572 default: false
573});