]> git.lizzy.rs Git - rust.git/blob - src/bootstrap/check.rs
Add support for rustc-env and unset-rustc-env for aux-builds
[rust.git] / src / bootstrap / check.rs
1 //! Implementation of compiling the compiler and standard library, in "check"-based modes.
2
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};
7 use crate::INTERNER;
8 use crate::{
9     builder::{Builder, Kind, RunConfig, ShouldRun, Step},
10     Subcommand,
11 };
12 use crate::{Compiler, Mode};
13 use std::path::PathBuf;
14
15 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
16 pub struct Std {
17     pub target: TargetSelection,
18 }
19
20 fn args(kind: Kind) -> Vec<String> {
21     match kind {
22         Kind::Clippy => vec!["--".to_owned(), "--cap-lints".to_owned(), "warn".to_owned()],
23         _ => Vec::new(),
24     }
25 }
26
27 fn cargo_subcommand(kind: Kind) -> &'static str {
28     match kind {
29         Kind::Check => "check",
30         Kind::Clippy => "clippy",
31         Kind::Fix => "fix",
32         _ => unreachable!(),
33     }
34 }
35
36 impl Step for Std {
37     type Output = ();
38     const DEFAULT: bool = true;
39
40     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
41         run.all_krates("test")
42     }
43
44     fn make_run(run: RunConfig<'_>) {
45         run.builder.ensure(Std { target: run.target });
46     }
47
48     fn run(self, builder: &Builder<'_>) {
49         let target = self.target;
50         let compiler = builder.compiler(0, builder.config.build);
51
52         let mut cargo = builder.cargo(
53             compiler,
54             Mode::Std,
55             SourceType::InTree,
56             target,
57             cargo_subcommand(builder.kind),
58         );
59         std_cargo(builder, target, compiler.stage, &mut cargo);
60
61         builder.info(&format!("Checking std artifacts ({} -> {})", &compiler.host, target));
62         run_cargo(
63             builder,
64             cargo,
65             args(builder.kind),
66             &libstd_stamp(builder, compiler, target),
67             vec![],
68             true,
69         );
70
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));
74
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.
79         //
80         // Currently only the "libtest" tree of crates does this.
81
82         if let Subcommand::Check { all_targets: true, .. } = builder.config.cmd {
83             let mut cargo = builder.cargo(
84                 compiler,
85                 Mode::Std,
86                 SourceType::InTree,
87                 target,
88                 cargo_subcommand(builder.kind),
89             );
90             std_cargo(builder, target, compiler.stage, &mut cargo);
91             cargo.arg("--all-targets");
92
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);
98             }
99
100             builder.info(&format!(
101                 "Checking std test/bench/example targets ({} -> {})",
102                 &compiler.host, target
103             ));
104             run_cargo(
105                 builder,
106                 cargo,
107                 args(builder.kind),
108                 &libstd_test_stamp(builder, compiler, target),
109                 vec![],
110                 true,
111             );
112         }
113     }
114 }
115
116 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
117 pub struct Rustc {
118     pub target: TargetSelection,
119 }
120
121 impl Step for Rustc {
122     type Output = ();
123     const ONLY_HOSTS: bool = true;
124     const DEFAULT: bool = true;
125
126     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
127         run.all_krates("rustc-main")
128     }
129
130     fn make_run(run: RunConfig<'_>) {
131         run.builder.ensure(Rustc { target: run.target });
132     }
133
134     /// Builds the compiler.
135     ///
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;
142
143         builder.ensure(Std { target });
144
145         let mut cargo = builder.cargo(
146             compiler,
147             Mode::Rustc,
148             SourceType::InTree,
149             target,
150             cargo_subcommand(builder.kind),
151         );
152         rustc_cargo(builder, &mut cargo, target);
153         if let Subcommand::Check { all_targets: true, .. } = builder.config.cmd {
154             cargo.arg("--all-targets");
155         }
156
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);
162         }
163
164         builder.info(&format!("Checking compiler artifacts ({} -> {})", &compiler.host, target));
165         run_cargo(
166             builder,
167             cargo,
168             args(builder.kind),
169             &librustc_stamp(builder, compiler, target),
170             vec![],
171             true,
172         );
173
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));
177     }
178 }
179
180 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
181 pub struct CodegenBackend {
182     pub target: TargetSelection,
183     pub backend: Interned<String>,
184 }
185
186 impl Step for CodegenBackend {
187     type Output = ();
188     const ONLY_HOSTS: bool = true;
189     const DEFAULT: bool = true;
190
191     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
192         run.paths(&["compiler/rustc_codegen_cranelift", "rustc_codegen_cranelift"])
193     }
194
195     fn make_run(run: RunConfig<'_>) {
196         for &backend in &[INTERNER.intern_str("cranelift")] {
197             run.builder.ensure(CodegenBackend { target: run.target, backend });
198         }
199     }
200
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;
205
206         builder.ensure(Rustc { target });
207
208         let mut cargo = builder.cargo(
209             compiler,
210             Mode::Codegen,
211             SourceType::Submodule,
212             target,
213             cargo_subcommand(builder.kind),
214         );
215         cargo
216             .arg("--manifest-path")
217             .arg(builder.src.join(format!("compiler/rustc_codegen_{}/Cargo.toml", backend)));
218         rustc_cargo_env(builder, &mut cargo, target);
219
220         run_cargo(
221             builder,
222             cargo,
223             args(builder.kind),
224             &codegen_backend_stamp(builder, compiler, target, backend),
225             vec![],
226             true,
227         );
228     }
229 }
230
231 macro_rules! tool_check_step {
232     ($name:ident, $path:expr, $source_type:expr) => {
233         #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
234         pub struct $name {
235             pub target: TargetSelection,
236         }
237
238         impl Step for $name {
239             type Output = ();
240             const ONLY_HOSTS: bool = true;
241             const DEFAULT: bool = true;
242
243             fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
244                 run.path($path)
245             }
246
247             fn make_run(run: RunConfig<'_>) {
248                 run.builder.ensure($name { target: run.target });
249             }
250
251             fn run(self, builder: &Builder<'_>) {
252                 let compiler = builder.compiler(0, builder.config.build);
253                 let target = self.target;
254
255                 builder.ensure(Rustc { target });
256
257                 let mut cargo = prepare_tool_cargo(
258                     builder,
259                     compiler,
260                     Mode::ToolRustc,
261                     target,
262                     cargo_subcommand(builder.kind),
263                     $path,
264                     $source_type,
265                     &[],
266                 );
267
268                 if let Subcommand::Check { all_targets: true, .. } = builder.config.cmd {
269                     cargo.arg("--all-targets");
270                 }
271
272                 builder.info(&format!(
273                     "Checking {} artifacts ({} -> {})",
274                     stringify!($name).to_lowercase(),
275                     &compiler.host.triple,
276                     target.triple
277                 ));
278                 run_cargo(
279                     builder,
280                     cargo,
281                     args(builder.kind),
282                     &stamp(builder, compiler, target),
283                     vec![],
284                     true,
285                 );
286
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));
290
291                 /// Cargo's output path in a given stage, compiled by a particular
292                 /// compiler for the specified target.
293                 fn stamp(
294                     builder: &Builder<'_>,
295                     compiler: Compiler,
296                     target: TargetSelection,
297                 ) -> PathBuf {
298                     builder
299                         .cargo_out(compiler, Mode::ToolRustc, target)
300                         .join(format!(".{}-check.stamp", stringify!($name).to_lowercase()))
301                 }
302             }
303         }
304     };
305 }
306
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
311 // rejected.
312 tool_check_step!(Clippy, "src/tools/clippy", SourceType::InTree);
313
314 tool_check_step!(Bootstrap, "src/bootstrap", SourceType::InTree);
315
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")
320 }
321
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<'_>,
326     compiler: Compiler,
327     target: TargetSelection,
328 ) -> PathBuf {
329     builder.cargo_out(compiler, Mode::Std, target).join(".libstd-check-test.stamp")
330 }
331
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")
336 }
337
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<'_>,
342     compiler: Compiler,
343     target: TargetSelection,
344     backend: Interned<String>,
345 ) -> PathBuf {
346     builder
347         .cargo_out(compiler, Mode::Codegen, target)
348         .join(format!(".librustc_codegen_{}-check.stamp", backend))
349 }