]> git.lizzy.rs Git - rust.git/blob - src/bootstrap/check.rs
Fix typo in source-based-code-coverage.md
[rust.git] / src / bootstrap / check.rs
1 //! Implementation of compiling the compiler and standard library, in "check"-based modes.
2
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};
8 use crate::INTERNER;
9 use crate::{Compiler, Mode, Subcommand};
10 use std::path::PathBuf;
11
12 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
13 pub struct Std {
14     pub target: TargetSelection,
15 }
16
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)
21     }
22
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
27             "collapsible_if",
28             "type_complexity",
29             "missing_safety_doc", // almost 3K warnings
30             "too_many_arguments",
31             "needless_lifetimes", // people want to keep the lifetimes
32             "wrong_self_convention",
33         ];
34         let mut args = vec![];
35         if fix {
36             #[rustfmt::skip]
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",
43             ]));
44         }
45         args.extend(strings(&["--", "--cap-lints", "warn"]));
46         args.extend(ignored_lints.iter().map(|lint| format!("-Aclippy::{}", lint)));
47         args
48     } else {
49         vec![]
50     }
51 }
52
53 fn cargo_subcommand(kind: Kind) -> &'static str {
54     match kind {
55         Kind::Check => "check",
56         Kind::Clippy => "clippy",
57         Kind::Fix => "fix",
58         _ => unreachable!(),
59     }
60 }
61
62 impl Step for Std {
63     type Output = ();
64     const DEFAULT: bool = true;
65
66     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
67         run.all_krates("test")
68     }
69
70     fn make_run(run: RunConfig<'_>) {
71         run.builder.ensure(Std { target: run.target });
72     }
73
74     fn run(self, builder: &Builder<'_>) {
75         let target = self.target;
76         let compiler = builder.compiler(0, builder.config.build);
77
78         let mut cargo = builder.cargo(
79             compiler,
80             Mode::Std,
81             SourceType::InTree,
82             target,
83             cargo_subcommand(builder.kind),
84         );
85         std_cargo(builder, target, compiler.stage, &mut cargo);
86
87         builder.info(&format!("Checking std artifacts ({} -> {})", &compiler.host, target));
88         run_cargo(
89             builder,
90             cargo,
91             args(builder),
92             &libstd_stamp(builder, compiler, target),
93             vec![],
94             true,
95         );
96
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));
100
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.
105         //
106         // Currently only the "libtest" tree of crates does this.
107
108         if let Subcommand::Check { all_targets: true, .. } = builder.config.cmd {
109             let mut cargo = builder.cargo(
110                 compiler,
111                 Mode::Std,
112                 SourceType::InTree,
113                 target,
114                 cargo_subcommand(builder.kind),
115             );
116             std_cargo(builder, target, compiler.stage, &mut cargo);
117             cargo.arg("--all-targets");
118
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);
124             }
125
126             builder.info(&format!(
127                 "Checking std test/bench/example targets ({} -> {})",
128                 &compiler.host, target
129             ));
130             run_cargo(
131                 builder,
132                 cargo,
133                 args(builder),
134                 &libstd_test_stamp(builder, compiler, target),
135                 vec![],
136                 true,
137             );
138         }
139     }
140 }
141
142 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
143 pub struct Rustc {
144     pub target: TargetSelection,
145 }
146
147 impl Step for Rustc {
148     type Output = ();
149     const ONLY_HOSTS: bool = true;
150     const DEFAULT: bool = true;
151
152     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
153         run.all_krates("rustc-main")
154     }
155
156     fn make_run(run: RunConfig<'_>) {
157         run.builder.ensure(Rustc { target: run.target });
158     }
159
160     /// Builds the compiler.
161     ///
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;
168
169         builder.ensure(Std { target });
170
171         let mut cargo = builder.cargo(
172             compiler,
173             Mode::Rustc,
174             SourceType::InTree,
175             target,
176             cargo_subcommand(builder.kind),
177         );
178         rustc_cargo(builder, &mut cargo, target);
179         if let Subcommand::Check { all_targets: true, .. } = builder.config.cmd {
180             cargo.arg("--all-targets");
181         }
182
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);
188         }
189
190         builder.info(&format!("Checking compiler artifacts ({} -> {})", &compiler.host, target));
191         run_cargo(
192             builder,
193             cargo,
194             args(builder),
195             &librustc_stamp(builder, compiler, target),
196             vec![],
197             true,
198         );
199
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));
203     }
204 }
205
206 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
207 pub struct CodegenBackend {
208     pub target: TargetSelection,
209     pub backend: Interned<String>,
210 }
211
212 impl Step for CodegenBackend {
213     type Output = ();
214     const ONLY_HOSTS: bool = true;
215     const DEFAULT: bool = true;
216
217     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
218         run.paths(&["compiler/rustc_codegen_cranelift", "rustc_codegen_cranelift"])
219     }
220
221     fn make_run(run: RunConfig<'_>) {
222         for &backend in &[INTERNER.intern_str("cranelift")] {
223             run.builder.ensure(CodegenBackend { target: run.target, backend });
224         }
225     }
226
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;
231
232         builder.ensure(Rustc { target });
233
234         let mut cargo = builder.cargo(
235             compiler,
236             Mode::Codegen,
237             SourceType::Submodule,
238             target,
239             cargo_subcommand(builder.kind),
240         );
241         cargo
242             .arg("--manifest-path")
243             .arg(builder.src.join(format!("compiler/rustc_codegen_{}/Cargo.toml", backend)));
244         rustc_cargo_env(builder, &mut cargo, target);
245
246         builder.info(&format!(
247             "Checking {} artifacts ({} -> {})",
248             backend, &compiler.host.triple, target.triple
249         ));
250
251         run_cargo(
252             builder,
253             cargo,
254             args(builder),
255             &codegen_backend_stamp(builder, compiler, target, backend),
256             vec![],
257             true,
258         );
259     }
260 }
261
262 macro_rules! tool_check_step {
263     ($name:ident, $path:expr, $source_type:expr) => {
264         #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
265         pub struct $name {
266             pub target: TargetSelection,
267         }
268
269         impl Step for $name {
270             type Output = ();
271             const ONLY_HOSTS: bool = true;
272             const DEFAULT: bool = true;
273
274             fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
275                 run.path($path)
276             }
277
278             fn make_run(run: RunConfig<'_>) {
279                 run.builder.ensure($name { target: run.target });
280             }
281
282             fn run(self, builder: &Builder<'_>) {
283                 let compiler = builder.compiler(0, builder.config.build);
284                 let target = self.target;
285
286                 builder.ensure(Rustc { target });
287
288                 let mut cargo = prepare_tool_cargo(
289                     builder,
290                     compiler,
291                     Mode::ToolRustc,
292                     target,
293                     cargo_subcommand(builder.kind),
294                     $path,
295                     $source_type,
296                     &[],
297                 );
298
299                 if let Subcommand::Check { all_targets: true, .. } = builder.config.cmd {
300                     cargo.arg("--all-targets");
301                 }
302
303                 builder.info(&format!(
304                     "Checking {} artifacts ({} -> {})",
305                     stringify!($name).to_lowercase(),
306                     &compiler.host.triple,
307                     target.triple
308                 ));
309                 run_cargo(
310                     builder,
311                     cargo,
312                     args(builder),
313                     &stamp(builder, compiler, target),
314                     vec![],
315                     true,
316                 );
317
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));
321
322                 /// Cargo's output path in a given stage, compiled by a particular
323                 /// compiler for the specified target.
324                 fn stamp(
325                     builder: &Builder<'_>,
326                     compiler: Compiler,
327                     target: TargetSelection,
328                 ) -> PathBuf {
329                     builder
330                         .cargo_out(compiler, Mode::ToolRustc, target)
331                         .join(format!(".{}-check.stamp", stringify!($name).to_lowercase()))
332                 }
333             }
334         }
335     };
336 }
337
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
342 // rejected.
343 tool_check_step!(Clippy, "src/tools/clippy", SourceType::InTree);
344
345 tool_check_step!(Bootstrap, "src/bootstrap", SourceType::InTree);
346
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")
351 }
352
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<'_>,
357     compiler: Compiler,
358     target: TargetSelection,
359 ) -> PathBuf {
360     builder.cargo_out(compiler, Mode::Std, target).join(".libstd-check-test.stamp")
361 }
362
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")
367 }
368
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<'_>,
373     compiler: Compiler,
374     target: TargetSelection,
375     backend: Interned<String>,
376 ) -> PathBuf {
377     builder
378         .cargo_out(compiler, Mode::Codegen, target)
379         .join(format!(".librustc_codegen_{}-check.stamp", backend))
380 }