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::compile::{add_to_sysroot, run_cargo, rustc_cargo, std_cargo};
5 use crate::config::TargetSelection;
6 use crate::tool::{prepare_tool_cargo, SourceType};
7 use crate::{Compiler, Mode};
8 use std::path::PathBuf;
10 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
12 pub target: TargetSelection,
15 fn args(kind: Kind) -> Vec<String> {
17 Kind::Clippy => vec!["--".to_owned(), "--cap-lints".to_owned(), "warn".to_owned()],
22 fn cargo_subcommand(kind: Kind) -> &'static str {
24 Kind::Check => "check",
25 Kind::Clippy => "clippy",
33 const DEFAULT: bool = true;
35 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
36 run.all_krates("test")
39 fn make_run(run: RunConfig<'_>) {
40 run.builder.ensure(Std { target: run.target });
43 fn run(self, builder: &Builder<'_>) {
44 let target = self.target;
45 let compiler = builder.compiler(0, builder.config.build);
47 let mut cargo = builder.cargo(
52 cargo_subcommand(builder.kind),
54 std_cargo(builder, target, compiler.stage, &mut cargo);
56 builder.info(&format!("Checking std artifacts ({} -> {})", &compiler.host, target));
61 &libstd_stamp(builder, compiler, target),
66 let libdir = builder.sysroot_libdir(compiler, target);
67 let hostdir = builder.sysroot_libdir(compiler, compiler.host);
68 add_to_sysroot(&builder, &libdir, &hostdir, &libstd_stamp(builder, compiler, target));
70 // Then run cargo again, once we've put the rmeta files for the library
71 // crates into the sysroot. This is needed because e.g., core's tests
72 // depend on `libtest` -- Cargo presumes it will exist, but it doesn't
73 // since we initialize with an empty sysroot.
75 // Currently only the "libtest" tree of crates does this.
77 let mut cargo = builder.cargo(
82 cargo_subcommand(builder.kind),
84 std_cargo(builder, target, compiler.stage, &mut cargo);
85 cargo.arg("--all-targets");
87 // Explicitly pass -p for all dependencies krates -- this will force cargo
88 // to also check the tests/benches/examples for these crates, rather
89 // than just the leaf crate.
90 for krate in builder.in_tree_crates("test") {
91 cargo.arg("-p").arg(krate.name);
94 builder.info(&format!(
95 "Checking std test/bench/example targets ({} -> {})",
96 &compiler.host, target
102 &libstd_test_stamp(builder, compiler, target),
109 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
111 pub target: TargetSelection,
114 impl Step for Rustc {
116 const ONLY_HOSTS: bool = true;
117 const DEFAULT: bool = true;
119 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
120 run.all_krates("rustc-main")
123 fn make_run(run: RunConfig<'_>) {
124 run.builder.ensure(Rustc { target: run.target });
127 /// Builds the compiler.
129 /// This will build the compiler for a particular stage of the build using
130 /// the `compiler` targeting the `target` architecture. The artifacts
131 /// created will also be linked into the sysroot directory.
132 fn run(self, builder: &Builder<'_>) {
133 let compiler = builder.compiler(0, builder.config.build);
134 let target = self.target;
136 builder.ensure(Std { target });
138 let mut cargo = builder.cargo(
143 cargo_subcommand(builder.kind),
145 rustc_cargo(builder, &mut cargo, target);
146 cargo.arg("--all-targets");
148 // Explicitly pass -p for all compiler krates -- this will force cargo
149 // to also check the tests/benches/examples for these crates, rather
150 // than just the leaf crate.
151 for krate in builder.in_tree_crates("rustc-main") {
152 cargo.arg("-p").arg(krate.name);
155 builder.info(&format!("Checking compiler artifacts ({} -> {})", &compiler.host, target));
160 &librustc_stamp(builder, compiler, target),
165 let libdir = builder.sysroot_libdir(compiler, target);
166 let hostdir = builder.sysroot_libdir(compiler, compiler.host);
167 add_to_sysroot(&builder, &libdir, &hostdir, &librustc_stamp(builder, compiler, target));
171 macro_rules! tool_check_step {
172 ($name:ident, $path:expr, $source_type:expr) => {
173 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
175 pub target: TargetSelection,
178 impl Step for $name {
180 const ONLY_HOSTS: bool = true;
181 const DEFAULT: bool = true;
183 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
187 fn make_run(run: RunConfig<'_>) {
188 run.builder.ensure($name { target: run.target });
191 fn run(self, builder: &Builder<'_>) {
192 let compiler = builder.compiler(0, builder.config.build);
193 let target = self.target;
195 builder.ensure(Rustc { target });
197 let mut cargo = prepare_tool_cargo(
202 cargo_subcommand(builder.kind),
208 cargo.arg("--all-targets");
210 builder.info(&format!(
211 "Checking {} artifacts ({} -> {})",
212 stringify!($name).to_lowercase(),
213 &compiler.host.triple,
220 &stamp(builder, compiler, target),
225 let libdir = builder.sysroot_libdir(compiler, target);
226 let hostdir = builder.sysroot_libdir(compiler, compiler.host);
227 add_to_sysroot(&builder, &libdir, &hostdir, &stamp(builder, compiler, target));
229 /// Cargo's output path in a given stage, compiled by a particular
230 /// compiler for the specified target.
232 builder: &Builder<'_>,
234 target: TargetSelection,
237 .cargo_out(compiler, Mode::ToolRustc, target)
238 .join(format!(".{}-check.stamp", stringify!($name).to_lowercase()))
245 tool_check_step!(Rustdoc, "src/tools/rustdoc", SourceType::InTree);
246 // Clippy is a hybrid. It is an external tool, but uses a git subtree instead
247 // of a submodule. Since the SourceType only drives the deny-warnings
248 // behavior, treat it as in-tree so that any new warnings in clippy will be
250 tool_check_step!(Clippy, "src/tools/clippy", SourceType::InTree);
252 tool_check_step!(Bootstrap, "src/bootstrap", SourceType::InTree);
254 /// Cargo's output path for the standard library in a given stage, compiled
255 /// by a particular compiler for the specified target.
256 fn libstd_stamp(builder: &Builder<'_>, compiler: Compiler, target: TargetSelection) -> PathBuf {
257 builder.cargo_out(compiler, Mode::Std, target).join(".libstd-check.stamp")
260 /// Cargo's output path for the standard library in a given stage, compiled
261 /// by a particular compiler for the specified target.
262 fn libstd_test_stamp(
263 builder: &Builder<'_>,
265 target: TargetSelection,
267 builder.cargo_out(compiler, Mode::Std, target).join(".libstd-check-test.stamp")
270 /// Cargo's output path for librustc in a given stage, compiled by a particular
271 /// compiler for the specified target.
272 fn librustc_stamp(builder: &Builder<'_>, compiler: Compiler, target: TargetSelection) -> PathBuf {
273 builder.cargo_out(compiler, Mode::Rustc, target).join(".librustc-check.stamp")