1 //! Implementation of compiling the compiler and standard library, in "check"-based modes.
3 use crate::cache::Interned;
4 use crate::compile::{add_to_sysroot, run_cargo, rustc_cargo, rustc_cargo_env, std_cargo};
5 use crate::config::TargetSelection;
6 use crate::tool::{prepare_tool_cargo, SourceType};
9 builder::{Builder, Kind, RunConfig, ShouldRun, Step},
12 use crate::{Compiler, Mode};
13 use std::path::PathBuf;
15 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
17 pub target: TargetSelection,
20 fn args(kind: Kind) -> Vec<String> {
22 Kind::Clippy => vec!["--".to_owned(), "--cap-lints".to_owned(), "warn".to_owned()],
27 fn cargo_subcommand(kind: Kind) -> &'static str {
29 Kind::Check => "check",
30 Kind::Clippy => "clippy",
38 const DEFAULT: bool = true;
40 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
41 run.all_krates("test")
44 fn make_run(run: RunConfig<'_>) {
45 run.builder.ensure(Std { target: run.target });
48 fn run(self, builder: &Builder<'_>) {
49 let target = self.target;
50 let compiler = builder.compiler(0, builder.config.build);
52 let mut cargo = builder.cargo(
57 cargo_subcommand(builder.kind),
59 std_cargo(builder, target, compiler.stage, &mut cargo);
61 builder.info(&format!("Checking std artifacts ({} -> {})", &compiler.host, target));
66 &libstd_stamp(builder, compiler, target),
71 let libdir = builder.sysroot_libdir(compiler, target);
72 let hostdir = builder.sysroot_libdir(compiler, compiler.host);
73 add_to_sysroot(&builder, &libdir, &hostdir, &libstd_stamp(builder, compiler, target));
75 // Then run cargo again, once we've put the rmeta files for the library
76 // crates into the sysroot. This is needed because e.g., core's tests
77 // depend on `libtest` -- Cargo presumes it will exist, but it doesn't
78 // since we initialize with an empty sysroot.
80 // Currently only the "libtest" tree of crates does this.
82 if let Subcommand::Check { all_targets: true, .. } = builder.config.cmd {
83 let mut cargo = builder.cargo(
88 cargo_subcommand(builder.kind),
90 std_cargo(builder, target, compiler.stage, &mut cargo);
91 cargo.arg("--all-targets");
93 // Explicitly pass -p for all dependencies krates -- this will force cargo
94 // to also check the tests/benches/examples for these crates, rather
95 // than just the leaf crate.
96 for krate in builder.in_tree_crates("test") {
97 cargo.arg("-p").arg(krate.name);
100 builder.info(&format!(
101 "Checking std test/bench/example targets ({} -> {})",
102 &compiler.host, target
108 &libstd_test_stamp(builder, compiler, target),
116 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
118 pub target: TargetSelection,
121 impl Step for Rustc {
123 const ONLY_HOSTS: bool = true;
124 const DEFAULT: bool = true;
126 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
127 run.all_krates("rustc-main")
130 fn make_run(run: RunConfig<'_>) {
131 run.builder.ensure(Rustc { target: run.target });
134 /// Builds the compiler.
136 /// This will build the compiler for a particular stage of the build using
137 /// the `compiler` targeting the `target` architecture. The artifacts
138 /// created will also be linked into the sysroot directory.
139 fn run(self, builder: &Builder<'_>) {
140 let compiler = builder.compiler(0, builder.config.build);
141 let target = self.target;
143 builder.ensure(Std { target });
145 let mut cargo = builder.cargo(
150 cargo_subcommand(builder.kind),
152 rustc_cargo(builder, &mut cargo, target);
153 if let Subcommand::Check { all_targets: true, .. } = builder.config.cmd {
154 cargo.arg("--all-targets");
157 // Explicitly pass -p for all compiler krates -- this will force cargo
158 // to also check the tests/benches/examples for these crates, rather
159 // than just the leaf crate.
160 for krate in builder.in_tree_crates("rustc-main") {
161 cargo.arg("-p").arg(krate.name);
164 builder.info(&format!("Checking compiler artifacts ({} -> {})", &compiler.host, target));
169 &librustc_stamp(builder, compiler, target),
174 let libdir = builder.sysroot_libdir(compiler, target);
175 let hostdir = builder.sysroot_libdir(compiler, compiler.host);
176 add_to_sysroot(&builder, &libdir, &hostdir, &librustc_stamp(builder, compiler, target));
180 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
181 pub struct CodegenBackend {
182 pub target: TargetSelection,
183 pub backend: Interned<String>,
186 impl Step for CodegenBackend {
188 const ONLY_HOSTS: bool = true;
189 const DEFAULT: bool = true;
191 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
192 run.paths(&["compiler/rustc_codegen_cranelift", "rustc_codegen_cranelift"])
195 fn make_run(run: RunConfig<'_>) {
196 for &backend in &[INTERNER.intern_str("cranelift")] {
197 run.builder.ensure(CodegenBackend { target: run.target, backend });
201 fn run(self, builder: &Builder<'_>) {
202 let compiler = builder.compiler(0, builder.config.build);
203 let target = self.target;
204 let backend = self.backend;
206 builder.ensure(Rustc { target });
208 let mut cargo = builder.cargo(
211 SourceType::Submodule,
213 cargo_subcommand(builder.kind),
216 .arg("--manifest-path")
217 .arg(builder.src.join(format!("compiler/rustc_codegen_{}/Cargo.toml", backend)));
218 rustc_cargo_env(builder, &mut cargo, target);
224 &codegen_backend_stamp(builder, compiler, target, backend),
231 macro_rules! tool_check_step {
232 ($name:ident, $path:expr, $source_type:expr) => {
233 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
235 pub target: TargetSelection,
238 impl Step for $name {
240 const ONLY_HOSTS: bool = true;
241 const DEFAULT: bool = true;
243 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
247 fn make_run(run: RunConfig<'_>) {
248 run.builder.ensure($name { target: run.target });
251 fn run(self, builder: &Builder<'_>) {
252 let compiler = builder.compiler(0, builder.config.build);
253 let target = self.target;
255 builder.ensure(Rustc { target });
257 let mut cargo = prepare_tool_cargo(
262 cargo_subcommand(builder.kind),
268 if let Subcommand::Check { all_targets: true, .. } = builder.config.cmd {
269 cargo.arg("--all-targets");
272 builder.info(&format!(
273 "Checking {} artifacts ({} -> {})",
274 stringify!($name).to_lowercase(),
275 &compiler.host.triple,
282 &stamp(builder, compiler, target),
287 let libdir = builder.sysroot_libdir(compiler, target);
288 let hostdir = builder.sysroot_libdir(compiler, compiler.host);
289 add_to_sysroot(&builder, &libdir, &hostdir, &stamp(builder, compiler, target));
291 /// Cargo's output path in a given stage, compiled by a particular
292 /// compiler for the specified target.
294 builder: &Builder<'_>,
296 target: TargetSelection,
299 .cargo_out(compiler, Mode::ToolRustc, target)
300 .join(format!(".{}-check.stamp", stringify!($name).to_lowercase()))
307 tool_check_step!(Rustdoc, "src/tools/rustdoc", SourceType::InTree);
308 // Clippy is a hybrid. It is an external tool, but uses a git subtree instead
309 // of a submodule. Since the SourceType only drives the deny-warnings
310 // behavior, treat it as in-tree so that any new warnings in clippy will be
312 tool_check_step!(Clippy, "src/tools/clippy", SourceType::InTree);
314 tool_check_step!(Bootstrap, "src/bootstrap", SourceType::InTree);
316 /// Cargo's output path for the standard library in a given stage, compiled
317 /// by a particular compiler for the specified target.
318 fn libstd_stamp(builder: &Builder<'_>, compiler: Compiler, target: TargetSelection) -> PathBuf {
319 builder.cargo_out(compiler, Mode::Std, target).join(".libstd-check.stamp")
322 /// Cargo's output path for the standard library in a given stage, compiled
323 /// by a particular compiler for the specified target.
324 fn libstd_test_stamp(
325 builder: &Builder<'_>,
327 target: TargetSelection,
329 builder.cargo_out(compiler, Mode::Std, target).join(".libstd-check-test.stamp")
332 /// Cargo's output path for librustc in a given stage, compiled by a particular
333 /// compiler for the specified target.
334 fn librustc_stamp(builder: &Builder<'_>, compiler: Compiler, target: TargetSelection) -> PathBuf {
335 builder.cargo_out(compiler, Mode::Rustc, target).join(".librustc-check.stamp")
338 /// Cargo's output path for librustc_codegen_llvm in a given stage, compiled by a particular
339 /// compiler for the specified target and backend.
340 fn codegen_backend_stamp(
341 builder: &Builder<'_>,
343 target: TargetSelection,
344 backend: Interned<String>,
347 .cargo_out(compiler, Mode::Codegen, target)
348 .join(format!(".librustc_codegen_{}-check.stamp", backend))