1 //! Implementation of compiling the compiler and standard library, in "check"-based modes.
3 use crate::compile::{add_to_sysroot, run_cargo, rustc_cargo, std_cargo};
4 use crate::config::TargetSelection;
5 use crate::tool::{prepare_tool_cargo, SourceType};
7 builder::{Builder, Kind, RunConfig, ShouldRun, Step},
10 use crate::{Compiler, Mode};
11 use std::path::PathBuf;
13 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
15 pub target: TargetSelection,
18 fn args(kind: Kind) -> Vec<String> {
20 Kind::Clippy => vec!["--".to_owned(), "--cap-lints".to_owned(), "warn".to_owned()],
25 fn cargo_subcommand(kind: Kind) -> &'static str {
27 Kind::Check => "check",
28 Kind::Clippy => "clippy",
36 const DEFAULT: bool = true;
38 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
39 run.all_krates("test")
42 fn make_run(run: RunConfig<'_>) {
43 run.builder.ensure(Std { target: run.target });
46 fn run(self, builder: &Builder<'_>) {
47 let target = self.target;
48 let compiler = builder.compiler(0, builder.config.build);
50 let mut cargo = builder.cargo(
55 cargo_subcommand(builder.kind),
57 std_cargo(builder, target, compiler.stage, &mut cargo);
59 builder.info(&format!("Checking std artifacts ({} -> {})", &compiler.host, target));
64 &libstd_stamp(builder, compiler, target),
69 let libdir = builder.sysroot_libdir(compiler, target);
70 let hostdir = builder.sysroot_libdir(compiler, compiler.host);
71 add_to_sysroot(&builder, &libdir, &hostdir, &libstd_stamp(builder, compiler, target));
73 // Then run cargo again, once we've put the rmeta files for the library
74 // crates into the sysroot. This is needed because e.g., core's tests
75 // depend on `libtest` -- Cargo presumes it will exist, but it doesn't
76 // since we initialize with an empty sysroot.
78 // Currently only the "libtest" tree of crates does this.
80 if let Subcommand::Check { all_targets: true, .. } = builder.config.cmd {
81 let mut cargo = builder.cargo(
86 cargo_subcommand(builder.kind),
88 std_cargo(builder, target, compiler.stage, &mut cargo);
89 cargo.arg("--all-targets");
91 // Explicitly pass -p for all dependencies krates -- this will force cargo
92 // to also check the tests/benches/examples for these crates, rather
93 // than just the leaf crate.
94 for krate in builder.in_tree_crates("test") {
95 cargo.arg("-p").arg(krate.name);
98 builder.info(&format!(
99 "Checking std test/bench/example targets ({} -> {})",
100 &compiler.host, target
106 &libstd_test_stamp(builder, compiler, target),
114 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
116 pub target: TargetSelection,
119 impl Step for Rustc {
121 const ONLY_HOSTS: bool = true;
122 const DEFAULT: bool = true;
124 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
125 run.all_krates("rustc-main")
128 fn make_run(run: RunConfig<'_>) {
129 run.builder.ensure(Rustc { target: run.target });
132 /// Builds the compiler.
134 /// This will build the compiler for a particular stage of the build using
135 /// the `compiler` targeting the `target` architecture. The artifacts
136 /// created will also be linked into the sysroot directory.
137 fn run(self, builder: &Builder<'_>) {
138 let compiler = builder.compiler(0, builder.config.build);
139 let target = self.target;
141 builder.ensure(Std { target });
143 let mut cargo = builder.cargo(
148 cargo_subcommand(builder.kind),
150 rustc_cargo(builder, &mut cargo, target);
151 if let Subcommand::Check { all_targets: true, .. } = builder.config.cmd {
152 cargo.arg("--all-targets");
155 // Explicitly pass -p for all compiler krates -- this will force cargo
156 // to also check the tests/benches/examples for these crates, rather
157 // than just the leaf crate.
158 for krate in builder.in_tree_crates("rustc-main") {
159 cargo.arg("-p").arg(krate.name);
162 builder.info(&format!("Checking compiler artifacts ({} -> {})", &compiler.host, target));
167 &librustc_stamp(builder, compiler, target),
172 let libdir = builder.sysroot_libdir(compiler, target);
173 let hostdir = builder.sysroot_libdir(compiler, compiler.host);
174 add_to_sysroot(&builder, &libdir, &hostdir, &librustc_stamp(builder, compiler, target));
178 macro_rules! tool_check_step {
179 ($name:ident, $path:expr, $source_type:expr) => {
180 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
182 pub target: TargetSelection,
185 impl Step for $name {
187 const ONLY_HOSTS: bool = true;
188 const DEFAULT: bool = true;
190 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
194 fn make_run(run: RunConfig<'_>) {
195 run.builder.ensure($name { target: run.target });
198 fn run(self, builder: &Builder<'_>) {
199 let compiler = builder.compiler(0, builder.config.build);
200 let target = self.target;
202 builder.ensure(Rustc { target });
204 let mut cargo = prepare_tool_cargo(
209 cargo_subcommand(builder.kind),
215 if let Subcommand::Check { all_targets: true, .. } = builder.config.cmd {
216 cargo.arg("--all-targets");
219 builder.info(&format!(
220 "Checking {} artifacts ({} -> {})",
221 stringify!($name).to_lowercase(),
222 &compiler.host.triple,
229 &stamp(builder, compiler, target),
234 let libdir = builder.sysroot_libdir(compiler, target);
235 let hostdir = builder.sysroot_libdir(compiler, compiler.host);
236 add_to_sysroot(&builder, &libdir, &hostdir, &stamp(builder, compiler, target));
238 /// Cargo's output path in a given stage, compiled by a particular
239 /// compiler for the specified target.
241 builder: &Builder<'_>,
243 target: TargetSelection,
246 .cargo_out(compiler, Mode::ToolRustc, target)
247 .join(format!(".{}-check.stamp", stringify!($name).to_lowercase()))
254 tool_check_step!(Rustdoc, "src/tools/rustdoc", SourceType::InTree);
255 // Clippy is a hybrid. It is an external tool, but uses a git subtree instead
256 // of a submodule. Since the SourceType only drives the deny-warnings
257 // behavior, treat it as in-tree so that any new warnings in clippy will be
259 tool_check_step!(Clippy, "src/tools/clippy", SourceType::InTree);
261 tool_check_step!(Bootstrap, "src/bootstrap", SourceType::InTree);
263 /// Cargo's output path for the standard library in a given stage, compiled
264 /// by a particular compiler for the specified target.
265 fn libstd_stamp(builder: &Builder<'_>, compiler: Compiler, target: TargetSelection) -> PathBuf {
266 builder.cargo_out(compiler, Mode::Std, target).join(".libstd-check.stamp")
269 /// Cargo's output path for the standard library in a given stage, compiled
270 /// by a particular compiler for the specified target.
271 fn libstd_test_stamp(
272 builder: &Builder<'_>,
274 target: TargetSelection,
276 builder.cargo_out(compiler, Mode::Std, target).join(".libstd-check-test.stamp")
279 /// Cargo's output path for librustc in a given stage, compiled by a particular
280 /// compiler for the specified target.
281 fn librustc_stamp(builder: &Builder<'_>, compiler: Compiler, target: TargetSelection) -> PathBuf {
282 builder.cargo_out(compiler, Mode::Rustc, target).join(".librustc-check.stamp")