1 //! Implementation of compiling the compiler and standard library, in "check"-based modes.
3 use crate::builder::{Builder, Kind, RunConfig, ShouldRun, Step};
4 use crate::cache::Interned;
5 use crate::compile::{add_to_sysroot, run_cargo, rustc_cargo, rustc_cargo_env, std_cargo};
6 use crate::config::TargetSelection;
7 use crate::tool::{prepare_tool_cargo, SourceType};
9 use crate::{Compiler, Mode, Subcommand};
10 use std::path::PathBuf;
12 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
14 pub target: TargetSelection,
17 /// Returns args for the subcommand itself (not for cargo)
18 fn args(builder: &Builder<'_>) -> Vec<String> {
19 fn strings<'a>(arr: &'a [&str]) -> impl Iterator<Item = String> + 'a {
20 arr.iter().copied().map(String::from)
23 if let Subcommand::Clippy { fix, .. } = builder.config.cmd {
24 // disable the most spammy clippy lints
25 let ignored_lints = vec![
26 "many_single_char_names", // there are a lot in stdarch
29 "missing_safety_doc", // almost 3K warnings
31 "needless_lifetimes", // people want to keep the lifetimes
32 "wrong_self_convention",
34 let mut args = vec![];
37 args.extend(strings(&[
38 "--fix", "-Zunstable-options",
39 // FIXME: currently, `--fix` gives an error while checking tests for libtest,
40 // possibly because libtest is not yet built in the sysroot.
41 // As a workaround, avoid checking tests and benches when passed --fix.
42 "--lib", "--bins", "--examples",
45 args.extend(strings(&["--", "--cap-lints", "warn"]));
46 args.extend(ignored_lints.iter().map(|lint| format!("-Aclippy::{}", lint)));
53 fn cargo_subcommand(kind: Kind) -> &'static str {
55 Kind::Check => "check",
56 Kind::Clippy => "clippy",
64 const DEFAULT: bool = true;
66 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
67 run.all_krates("test")
70 fn make_run(run: RunConfig<'_>) {
71 run.builder.ensure(Std { target: run.target });
74 fn run(self, builder: &Builder<'_>) {
75 let target = self.target;
76 let compiler = builder.compiler(0, builder.config.build);
78 let mut cargo = builder.cargo(
83 cargo_subcommand(builder.kind),
85 std_cargo(builder, target, compiler.stage, &mut cargo);
87 builder.info(&format!("Checking std artifacts ({} -> {})", &compiler.host, target));
92 &libstd_stamp(builder, compiler, target),
97 let libdir = builder.sysroot_libdir(compiler, target);
98 let hostdir = builder.sysroot_libdir(compiler, compiler.host);
99 add_to_sysroot(&builder, &libdir, &hostdir, &libstd_stamp(builder, compiler, target));
101 // Then run cargo again, once we've put the rmeta files for the library
102 // crates into the sysroot. This is needed because e.g., core's tests
103 // depend on `libtest` -- Cargo presumes it will exist, but it doesn't
104 // since we initialize with an empty sysroot.
106 // Currently only the "libtest" tree of crates does this.
108 if let Subcommand::Check { all_targets: true, .. } = builder.config.cmd {
109 let mut cargo = builder.cargo(
114 cargo_subcommand(builder.kind),
116 std_cargo(builder, target, compiler.stage, &mut cargo);
117 cargo.arg("--all-targets");
119 // Explicitly pass -p for all dependencies krates -- this will force cargo
120 // to also check the tests/benches/examples for these crates, rather
121 // than just the leaf crate.
122 for krate in builder.in_tree_crates("test", Some(target)) {
123 cargo.arg("-p").arg(krate.name);
126 builder.info(&format!(
127 "Checking std test/bench/example targets ({} -> {})",
128 &compiler.host, target
134 &libstd_test_stamp(builder, compiler, target),
142 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
144 pub target: TargetSelection,
147 impl Step for Rustc {
149 const ONLY_HOSTS: bool = true;
150 const DEFAULT: bool = true;
152 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
153 run.all_krates("rustc-main")
156 fn make_run(run: RunConfig<'_>) {
157 run.builder.ensure(Rustc { target: run.target });
160 /// Builds the compiler.
162 /// This will build the compiler for a particular stage of the build using
163 /// the `compiler` targeting the `target` architecture. The artifacts
164 /// created will also be linked into the sysroot directory.
165 fn run(self, builder: &Builder<'_>) {
166 let compiler = builder.compiler(0, builder.config.build);
167 let target = self.target;
169 builder.ensure(Std { target });
171 let mut cargo = builder.cargo(
176 cargo_subcommand(builder.kind),
178 rustc_cargo(builder, &mut cargo, target);
179 if let Subcommand::Check { all_targets: true, .. } = builder.config.cmd {
180 cargo.arg("--all-targets");
183 // Explicitly pass -p for all compiler krates -- this will force cargo
184 // to also check the tests/benches/examples for these crates, rather
185 // than just the leaf crate.
186 for krate in builder.in_tree_crates("rustc-main", Some(target)) {
187 cargo.arg("-p").arg(krate.name);
190 builder.info(&format!("Checking compiler artifacts ({} -> {})", &compiler.host, target));
195 &librustc_stamp(builder, compiler, target),
200 let libdir = builder.sysroot_libdir(compiler, target);
201 let hostdir = builder.sysroot_libdir(compiler, compiler.host);
202 add_to_sysroot(&builder, &libdir, &hostdir, &librustc_stamp(builder, compiler, target));
206 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
207 pub struct CodegenBackend {
208 pub target: TargetSelection,
209 pub backend: Interned<String>,
212 impl Step for CodegenBackend {
214 const ONLY_HOSTS: bool = true;
215 const DEFAULT: bool = true;
217 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
218 run.paths(&["compiler/rustc_codegen_cranelift", "rustc_codegen_cranelift"])
221 fn make_run(run: RunConfig<'_>) {
222 for &backend in &[INTERNER.intern_str("cranelift")] {
223 run.builder.ensure(CodegenBackend { target: run.target, backend });
227 fn run(self, builder: &Builder<'_>) {
228 let compiler = builder.compiler(0, builder.config.build);
229 let target = self.target;
230 let backend = self.backend;
232 builder.ensure(Rustc { target });
234 let mut cargo = builder.cargo(
237 SourceType::Submodule,
239 cargo_subcommand(builder.kind),
242 .arg("--manifest-path")
243 .arg(builder.src.join(format!("compiler/rustc_codegen_{}/Cargo.toml", backend)));
244 rustc_cargo_env(builder, &mut cargo, target);
246 builder.info(&format!(
247 "Checking {} artifacts ({} -> {})",
248 backend, &compiler.host.triple, target.triple
255 &codegen_backend_stamp(builder, compiler, target, backend),
262 macro_rules! tool_check_step {
263 ($name:ident, $path:expr, $source_type:expr) => {
264 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
266 pub target: TargetSelection,
269 impl Step for $name {
271 const ONLY_HOSTS: bool = true;
272 const DEFAULT: bool = true;
274 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
278 fn make_run(run: RunConfig<'_>) {
279 run.builder.ensure($name { target: run.target });
282 fn run(self, builder: &Builder<'_>) {
283 let compiler = builder.compiler(0, builder.config.build);
284 let target = self.target;
286 builder.ensure(Rustc { target });
288 let mut cargo = prepare_tool_cargo(
293 cargo_subcommand(builder.kind),
299 if let Subcommand::Check { all_targets: true, .. } = builder.config.cmd {
300 cargo.arg("--all-targets");
303 builder.info(&format!(
304 "Checking {} artifacts ({} -> {})",
305 stringify!($name).to_lowercase(),
306 &compiler.host.triple,
313 &stamp(builder, compiler, target),
318 let libdir = builder.sysroot_libdir(compiler, target);
319 let hostdir = builder.sysroot_libdir(compiler, compiler.host);
320 add_to_sysroot(&builder, &libdir, &hostdir, &stamp(builder, compiler, target));
322 /// Cargo's output path in a given stage, compiled by a particular
323 /// compiler for the specified target.
325 builder: &Builder<'_>,
327 target: TargetSelection,
330 .cargo_out(compiler, Mode::ToolRustc, target)
331 .join(format!(".{}-check.stamp", stringify!($name).to_lowercase()))
338 tool_check_step!(Rustdoc, "src/tools/rustdoc", SourceType::InTree);
339 // Clippy is a hybrid. It is an external tool, but uses a git subtree instead
340 // of a submodule. Since the SourceType only drives the deny-warnings
341 // behavior, treat it as in-tree so that any new warnings in clippy will be
343 tool_check_step!(Clippy, "src/tools/clippy", SourceType::InTree);
345 tool_check_step!(Bootstrap, "src/bootstrap", SourceType::InTree);
347 /// Cargo's output path for the standard library in a given stage, compiled
348 /// by a particular compiler for the specified target.
349 fn libstd_stamp(builder: &Builder<'_>, compiler: Compiler, target: TargetSelection) -> PathBuf {
350 builder.cargo_out(compiler, Mode::Std, target).join(".libstd-check.stamp")
353 /// Cargo's output path for the standard library in a given stage, compiled
354 /// by a particular compiler for the specified target.
355 fn libstd_test_stamp(
356 builder: &Builder<'_>,
358 target: TargetSelection,
360 builder.cargo_out(compiler, Mode::Std, target).join(".libstd-check-test.stamp")
363 /// Cargo's output path for librustc in a given stage, compiled by a particular
364 /// compiler for the specified target.
365 fn librustc_stamp(builder: &Builder<'_>, compiler: Compiler, target: TargetSelection) -> PathBuf {
366 builder.cargo_out(compiler, Mode::Rustc, target).join(".librustc-check.stamp")
369 /// Cargo's output path for librustc_codegen_llvm in a given stage, compiled by a particular
370 /// compiler for the specified target and backend.
371 fn codegen_backend_stamp(
372 builder: &Builder<'_>,
374 target: TargetSelection,
375 backend: Interned<String>,
378 .cargo_out(compiler, Mode::Codegen, target)
379 .join(format!(".librustc_codegen_{}-check.stamp", backend))