]> git.lizzy.rs Git - rust.git/blob - src/bootstrap/check.rs
Rollup merge of #78084 - GuillaumeGomez:improve-mobile-display, r=jyn514,Nemo157
[rust.git] / src / bootstrap / check.rs
1 //! Implementation of compiling the compiler and standard library, in "check"-based modes.
2
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};
6 use crate::{
7     builder::{Builder, Kind, RunConfig, ShouldRun, Step},
8     Subcommand,
9 };
10 use crate::{Compiler, Mode};
11 use std::path::PathBuf;
12
13 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
14 pub struct Std {
15     pub target: TargetSelection,
16 }
17
18 fn args(kind: Kind) -> Vec<String> {
19     match kind {
20         Kind::Clippy => vec!["--".to_owned(), "--cap-lints".to_owned(), "warn".to_owned()],
21         _ => Vec::new(),
22     }
23 }
24
25 fn cargo_subcommand(kind: Kind) -> &'static str {
26     match kind {
27         Kind::Check => "check",
28         Kind::Clippy => "clippy",
29         Kind::Fix => "fix",
30         _ => unreachable!(),
31     }
32 }
33
34 impl Step for Std {
35     type Output = ();
36     const DEFAULT: bool = true;
37
38     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
39         run.all_krates("test")
40     }
41
42     fn make_run(run: RunConfig<'_>) {
43         run.builder.ensure(Std { target: run.target });
44     }
45
46     fn run(self, builder: &Builder<'_>) {
47         let target = self.target;
48         let compiler = builder.compiler(0, builder.config.build);
49
50         let mut cargo = builder.cargo(
51             compiler,
52             Mode::Std,
53             SourceType::InTree,
54             target,
55             cargo_subcommand(builder.kind),
56         );
57         std_cargo(builder, target, compiler.stage, &mut cargo);
58
59         builder.info(&format!("Checking std artifacts ({} -> {})", &compiler.host, target));
60         run_cargo(
61             builder,
62             cargo,
63             args(builder.kind),
64             &libstd_stamp(builder, compiler, target),
65             vec![],
66             true,
67         );
68
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));
72
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.
77         //
78         // Currently only the "libtest" tree of crates does this.
79
80         if let Subcommand::Check { all_targets: true, .. } = builder.config.cmd {
81             let mut cargo = builder.cargo(
82                 compiler,
83                 Mode::Std,
84                 SourceType::InTree,
85                 target,
86                 cargo_subcommand(builder.kind),
87             );
88             std_cargo(builder, target, compiler.stage, &mut cargo);
89             cargo.arg("--all-targets");
90
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);
96             }
97
98             builder.info(&format!(
99                 "Checking std test/bench/example targets ({} -> {})",
100                 &compiler.host, target
101             ));
102             run_cargo(
103                 builder,
104                 cargo,
105                 args(builder.kind),
106                 &libstd_test_stamp(builder, compiler, target),
107                 vec![],
108                 true,
109             );
110         }
111     }
112 }
113
114 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
115 pub struct Rustc {
116     pub target: TargetSelection,
117 }
118
119 impl Step for Rustc {
120     type Output = ();
121     const ONLY_HOSTS: bool = true;
122     const DEFAULT: bool = true;
123
124     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
125         run.all_krates("rustc-main")
126     }
127
128     fn make_run(run: RunConfig<'_>) {
129         run.builder.ensure(Rustc { target: run.target });
130     }
131
132     /// Builds the compiler.
133     ///
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;
140
141         builder.ensure(Std { target });
142
143         let mut cargo = builder.cargo(
144             compiler,
145             Mode::Rustc,
146             SourceType::InTree,
147             target,
148             cargo_subcommand(builder.kind),
149         );
150         rustc_cargo(builder, &mut cargo, target);
151         if let Subcommand::Check { all_targets: true, .. } = builder.config.cmd {
152             cargo.arg("--all-targets");
153         }
154
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);
160         }
161
162         builder.info(&format!("Checking compiler artifacts ({} -> {})", &compiler.host, target));
163         run_cargo(
164             builder,
165             cargo,
166             args(builder.kind),
167             &librustc_stamp(builder, compiler, target),
168             vec![],
169             true,
170         );
171
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));
175     }
176 }
177
178 macro_rules! tool_check_step {
179     ($name:ident, $path:expr, $source_type:expr) => {
180         #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
181         pub struct $name {
182             pub target: TargetSelection,
183         }
184
185         impl Step for $name {
186             type Output = ();
187             const ONLY_HOSTS: bool = true;
188             const DEFAULT: bool = true;
189
190             fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
191                 run.path($path)
192             }
193
194             fn make_run(run: RunConfig<'_>) {
195                 run.builder.ensure($name { target: run.target });
196             }
197
198             fn run(self, builder: &Builder<'_>) {
199                 let compiler = builder.compiler(0, builder.config.build);
200                 let target = self.target;
201
202                 builder.ensure(Rustc { target });
203
204                 let mut cargo = prepare_tool_cargo(
205                     builder,
206                     compiler,
207                     Mode::ToolRustc,
208                     target,
209                     cargo_subcommand(builder.kind),
210                     $path,
211                     $source_type,
212                     &[],
213                 );
214
215                 if let Subcommand::Check { all_targets: true, .. } = builder.config.cmd {
216                     cargo.arg("--all-targets");
217                 }
218
219                 builder.info(&format!(
220                     "Checking {} artifacts ({} -> {})",
221                     stringify!($name).to_lowercase(),
222                     &compiler.host.triple,
223                     target.triple
224                 ));
225                 run_cargo(
226                     builder,
227                     cargo,
228                     args(builder.kind),
229                     &stamp(builder, compiler, target),
230                     vec![],
231                     true,
232                 );
233
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));
237
238                 /// Cargo's output path in a given stage, compiled by a particular
239                 /// compiler for the specified target.
240                 fn stamp(
241                     builder: &Builder<'_>,
242                     compiler: Compiler,
243                     target: TargetSelection,
244                 ) -> PathBuf {
245                     builder
246                         .cargo_out(compiler, Mode::ToolRustc, target)
247                         .join(format!(".{}-check.stamp", stringify!($name).to_lowercase()))
248                 }
249             }
250         }
251     };
252 }
253
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
258 // rejected.
259 tool_check_step!(Clippy, "src/tools/clippy", SourceType::InTree);
260
261 tool_check_step!(Bootstrap, "src/bootstrap", SourceType::InTree);
262
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")
267 }
268
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<'_>,
273     compiler: Compiler,
274     target: TargetSelection,
275 ) -> PathBuf {
276     builder.cargo_out(compiler, Mode::Std, target).join(".libstd-check-test.stamp")
277 }
278
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")
283 }