]> git.proxmox.com Git - rustc.git/blame - src/bootstrap/check.rs
New upstream version 1.54.0+dfsg1
[rustc.git] / src / bootstrap / check.rs
CommitLineData
dc9dc135 1//! Implementation of compiling the compiler and standard library, in "check"-based modes.
54a0048b 2
dfeec247 3use crate::builder::{Builder, Kind, RunConfig, ShouldRun, Step};
29967ef6
XL
4use crate::cache::Interned;
5use crate::compile::{add_to_sysroot, run_cargo, rustc_cargo, rustc_cargo_env, std_cargo};
3dfed10e 6use crate::config::TargetSelection;
0731742a 7use crate::tool::{prepare_tool_cargo, SourceType};
29967ef6
XL
8use crate::INTERNER;
9use crate::{Compiler, Mode, Subcommand};
2c00a5a8 10use std::path::PathBuf;
7cac9316 11
3b2f2976 12#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
2c00a5a8 13pub struct Std {
3dfed10e 14 pub target: TargetSelection,
3b2f2976
XL
15}
16
29967ef6
XL
17/// Returns args for the subcommand itself (not for cargo)
18fn 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 {
5869c6ff
XL
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 ];
29967ef6
XL
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"]));
5869c6ff 46 args.extend(ignored_lints.iter().map(|lint| format!("-Aclippy::{}", lint)));
29967ef6
XL
47 args
48 } else {
49 vec![]
dc9dc135
XL
50 }
51}
52
53fn cargo_subcommand(kind: Kind) -> &'static str {
54 match kind {
55 Kind::Check => "check",
56 Kind::Clippy => "clippy",
57 Kind::Fix => "fix",
dfeec247 58 _ => unreachable!(),
dc9dc135
XL
59 }
60}
61
2c00a5a8 62impl Step for Std {
3b2f2976 63 type Output = ();
3b2f2976
XL
64 const DEFAULT: bool = true;
65
9fa01778 66 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
e1599b0c 67 run.all_krates("test")
a7813a04
XL
68 }
69
9fa01778 70 fn make_run(run: RunConfig<'_>) {
dfeec247 71 run.builder.ensure(Std { target: run.target });
a7813a04 72 }
a7813a04 73
9fa01778 74 fn run(self, builder: &Builder<'_>) {
3b2f2976 75 let target = self.target;
5869c6ff 76 let compiler = builder.compiler(builder.top_stage, builder.config.build);
83c7162d 77
f035d41b
XL
78 let mut cargo = builder.cargo(
79 compiler,
80 Mode::Std,
81 SourceType::InTree,
82 target,
83 cargo_subcommand(builder.kind),
84 );
f9f354fc 85 std_cargo(builder, target, compiler.stage, &mut cargo);
0531ce1d 86
5869c6ff
XL
87 builder.info(&format!(
88 "Checking stage{} std artifacts ({} -> {})",
89 builder.top_stage, &compiler.host, target
90 ));
dfeec247
XL
91 run_cargo(
92 builder,
93 cargo,
29967ef6 94 args(builder),
dfeec247
XL
95 &libstd_stamp(builder, compiler, target),
96 vec![],
97 true,
98 );
0531ce1d 99
5869c6ff
XL
100 // We skip populating the sysroot in non-zero stage because that'll lead
101 // to rlib/rmeta conflicts if std gets built during this session.
102 if compiler.stage == 0 {
103 let libdir = builder.sysroot_libdir(compiler, target);
104 let hostdir = builder.sysroot_libdir(compiler, compiler.host);
105 add_to_sysroot(&builder, &libdir, &hostdir, &libstd_stamp(builder, compiler, target));
106 }
1b1a35ee
XL
107
108 // Then run cargo again, once we've put the rmeta files for the library
109 // crates into the sysroot. This is needed because e.g., core's tests
110 // depend on `libtest` -- Cargo presumes it will exist, but it doesn't
111 // since we initialize with an empty sysroot.
112 //
113 // Currently only the "libtest" tree of crates does this.
114
29967ef6
XL
115 if let Subcommand::Check { all_targets: true, .. } = builder.config.cmd {
116 let mut cargo = builder.cargo(
117 compiler,
118 Mode::Std,
119 SourceType::InTree,
120 target,
121 cargo_subcommand(builder.kind),
122 );
123 std_cargo(builder, target, compiler.stage, &mut cargo);
124 cargo.arg("--all-targets");
125
126 // Explicitly pass -p for all dependencies krates -- this will force cargo
127 // to also check the tests/benches/examples for these crates, rather
128 // than just the leaf crate.
129 for krate in builder.in_tree_crates("test", Some(target)) {
130 cargo.arg("-p").arg(krate.name);
131 }
1b1a35ee 132
29967ef6 133 builder.info(&format!(
5869c6ff
XL
134 "Checking stage{} std test/bench/example targets ({} -> {})",
135 builder.top_stage, &compiler.host, target
29967ef6
XL
136 ));
137 run_cargo(
138 builder,
139 cargo,
140 args(builder),
141 &libstd_test_stamp(builder, compiler, target),
142 vec![],
143 true,
144 );
1b1a35ee 145 }
a7813a04
XL
146 }
147}
148
3b2f2976 149#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
2c00a5a8 150pub struct Rustc {
3dfed10e 151 pub target: TargetSelection,
3b2f2976
XL
152}
153
2c00a5a8 154impl Step for Rustc {
3b2f2976 155 type Output = ();
3b2f2976 156 const ONLY_HOSTS: bool = true;
3b2f2976 157 const DEFAULT: bool = true;
3b2f2976 158
9fa01778 159 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2c00a5a8 160 run.all_krates("rustc-main")
3b2f2976
XL
161 }
162
9fa01778 163 fn make_run(run: RunConfig<'_>) {
dfeec247 164 run.builder.ensure(Rustc { target: run.target });
3b2f2976
XL
165 }
166
9fa01778 167 /// Builds the compiler.
3b2f2976 168 ///
2c00a5a8
XL
169 /// This will build the compiler for a particular stage of the build using
170 /// the `compiler` targeting the `target` architecture. The artifacts
171 /// created will also be linked into the sysroot directory.
9fa01778 172 fn run(self, builder: &Builder<'_>) {
5869c6ff 173 let compiler = builder.compiler(builder.top_stage, builder.config.build);
3b2f2976 174 let target = self.target;
3b2f2976 175
5869c6ff
XL
176 if compiler.stage != 0 {
177 // If we're not in stage 0, then we won't have a std from the beta
178 // compiler around. That means we need to make sure there's one in
179 // the sysroot for the compiler to find. Otherwise, we're going to
180 // fail when building crates that need to generate code (e.g., build
181 // scripts and their dependencies).
182 builder.ensure(crate::compile::Std { target: compiler.host, compiler });
183 builder.ensure(crate::compile::Std { target, compiler });
184 } else {
185 builder.ensure(Std { target });
186 }
ff7c6d11 187
f035d41b
XL
188 let mut cargo = builder.cargo(
189 compiler,
190 Mode::Rustc,
191 SourceType::InTree,
192 target,
193 cargo_subcommand(builder.kind),
194 );
60c5eb7d 195 rustc_cargo(builder, &mut cargo, target);
29967ef6
XL
196 if let Subcommand::Check { all_targets: true, .. } = builder.config.cmd {
197 cargo.arg("--all-targets");
198 }
1b1a35ee
XL
199
200 // Explicitly pass -p for all compiler krates -- this will force cargo
201 // to also check the tests/benches/examples for these crates, rather
202 // than just the leaf crate.
29967ef6 203 for krate in builder.in_tree_crates("rustc-main", Some(target)) {
1b1a35ee
XL
204 cargo.arg("-p").arg(krate.name);
205 }
0531ce1d 206
5869c6ff
XL
207 builder.info(&format!(
208 "Checking stage{} compiler artifacts ({} -> {})",
209 builder.top_stage, &compiler.host, target
210 ));
dfeec247
XL
211 run_cargo(
212 builder,
213 cargo,
29967ef6 214 args(builder),
dfeec247
XL
215 &librustc_stamp(builder, compiler, target),
216 vec![],
217 true,
218 );
0531ce1d 219
2c00a5a8 220 let libdir = builder.sysroot_libdir(compiler, target);
532ac7d7
XL
221 let hostdir = builder.sysroot_libdir(compiler, compiler.host);
222 add_to_sysroot(&builder, &libdir, &hostdir, &librustc_stamp(builder, compiler, target));
83c7162d
XL
223 }
224}
225
29967ef6
XL
226#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
227pub struct CodegenBackend {
228 pub target: TargetSelection,
229 pub backend: Interned<String>,
230}
231
232impl Step for CodegenBackend {
233 type Output = ();
234 const ONLY_HOSTS: bool = true;
235 const DEFAULT: bool = true;
236
237 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
238 run.paths(&["compiler/rustc_codegen_cranelift", "rustc_codegen_cranelift"])
239 }
240
241 fn make_run(run: RunConfig<'_>) {
242 for &backend in &[INTERNER.intern_str("cranelift")] {
243 run.builder.ensure(CodegenBackend { target: run.target, backend });
244 }
245 }
246
247 fn run(self, builder: &Builder<'_>) {
5869c6ff 248 let compiler = builder.compiler(builder.top_stage, builder.config.build);
29967ef6
XL
249 let target = self.target;
250 let backend = self.backend;
251
252 builder.ensure(Rustc { target });
253
254 let mut cargo = builder.cargo(
255 compiler,
256 Mode::Codegen,
257 SourceType::Submodule,
258 target,
259 cargo_subcommand(builder.kind),
260 );
261 cargo
262 .arg("--manifest-path")
263 .arg(builder.src.join(format!("compiler/rustc_codegen_{}/Cargo.toml", backend)));
264 rustc_cargo_env(builder, &mut cargo, target);
265
fc512014 266 builder.info(&format!(
5869c6ff
XL
267 "Checking stage{} {} artifacts ({} -> {})",
268 builder.top_stage, backend, &compiler.host.triple, target.triple
fc512014
XL
269 ));
270
29967ef6
XL
271 run_cargo(
272 builder,
273 cargo,
274 args(builder),
275 &codegen_backend_stamp(builder, compiler, target, backend),
276 vec![],
277 true,
278 );
279 }
280}
281
f9f354fc 282macro_rules! tool_check_step {
17df50a5 283 ($name:ident, $path:literal, $($alias:literal, )* $source_type:path $(, $default:literal )?) => {
f9f354fc
XL
284 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
285 pub struct $name {
3dfed10e 286 pub target: TargetSelection,
f9f354fc
XL
287 }
288
289 impl Step for $name {
290 type Output = ();
291 const ONLY_HOSTS: bool = true;
17df50a5
XL
292 // don't ever check out-of-tree tools by default, they'll fail when toolstate is broken
293 const DEFAULT: bool = matches!($source_type, SourceType::InTree) $( && $default )?;
f9f354fc
XL
294
295 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
cdc7bbd5 296 run.paths(&[ $path, $($alias),* ])
f9f354fc
XL
297 }
298
299 fn make_run(run: RunConfig<'_>) {
300 run.builder.ensure($name { target: run.target });
301 }
302
303 fn run(self, builder: &Builder<'_>) {
5869c6ff 304 let compiler = builder.compiler(builder.top_stage, builder.config.build);
f9f354fc
XL
305 let target = self.target;
306
307 builder.ensure(Rustc { target });
308
1b1a35ee 309 let mut cargo = prepare_tool_cargo(
f9f354fc
XL
310 builder,
311 compiler,
312 Mode::ToolRustc,
313 target,
314 cargo_subcommand(builder.kind),
315 $path,
f035d41b 316 $source_type,
f9f354fc
XL
317 &[],
318 );
319
29967ef6
XL
320 if let Subcommand::Check { all_targets: true, .. } = builder.config.cmd {
321 cargo.arg("--all-targets");
322 }
1b1a35ee 323
5869c6ff 324 // Enable internal lints for clippy and rustdoc
cdc7bbd5
XL
325 // NOTE: this doesn't enable lints for any other tools unless they explicitly add `#![warn(rustc::internal)]`
326 // See https://github.com/rust-lang/rust/pull/80573#issuecomment-754010776
327 cargo.rustflag("-Zunstable-options");
5869c6ff 328
1b1a35ee 329 builder.info(&format!(
5869c6ff
XL
330 "Checking stage{} {} artifacts ({} -> {})",
331 builder.top_stage,
f9f354fc 332 stringify!($name).to_lowercase(),
3dfed10e
XL
333 &compiler.host.triple,
334 target.triple
1b1a35ee 335 ));
f9f354fc
XL
336 run_cargo(
337 builder,
338 cargo,
29967ef6 339 args(builder),
f9f354fc
XL
340 &stamp(builder, compiler, target),
341 vec![],
342 true,
343 );
344
f9f354fc
XL
345 /// Cargo's output path in a given stage, compiled by a particular
346 /// compiler for the specified target.
347 fn stamp(
348 builder: &Builder<'_>,
349 compiler: Compiler,
3dfed10e 350 target: TargetSelection,
f9f354fc
XL
351 ) -> PathBuf {
352 builder
353 .cargo_out(compiler, Mode::ToolRustc, target)
354 .join(format!(".{}-check.stamp", stringify!($name).to_lowercase()))
355 }
356 }
357 }
358 };
83c7162d
XL
359}
360
cdc7bbd5 361tool_check_step!(Rustdoc, "src/tools/rustdoc", "src/librustdoc", SourceType::InTree);
17df50a5 362// Clippy and Rustfmt are hybrids. They are external tools, but use a git subtree instead
f035d41b
XL
363// of a submodule. Since the SourceType only drives the deny-warnings
364// behavior, treat it as in-tree so that any new warnings in clippy will be
365// rejected.
366tool_check_step!(Clippy, "src/tools/clippy", SourceType::InTree);
17df50a5
XL
367tool_check_step!(Miri, "src/tools/miri", SourceType::Submodule);
368tool_check_step!(Rls, "src/tools/rls", SourceType::Submodule);
369tool_check_step!(Rustfmt, "src/tools/rustfmt", SourceType::InTree);
c30ab7b3 370
17df50a5 371tool_check_step!(Bootstrap, "src/bootstrap", SourceType::InTree, false);
1b1a35ee 372
2c00a5a8
XL
373/// Cargo's output path for the standard library in a given stage, compiled
374/// by a particular compiler for the specified target.
3dfed10e 375fn libstd_stamp(builder: &Builder<'_>, compiler: Compiler, target: TargetSelection) -> PathBuf {
94b46f34 376 builder.cargo_out(compiler, Mode::Std, target).join(".libstd-check.stamp")
3b2f2976
XL
377}
378
1b1a35ee
XL
379/// Cargo's output path for the standard library in a given stage, compiled
380/// by a particular compiler for the specified target.
381fn libstd_test_stamp(
382 builder: &Builder<'_>,
383 compiler: Compiler,
384 target: TargetSelection,
385) -> PathBuf {
386 builder.cargo_out(compiler, Mode::Std, target).join(".libstd-check-test.stamp")
387}
388
2c00a5a8
XL
389/// Cargo's output path for librustc in a given stage, compiled by a particular
390/// compiler for the specified target.
3dfed10e 391fn librustc_stamp(builder: &Builder<'_>, compiler: Compiler, target: TargetSelection) -> PathBuf {
94b46f34 392 builder.cargo_out(compiler, Mode::Rustc, target).join(".librustc-check.stamp")
83c7162d 393}
29967ef6
XL
394
395/// Cargo's output path for librustc_codegen_llvm in a given stage, compiled by a particular
396/// compiler for the specified target and backend.
397fn codegen_backend_stamp(
398 builder: &Builder<'_>,
399 compiler: Compiler,
400 target: TargetSelection,
401 backend: Interned<String>,
402) -> PathBuf {
403 builder
404 .cargo_out(compiler, Mode::Codegen, target)
405 .join(format!(".librustc_codegen_{}-check.stamp", backend))
406}