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::{SourceType, prepare_tool_cargo};
7use crate::core::builder::{
8 self, Alias, Builder, Kind, RunConfig, ShouldRun, Step, crate_description,
9};
10use crate::core::config::TargetSelection;
11use crate::utils::build_stamp::{self, BuildStamp};
12use crate::{Mode, Subcommand};
13
14#[derive(Debug, Clone, PartialEq, Eq, Hash)]
15pub struct Std {
16 pub target: TargetSelection,
17 crates: Vec<String>,
23 override_build_kind: Option<Kind>,
30}
31
32impl Std {
33 pub fn new(target: TargetSelection) -> Self {
34 Self { target, crates: vec![], override_build_kind: None }
35 }
36
37 pub fn build_kind(mut self, kind: Option<Kind>) -> Self {
38 self.override_build_kind = kind;
39 self
40 }
41}
42
43impl Step for Std {
44 type Output = ();
45 const DEFAULT: bool = true;
46
47 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
48 run.crate_or_deps("sysroot").crate_or_deps("coretests").path("library")
49 }
50
51 fn make_run(run: RunConfig<'_>) {
52 let crates = std_crates_for_run_make(&run);
53 run.builder.ensure(Std { target: run.target, crates, override_build_kind: None });
54 }
55
56 fn run(self, builder: &Builder<'_>) {
57 builder.require_submodule("library/stdarch", None);
58
59 let target = self.target;
60 let compiler = builder.compiler(builder.top_stage, builder.config.build);
61
62 let mut cargo = builder::Cargo::new(
63 builder,
64 compiler,
65 Mode::Std,
66 SourceType::InTree,
67 target,
68 self.override_build_kind.unwrap_or(builder.kind),
69 );
70
71 std_cargo(builder, target, compiler.stage, &mut cargo);
72 if matches!(builder.config.cmd, Subcommand::Fix { .. }) {
73 cargo.arg("--lib");
75 }
76
77 for krate in &*self.crates {
78 cargo.arg("-p").arg(krate);
79 }
80
81 let _guard = builder.msg_check(
82 format_args!("library artifacts{}", crate_description(&self.crates)),
83 target,
84 );
85
86 let stamp = build_stamp::libstd_stamp(builder, compiler, target).with_prefix("check");
87 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
88
89 if compiler.stage == 0 {
92 let libdir = builder.sysroot_target_libdir(compiler, target);
93 let hostdir = builder.sysroot_target_libdir(compiler, compiler.host);
94 add_to_sysroot(builder, &libdir, &hostdir, &stamp);
95 }
96 drop(_guard);
97
98 if builder.kind == Kind::Clippy || !self.crates.iter().any(|krate| krate == "test") {
101 return;
102 }
103
104 let mut cargo = builder::Cargo::new(
111 builder,
112 compiler,
113 Mode::Std,
114 SourceType::InTree,
115 target,
116 self.override_build_kind.unwrap_or(builder.kind),
117 );
118
119 if compiler.stage == 0 {
123 cargo.arg("--all-targets");
124 }
125
126 std_cargo(builder, target, compiler.stage, &mut cargo);
127
128 for krate in &*self.crates {
132 cargo.arg("-p").arg(krate);
133 }
134
135 let stamp = build_stamp::libstd_stamp(builder, compiler, target).with_prefix("check-test");
136 let _guard = builder.msg_check("library test/bench/example targets", target);
137 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
138 }
139}
140
141#[derive(Debug, Clone, PartialEq, Eq, Hash)]
142pub struct Rustc {
143 pub target: TargetSelection,
144 crates: Vec<String>,
150 override_build_kind: Option<Kind>,
157}
158
159impl Rustc {
160 pub fn new(target: TargetSelection, builder: &Builder<'_>) -> Self {
161 let crates = builder
162 .in_tree_crates("rustc-main", Some(target))
163 .into_iter()
164 .map(|krate| krate.name.to_string())
165 .collect();
166 Self { target, crates, override_build_kind: None }
167 }
168
169 pub fn build_kind(mut self, build_kind: Option<Kind>) -> Self {
170 self.override_build_kind = build_kind;
171 self
172 }
173}
174
175impl Step for Rustc {
176 type Output = ();
177 const ONLY_HOSTS: bool = true;
178 const DEFAULT: bool = true;
179
180 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
181 run.crate_or_deps("rustc-main").path("compiler")
182 }
183
184 fn make_run(run: RunConfig<'_>) {
185 let crates = run.make_run_crates(Alias::Compiler);
186 run.builder.ensure(Rustc { target: run.target, crates, override_build_kind: None });
187 }
188
189 fn run(self, builder: &Builder<'_>) {
195 let compiler = builder.compiler(builder.top_stage, builder.config.build);
196 let target = self.target;
197
198 if compiler.stage != 0 {
199 builder.ensure(crate::core::build_steps::compile::Std::new(compiler, compiler.host));
205 builder.ensure(crate::core::build_steps::compile::Std::new(compiler, target));
206 } else {
207 builder.ensure(Std::new(target).build_kind(self.override_build_kind));
208 }
209
210 let mut cargo = builder::Cargo::new(
211 builder,
212 compiler,
213 Mode::Rustc,
214 SourceType::InTree,
215 target,
216 self.override_build_kind.unwrap_or(builder.kind),
217 );
218
219 rustc_cargo(builder, &mut cargo, target, &compiler, &self.crates);
220
221 if builder.kind != Kind::Clippy {
224 cargo.arg("--all-targets");
225 }
226
227 for krate in &*self.crates {
231 cargo.arg("-p").arg(krate);
232 }
233
234 let _guard = builder.msg_check(
235 format_args!("compiler artifacts{}", crate_description(&self.crates)),
236 target,
237 );
238
239 let stamp = build_stamp::librustc_stamp(builder, compiler, target).with_prefix("check");
240
241 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
242
243 let libdir = builder.sysroot_target_libdir(compiler, target);
244 let hostdir = builder.sysroot_target_libdir(compiler, compiler.host);
245 add_to_sysroot(builder, &libdir, &hostdir, &stamp);
246 }
247}
248
249#[derive(Debug, Clone, PartialEq, Eq, Hash)]
250pub struct CodegenBackend {
251 pub target: TargetSelection,
252 pub backend: &'static str,
253}
254
255impl Step for CodegenBackend {
256 type Output = ();
257 const ONLY_HOSTS: bool = true;
258 const DEFAULT: bool = true;
259
260 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
261 run.paths(&["compiler/rustc_codegen_cranelift", "compiler/rustc_codegen_gcc"])
262 }
263
264 fn make_run(run: RunConfig<'_>) {
265 for &backend in &["cranelift", "gcc"] {
266 run.builder.ensure(CodegenBackend { target: run.target, backend });
267 }
268 }
269
270 fn run(self, builder: &Builder<'_>) {
271 if builder.build.config.vendor && self.backend == "gcc" {
273 println!("Skipping checking of `rustc_codegen_gcc` with vendoring enabled.");
274 return;
275 }
276
277 let compiler = builder.compiler(builder.top_stage, builder.config.build);
278 let target = self.target;
279 let backend = self.backend;
280
281 builder.ensure(Rustc::new(target, builder));
282
283 let mut cargo = builder::Cargo::new(
284 builder,
285 compiler,
286 Mode::Codegen,
287 SourceType::InTree,
288 target,
289 builder.kind,
290 );
291
292 cargo
293 .arg("--manifest-path")
294 .arg(builder.src.join(format!("compiler/rustc_codegen_{backend}/Cargo.toml")));
295 rustc_cargo_env(builder, &mut cargo, target, compiler.stage);
296
297 let _guard = builder.msg_check(backend, target);
298
299 let stamp = build_stamp::codegen_backend_stamp(builder, compiler, target, backend)
300 .with_prefix("check");
301
302 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
303 }
304}
305
306#[derive(Debug, Clone, PartialEq, Eq, Hash)]
307pub struct RustAnalyzer {
308 pub target: TargetSelection,
309}
310
311impl Step for RustAnalyzer {
312 type Output = ();
313 const ONLY_HOSTS: bool = true;
314 const DEFAULT: bool = true;
315
316 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
317 let builder = run.builder;
318 run.path("src/tools/rust-analyzer").default_condition(
319 builder
320 .config
321 .tools
322 .as_ref()
323 .is_none_or(|tools| tools.iter().any(|tool| tool == "rust-analyzer")),
324 )
325 }
326
327 fn make_run(run: RunConfig<'_>) {
328 run.builder.ensure(RustAnalyzer { target: run.target });
329 }
330
331 fn run(self, builder: &Builder<'_>) {
332 let compiler = builder.compiler(builder.top_stage, builder.config.build);
333 let target = self.target;
334
335 builder.ensure(Rustc::new(target, builder));
336
337 let mut cargo = prepare_tool_cargo(
338 builder,
339 compiler,
340 Mode::ToolRustc,
341 target,
342 builder.kind,
343 "src/tools/rust-analyzer",
344 SourceType::InTree,
345 &["in-rust-tree".to_owned()],
346 );
347
348 cargo.allow_features(crate::core::build_steps::tool::RustAnalyzer::ALLOW_FEATURES);
349
350 if builder.kind != Kind::Clippy {
353 cargo.arg("--bins");
355 cargo.arg("--tests");
356 cargo.arg("--benches");
357 }
358
359 let stamp = BuildStamp::new(&builder.cargo_out(compiler, Mode::ToolRustc, target))
362 .with_prefix("rust-analyzer-check");
363
364 let _guard = builder.msg_check("rust-analyzer artifacts", target);
365 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
366 }
367}
368
369macro_rules! tool_check_step {
370 (
371 $name:ident {
372 path: $path:literal
374 $(, alt_path: $alt_path:literal )*
375 $(, default: $default:literal )?
376 $( , )?
377 }
378 ) => {
379 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
380 pub struct $name {
381 pub target: TargetSelection,
382 }
383
384 impl Step for $name {
385 type Output = ();
386 const ONLY_HOSTS: bool = true;
387 const DEFAULT: bool = true $( && $default )?;
389
390 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
391 run.paths(&[ $path, $( $alt_path ),* ])
392 }
393
394 fn make_run(run: RunConfig<'_>) {
395 run.builder.ensure($name { target: run.target });
396 }
397
398 fn run(self, builder: &Builder<'_>) {
399 let Self { target } = self;
400 run_tool_check_step(builder, target, stringify!($name), $path);
401 }
402 }
403 }
404}
405
406fn run_tool_check_step(
408 builder: &Builder<'_>,
409 target: TargetSelection,
410 step_type_name: &str,
411 path: &str,
412) {
413 let display_name = path.rsplit('/').next().unwrap();
414 let compiler = builder.compiler(builder.top_stage, builder.config.build);
415
416 builder.ensure(Rustc::new(target, builder));
417
418 let mut cargo = prepare_tool_cargo(
419 builder,
420 compiler,
421 Mode::ToolRustc,
422 target,
423 builder.kind,
424 path,
425 SourceType::InTree,
430 &[],
431 );
432
433 if builder.kind != Kind::Clippy {
436 cargo.arg("--all-targets");
437 }
438
439 let stamp = BuildStamp::new(&builder.cargo_out(compiler, Mode::ToolRustc, target))
440 .with_prefix(&format!("{}-check", step_type_name.to_lowercase()));
441
442 let _guard = builder.msg_check(format!("{display_name} artifacts"), target);
443 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
444}
445
446tool_check_step!(Rustdoc { path: "src/tools/rustdoc", alt_path: "src/librustdoc" });
447tool_check_step!(Clippy { path: "src/tools/clippy" });
452tool_check_step!(Miri { path: "src/tools/miri" });
453tool_check_step!(CargoMiri { path: "src/tools/miri/cargo-miri" });
454tool_check_step!(Rls { path: "src/tools/rls" });
455tool_check_step!(Rustfmt { path: "src/tools/rustfmt" });
456tool_check_step!(MiroptTestTools { path: "src/tools/miropt-test-tools" });
457tool_check_step!(TestFloatParse { path: "src/etc/test-float-parse" });
458tool_check_step!(FeaturesStatusDump { path: "src/tools/features-status-dump" });
459
460tool_check_step!(Bootstrap { path: "src/bootstrap", default: false });
461
462tool_check_step!(RunMakeSupport { path: "src/tools/run-make-support", default: false });
465
466tool_check_step!(Compiletest { path: "src/tools/compiletest", default: false });