]> git.proxmox.com Git - rustc.git/blame - src/bootstrap/test.rs
New upstream version 1.39.0+dfsg1
[rustc.git] / src / bootstrap / test.rs
CommitLineData
2c00a5a8
XL
1//! Implementation of the test-related targets of the build system.
2//!
3//! This file implements the various regression test suites that we execute on
4//! our CI.
5
6use std::env;
7use std::ffi::OsString;
2c00a5a8 8use std::fmt;
0731742a 9use std::fs;
94b46f34
XL
10use std::iter;
11use std::path::{Path, PathBuf};
12use std::process::Command;
2c00a5a8 13
48663c56 14use build_helper::{self, output, t};
2c00a5a8 15
0731742a
XL
16use crate::builder::{Builder, Compiler, Kind, RunConfig, ShouldRun, Step};
17use crate::cache::{Interned, INTERNER};
18use crate::compile;
19use crate::dist;
20use crate::flags::Subcommand;
21use crate::native;
22use crate::tool::{self, Tool, SourceType};
23use crate::toolstate::ToolState;
24use crate::util::{self, dylib_path, dylib_path_var};
25use crate::Crate as CargoCrate;
e1599b0c 26use crate::{DocTests, Mode, GitRepo, envify};
2c00a5a8
XL
27
28const ADB_TEST_DIR: &str = "/data/tmp/work";
29
30/// The two modes of the test runner; tests or benchmarks.
83c7162d 31#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone, PartialOrd, Ord)]
2c00a5a8 32pub enum TestKind {
9fa01778 33 /// Run `cargo test`.
2c00a5a8 34 Test,
9fa01778 35 /// Run `cargo bench`.
2c00a5a8
XL
36 Bench,
37}
38
94b46f34
XL
39impl From<Kind> for TestKind {
40 fn from(kind: Kind) -> Self {
41 match kind {
42 Kind::Test => TestKind::Test,
43 Kind::Bench => TestKind::Bench,
44 _ => panic!("unexpected kind in crate: {:?}", kind),
45 }
46 }
47}
48
2c00a5a8
XL
49impl TestKind {
50 // Return the cargo subcommand for this test kind
51 fn subcommand(self) -> &'static str {
52 match self {
53 TestKind::Test => "test",
54 TestKind::Bench => "bench",
55 }
56 }
57}
58
59impl fmt::Display for TestKind {
9fa01778 60 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2c00a5a8
XL
61 f.write_str(match *self {
62 TestKind::Test => "Testing",
63 TestKind::Bench => "Benchmarking",
64 })
65 }
66}
67
9fa01778 68fn try_run(builder: &Builder<'_>, cmd: &mut Command) -> bool {
83c7162d
XL
69 if !builder.fail_fast {
70 if !builder.try_run(cmd) {
71 let mut failures = builder.delayed_failures.borrow_mut();
2c00a5a8
XL
72 failures.push(format!("{:?}", cmd));
73 return false;
74 }
75 } else {
83c7162d 76 builder.run(cmd);
2c00a5a8
XL
77 }
78 true
79}
80
9fa01778 81fn try_run_quiet(builder: &Builder<'_>, cmd: &mut Command) -> bool {
83c7162d
XL
82 if !builder.fail_fast {
83 if !builder.try_run_quiet(cmd) {
84 let mut failures = builder.delayed_failures.borrow_mut();
2c00a5a8 85 failures.push(format!("{:?}", cmd));
0531ce1d 86 return false;
2c00a5a8
XL
87 }
88 } else {
83c7162d 89 builder.run_quiet(cmd);
2c00a5a8 90 }
0531ce1d 91 true
2c00a5a8
XL
92}
93
94#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
95pub struct Linkcheck {
96 host: Interned<String>,
97}
98
99impl Step for Linkcheck {
100 type Output = ();
101 const ONLY_HOSTS: bool = true;
102 const DEFAULT: bool = true;
103
104 /// Runs the `linkchecker` tool as compiled in `stage` by the `host` compiler.
105 ///
106 /// This tool in `src/tools` will verify the validity of all our links in the
107 /// documentation to ensure we don't have a bunch of dead ones.
9fa01778 108 fn run(self, builder: &Builder<'_>) {
2c00a5a8
XL
109 let host = self.host;
110
83c7162d 111 builder.info(&format!("Linkcheck ({})", host));
2c00a5a8
XL
112
113 builder.default_doc(None);
114
83c7162d 115 let _time = util::timeit(&builder);
94b46f34
XL
116 try_run(
117 builder,
118 builder
119 .tool_cmd(Tool::Linkchecker)
120 .arg(builder.out.join(host).join("doc")),
121 );
2c00a5a8
XL
122 }
123
9fa01778 124 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2c00a5a8 125 let builder = run.builder;
94b46f34
XL
126 run.path("src/tools/linkchecker")
127 .default_condition(builder.config.docs)
2c00a5a8
XL
128 }
129
9fa01778 130 fn make_run(run: RunConfig<'_>) {
2c00a5a8
XL
131 run.builder.ensure(Linkcheck { host: run.target });
132 }
133}
134
135#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
136pub struct Cargotest {
137 stage: u32,
138 host: Interned<String>,
139}
140
141impl Step for Cargotest {
142 type Output = ();
143 const ONLY_HOSTS: bool = true;
144
9fa01778 145 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2c00a5a8
XL
146 run.path("src/tools/cargotest")
147 }
148
9fa01778 149 fn make_run(run: RunConfig<'_>) {
2c00a5a8
XL
150 run.builder.ensure(Cargotest {
151 stage: run.builder.top_stage,
152 host: run.target,
153 });
154 }
155
156 /// Runs the `cargotest` tool as compiled in `stage` by the `host` compiler.
157 ///
158 /// This tool in `src/tools` will check out a few Rust projects and run `cargo
159 /// test` to ensure that we don't regress the test suites there.
9fa01778 160 fn run(self, builder: &Builder<'_>) {
2c00a5a8 161 let compiler = builder.compiler(self.stage, self.host);
94b46f34
XL
162 builder.ensure(compile::Rustc {
163 compiler,
164 target: compiler.host,
165 });
2c00a5a8
XL
166
167 // Note that this is a short, cryptic, and not scoped directory name. This
168 // is currently to minimize the length of path on Windows where we otherwise
169 // quickly run into path name limit constraints.
83c7162d 170 let out_dir = builder.out.join("ct");
2c00a5a8
XL
171 t!(fs::create_dir_all(&out_dir));
172
83c7162d 173 let _time = util::timeit(&builder);
2c00a5a8 174 let mut cmd = builder.tool_cmd(Tool::CargoTest);
94b46f34
XL
175 try_run(
176 builder,
177 cmd.arg(&builder.initial_cargo)
178 .arg(&out_dir)
179 .env("RUSTC", builder.rustc(compiler))
532ac7d7 180 .env("RUSTDOC", builder.rustdoc(compiler)),
94b46f34 181 );
2c00a5a8
XL
182 }
183}
184
185#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
186pub struct Cargo {
187 stage: u32,
188 host: Interned<String>,
189}
190
191impl Step for Cargo {
192 type Output = ();
193 const ONLY_HOSTS: bool = true;
194
9fa01778 195 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2c00a5a8
XL
196 run.path("src/tools/cargo")
197 }
198
9fa01778 199 fn make_run(run: RunConfig<'_>) {
2c00a5a8
XL
200 run.builder.ensure(Cargo {
201 stage: run.builder.top_stage,
202 host: run.target,
203 });
204 }
205
206 /// Runs `cargo test` for `cargo` packaged with Rust.
9fa01778 207 fn run(self, builder: &Builder<'_>) {
2c00a5a8
XL
208 let compiler = builder.compiler(self.stage, self.host);
209
94b46f34
XL
210 builder.ensure(tool::Cargo {
211 compiler,
212 target: self.host,
213 });
8faf50e0
XL
214 let mut cargo = tool::prepare_tool_cargo(builder,
215 compiler,
216 Mode::ToolRustc,
217 self.host,
218 "test",
219 "src/tools/cargo",
0bf4aa26
XL
220 SourceType::Submodule,
221 &[]);
8faf50e0 222
83c7162d 223 if !builder.fail_fast {
2c00a5a8
XL
224 cargo.arg("--no-fail-fast");
225 }
226
2c00a5a8
XL
227 // Don't run cross-compile tests, we may not have cross-compiled libstd libs
228 // available.
229 cargo.env("CFG_DISABLE_CROSS_TESTS", "1");
b7449926
XL
230 // Disable a test that has issues with mingw.
231 cargo.env("CARGO_TEST_DISABLE_GIT_CLI", "1");
416331ca
XL
232 // Forcibly disable tests using nightly features since any changes to
233 // those features won't be able to land.
234 cargo.env("CARGO_TEST_DISABLE_NIGHTLY", "1");
2c00a5a8 235
e1599b0c
XL
236 cargo.env("PATH", &path_for_cargo(builder, compiler));
237
238 try_run(builder, &mut cargo.into());
2c00a5a8
XL
239 }
240}
241
242#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
243pub struct Rls {
244 stage: u32,
245 host: Interned<String>,
246}
247
248impl Step for Rls {
249 type Output = ();
250 const ONLY_HOSTS: bool = true;
251
9fa01778 252 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2c00a5a8
XL
253 run.path("src/tools/rls")
254 }
255
9fa01778 256 fn make_run(run: RunConfig<'_>) {
2c00a5a8
XL
257 run.builder.ensure(Rls {
258 stage: run.builder.top_stage,
259 host: run.target,
260 });
261 }
262
263 /// Runs `cargo test` for the rls.
9fa01778 264 fn run(self, builder: &Builder<'_>) {
2c00a5a8
XL
265 let stage = self.stage;
266 let host = self.host;
267 let compiler = builder.compiler(stage, host);
268
83c7162d
XL
269 let build_result = builder.ensure(tool::Rls {
270 compiler,
271 target: self.host,
272 extra_features: Vec::new(),
273 });
274 if build_result.is_none() {
275 eprintln!("failed to test rls: could not build");
276 return;
277 }
278
2c00a5a8
XL
279 let mut cargo = tool::prepare_tool_cargo(builder,
280 compiler,
94b46f34 281 Mode::ToolRustc,
2c00a5a8
XL
282 host,
283 "test",
8faf50e0 284 "src/tools/rls",
0bf4aa26
XL
285 SourceType::Submodule,
286 &[]);
2c00a5a8 287
2c00a5a8 288 builder.add_rustc_lib_path(compiler, &mut cargo);
b7449926
XL
289 cargo.arg("--")
290 .args(builder.config.cmd.test_args());
2c00a5a8 291
e1599b0c 292 if try_run(builder, &mut cargo.into()) {
83c7162d 293 builder.save_toolstate("rls", ToolState::TestPass);
2c00a5a8
XL
294 }
295 }
296}
297
298#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
299pub struct Rustfmt {
300 stage: u32,
301 host: Interned<String>,
302}
303
304impl Step for Rustfmt {
305 type Output = ();
306 const ONLY_HOSTS: bool = true;
307
9fa01778 308 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2c00a5a8
XL
309 run.path("src/tools/rustfmt")
310 }
311
9fa01778 312 fn make_run(run: RunConfig<'_>) {
2c00a5a8
XL
313 run.builder.ensure(Rustfmt {
314 stage: run.builder.top_stage,
315 host: run.target,
316 });
317 }
318
319 /// Runs `cargo test` for rustfmt.
9fa01778 320 fn run(self, builder: &Builder<'_>) {
2c00a5a8
XL
321 let stage = self.stage;
322 let host = self.host;
323 let compiler = builder.compiler(stage, host);
324
83c7162d
XL
325 let build_result = builder.ensure(tool::Rustfmt {
326 compiler,
327 target: self.host,
328 extra_features: Vec::new(),
329 });
330 if build_result.is_none() {
331 eprintln!("failed to test rustfmt: could not build");
332 return;
333 }
334
2c00a5a8
XL
335 let mut cargo = tool::prepare_tool_cargo(builder,
336 compiler,
94b46f34 337 Mode::ToolRustc,
2c00a5a8
XL
338 host,
339 "test",
8faf50e0 340 "src/tools/rustfmt",
0bf4aa26
XL
341 SourceType::Submodule,
342 &[]);
2c00a5a8 343
83c7162d
XL
344 let dir = testdir(builder, compiler.host);
345 t!(fs::create_dir_all(&dir));
346 cargo.env("RUSTFMT_TEST_DIR", dir);
2c00a5a8
XL
347
348 builder.add_rustc_lib_path(compiler, &mut cargo);
349
e1599b0c 350 if try_run(builder, &mut cargo.into()) {
83c7162d 351 builder.save_toolstate("rustfmt", ToolState::TestPass);
2c00a5a8
XL
352 }
353 }
354}
355
356#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
357pub struct Miri {
358 stage: u32,
359 host: Interned<String>,
360}
361
362impl Step for Miri {
363 type Output = ();
364 const ONLY_HOSTS: bool = true;
2c00a5a8 365
9fa01778 366 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
416331ca 367 run.path("src/tools/miri")
2c00a5a8
XL
368 }
369
9fa01778 370 fn make_run(run: RunConfig<'_>) {
2c00a5a8
XL
371 run.builder.ensure(Miri {
372 stage: run.builder.top_stage,
373 host: run.target,
374 });
375 }
376
377 /// Runs `cargo test` for miri.
9fa01778 378 fn run(self, builder: &Builder<'_>) {
2c00a5a8
XL
379 let stage = self.stage;
380 let host = self.host;
381 let compiler = builder.compiler(stage, host);
382
0531ce1d
XL
383 let miri = builder.ensure(tool::Miri {
384 compiler,
385 target: self.host,
386 extra_features: Vec::new(),
387 });
388 if let Some(miri) = miri {
416331ca
XL
389 // # Run `cargo miri setup`.
390 // As a side-effect, this will install xargo.
391 let mut cargo = tool::prepare_tool_cargo(
392 builder,
393 compiler,
394 Mode::ToolRustc,
395 host,
396 "run",
397 "src/tools/miri",
398 SourceType::Submodule,
399 &[],
400 );
401 cargo
402 .arg("--bin")
403 .arg("cargo-miri")
404 .arg("--")
405 .arg("miri")
406 .arg("setup");
407
408 // Tell `cargo miri` not to worry about the sysroot mismatch (we built with
409 // stage1 but run with stage2).
410 cargo.env("MIRI_SKIP_SYSROOT_CHECK", "1");
411 // Tell `cargo miri setup` where to find the sources.
412 cargo.env("XARGO_RUST_SRC", builder.src.join("src"));
413 // Debug things.
414 cargo.env("RUST_BACKTRACE", "1");
415 // Configure `cargo install` path, and let cargo-miri know that that's where
416 // xargo ends up.
417 cargo.env("CARGO_INSTALL_ROOT", &builder.out); // cargo adds a `bin/`
418 cargo.env("XARGO", builder.out.join("bin").join("xargo"));
419
e1599b0c 420 let mut cargo = Command::from(cargo);
416331ca
XL
421 if !try_run(builder, &mut cargo) {
422 return;
423 }
424
425 // # Determine where Miri put its sysroot.
426 // To this end, we run `cargo miri setup --env` and capture the output.
427 // (We do this separately from the above so that when the setup actually
428 // happens we get some output.)
429 // We re-use the `cargo` from above.
430 cargo.arg("--env");
431
432 // FIXME: Is there a way in which we can re-use the usual `run` helpers?
433 let miri_sysroot = if builder.config.dry_run {
434 String::new()
435 } else {
436 builder.verbose(&format!("running: {:?}", cargo));
437 let out = cargo.output()
438 .expect("We already ran `cargo miri setup` before and that worked");
439 assert!(out.status.success(), "`cargo miri setup` returned with non-0 exit code");
440 // Output is "MIRI_SYSROOT=<str>\n".
441 let stdout = String::from_utf8(out.stdout)
442 .expect("`cargo miri setup` stdout is not valid UTF-8");
443 let stdout = stdout.trim();
444 builder.verbose(&format!("`cargo miri setup --env` returned: {:?}", stdout));
445 let sysroot = stdout.splitn(2, '=')
446 .nth(1).expect("`cargo miri setup` stdout did not contain '='");
447 sysroot.to_owned()
448 };
449
450 // # Run `cargo test`.
451 let mut cargo = tool::prepare_tool_cargo(
452 builder,
453 compiler,
454 Mode::ToolRustc,
455 host,
456 "test",
457 "src/tools/miri",
458 SourceType::Submodule,
459 &[],
460 );
2c00a5a8 461
2c00a5a8 462 // miri tests need to know about the stage sysroot
416331ca 463 cargo.env("MIRI_SYSROOT", miri_sysroot);
2c00a5a8
XL
464 cargo.env("RUSTC_TEST_SUITE", builder.rustc(compiler));
465 cargo.env("RUSTC_LIB_PATH", builder.rustc_libdir(compiler));
466 cargo.env("MIRI_PATH", miri);
467
468 builder.add_rustc_lib_path(compiler, &mut cargo);
469
e1599b0c 470 if !try_run(builder, &mut cargo.into()) {
416331ca 471 return;
2c00a5a8 472 }
416331ca
XL
473
474 // # Done!
475 builder.save_toolstate("miri", ToolState::TestPass);
2c00a5a8
XL
476 } else {
477 eprintln!("failed to test miri: could not build");
478 }
479 }
480}
481
0731742a
XL
482#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
483pub struct CompiletestTest {
0731742a
XL
484 host: Interned<String>,
485}
486
487impl Step for CompiletestTest {
488 type Output = ();
489
9fa01778 490 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
0731742a
XL
491 run.path("src/tools/compiletest")
492 }
493
9fa01778 494 fn make_run(run: RunConfig<'_>) {
0731742a 495 run.builder.ensure(CompiletestTest {
0731742a
XL
496 host: run.target,
497 });
498 }
499
500 /// Runs `cargo test` for compiletest.
9fa01778 501 fn run(self, builder: &Builder<'_>) {
0731742a 502 let host = self.host;
532ac7d7 503 let compiler = builder.compiler(0, host);
0731742a 504
e1599b0c
XL
505 let cargo = tool::prepare_tool_cargo(builder,
506 compiler,
507 Mode::ToolBootstrap,
508 host,
509 "test",
510 "src/tools/compiletest",
511 SourceType::InTree,
512 &[]);
0731742a 513
e1599b0c 514 try_run(builder, &mut cargo.into());
0731742a
XL
515 }
516}
517
2c00a5a8
XL
518#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
519pub struct Clippy {
520 stage: u32,
521 host: Interned<String>,
522}
523
524impl Step for Clippy {
525 type Output = ();
526 const ONLY_HOSTS: bool = true;
527 const DEFAULT: bool = false;
528
9fa01778 529 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2c00a5a8
XL
530 run.path("src/tools/clippy")
531 }
532
9fa01778 533 fn make_run(run: RunConfig<'_>) {
2c00a5a8
XL
534 run.builder.ensure(Clippy {
535 stage: run.builder.top_stage,
536 host: run.target,
537 });
538 }
539
540 /// Runs `cargo test` for clippy.
9fa01778 541 fn run(self, builder: &Builder<'_>) {
2c00a5a8
XL
542 let stage = self.stage;
543 let host = self.host;
544 let compiler = builder.compiler(stage, host);
545
0531ce1d
XL
546 let clippy = builder.ensure(tool::Clippy {
547 compiler,
548 target: self.host,
549 extra_features: Vec::new(),
550 });
551 if let Some(clippy) = clippy {
8faf50e0
XL
552 let mut cargo = tool::prepare_tool_cargo(builder,
553 compiler,
554 Mode::ToolRustc,
555 host,
556 "test",
557 "src/tools/clippy",
0bf4aa26
XL
558 SourceType::Submodule,
559 &[]);
2c00a5a8 560
2c00a5a8
XL
561 // clippy tests need to know about the stage sysroot
562 cargo.env("SYSROOT", builder.sysroot(compiler));
563 cargo.env("RUSTC_TEST_SUITE", builder.rustc(compiler));
564 cargo.env("RUSTC_LIB_PATH", builder.rustc_libdir(compiler));
94b46f34
XL
565 let host_libs = builder
566 .stage_out(compiler, Mode::ToolRustc)
567 .join(builder.cargo_dir());
2c00a5a8
XL
568 cargo.env("HOST_LIBS", host_libs);
569 // clippy tests need to find the driver
570 cargo.env("CLIPPY_DRIVER_PATH", clippy);
571
572 builder.add_rustc_lib_path(compiler, &mut cargo);
573
e1599b0c 574 if try_run(builder, &mut cargo.into()) {
83c7162d 575 builder.save_toolstate("clippy-driver", ToolState::TestPass);
2c00a5a8
XL
576 }
577 } else {
578 eprintln!("failed to test clippy: could not build");
579 }
580 }
581}
582
9fa01778 583fn path_for_cargo(builder: &Builder<'_>, compiler: Compiler) -> OsString {
2c00a5a8
XL
584 // Configure PATH to find the right rustc. NB. we have to use PATH
585 // and not RUSTC because the Cargo test suite has tests that will
586 // fail if rustc is not spelled `rustc`.
587 let path = builder.sysroot(compiler).join("bin");
588 let old_path = env::var_os("PATH").unwrap_or_default();
589 env::join_paths(iter::once(path).chain(env::split_paths(&old_path))).expect("")
590}
591
592#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
593pub struct RustdocTheme {
594 pub compiler: Compiler,
595}
596
597impl Step for RustdocTheme {
598 type Output = ();
599 const DEFAULT: bool = true;
600 const ONLY_HOSTS: bool = true;
601
9fa01778 602 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2c00a5a8
XL
603 run.path("src/tools/rustdoc-themes")
604 }
605
9fa01778 606 fn make_run(run: RunConfig<'_>) {
2c00a5a8
XL
607 let compiler = run.builder.compiler(run.builder.top_stage, run.host);
608
a1dfa0c6 609 run.builder.ensure(RustdocTheme { compiler });
2c00a5a8
XL
610 }
611
9fa01778 612 fn run(self, builder: &Builder<'_>) {
83c7162d 613 let rustdoc = builder.out.join("bootstrap/debug/rustdoc");
2c00a5a8
XL
614 let mut cmd = builder.tool_cmd(Tool::RustdocTheme);
615 cmd.arg(rustdoc.to_str().unwrap())
94b46f34
XL
616 .arg(
617 builder
618 .src
619 .join("src/librustdoc/html/static/themes")
620 .to_str()
621 .unwrap(),
622 )
623 .env("RUSTC_STAGE", self.compiler.stage.to_string())
624 .env("RUSTC_SYSROOT", builder.sysroot(self.compiler))
625 .env(
626 "RUSTDOC_LIBDIR",
627 builder.sysroot_libdir(self.compiler, self.compiler.host),
628 )
629 .env("CFG_RELEASE_CHANNEL", &builder.config.channel)
532ac7d7 630 .env("RUSTDOC_REAL", builder.rustdoc(self.compiler))
94b46f34
XL
631 .env("RUSTDOC_CRATE_VERSION", builder.rust_version())
632 .env("RUSTC_BOOTSTRAP", "1");
83c7162d 633 if let Some(linker) = builder.linker(self.compiler.host) {
2c00a5a8
XL
634 cmd.env("RUSTC_TARGET_LINKER", linker);
635 }
83c7162d 636 try_run(builder, &mut cmd);
2c00a5a8
XL
637 }
638}
639
640#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
9fa01778 641pub struct RustdocJSStd {
2c00a5a8
XL
642 pub host: Interned<String>,
643 pub target: Interned<String>,
644}
645
9fa01778 646impl Step for RustdocJSStd {
2c00a5a8
XL
647 type Output = ();
648 const DEFAULT: bool = true;
649 const ONLY_HOSTS: bool = true;
650
9fa01778
XL
651 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
652 run.path("src/test/rustdoc-js-std")
2c00a5a8
XL
653 }
654
9fa01778
XL
655 fn make_run(run: RunConfig<'_>) {
656 run.builder.ensure(RustdocJSStd {
2c00a5a8
XL
657 host: run.host,
658 target: run.target,
659 });
660 }
661
9fa01778 662 fn run(self, builder: &Builder<'_>) {
2c00a5a8
XL
663 if let Some(ref nodejs) = builder.config.nodejs {
664 let mut command = Command::new(nodejs);
9fa01778 665 command.args(&["src/tools/rustdoc-js-std/tester.js", &*self.host]);
0731742a 666 builder.ensure(crate::doc::Std {
2c00a5a8
XL
667 target: self.target,
668 stage: builder.top_stage,
669 });
670 builder.run(&mut command);
9fa01778
XL
671 } else {
672 builder.info(
673 "No nodejs found, skipping \"src/test/rustdoc-js-std\" tests"
674 );
675 }
676 }
677}
678
679#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
680pub struct RustdocJSNotStd {
681 pub host: Interned<String>,
682 pub target: Interned<String>,
683 pub compiler: Compiler,
684}
685
686impl Step for RustdocJSNotStd {
687 type Output = ();
688 const DEFAULT: bool = true;
689 const ONLY_HOSTS: bool = true;
690
691 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
692 run.path("src/test/rustdoc-js")
693 }
694
695 fn make_run(run: RunConfig<'_>) {
696 let compiler = run.builder.compiler(run.builder.top_stage, run.host);
697 run.builder.ensure(RustdocJSNotStd {
698 host: run.host,
699 target: run.target,
700 compiler,
701 });
702 }
703
704 fn run(self, builder: &Builder<'_>) {
705 if builder.config.nodejs.is_some() {
706 builder.ensure(Compiletest {
707 compiler: self.compiler,
708 target: self.target,
709 mode: "js-doc-test",
710 suite: "rustdoc-js",
711 path: None,
712 compare_mode: None,
713 });
2c00a5a8 714 } else {
a1dfa0c6 715 builder.info(
94b46f34 716 "No nodejs found, skipping \"src/test/rustdoc-js\" tests"
a1dfa0c6 717 );
2c00a5a8
XL
718 }
719 }
720}
721
83c7162d
XL
722#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
723pub struct RustdocUi {
724 pub host: Interned<String>,
725 pub target: Interned<String>,
726 pub compiler: Compiler,
727}
728
729impl Step for RustdocUi {
730 type Output = ();
731 const DEFAULT: bool = true;
732 const ONLY_HOSTS: bool = true;
733
9fa01778 734 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
83c7162d
XL
735 run.path("src/test/rustdoc-ui")
736 }
737
9fa01778 738 fn make_run(run: RunConfig<'_>) {
83c7162d
XL
739 let compiler = run.builder.compiler(run.builder.top_stage, run.host);
740 run.builder.ensure(RustdocUi {
741 host: run.host,
742 target: run.target,
743 compiler,
744 });
745 }
746
9fa01778 747 fn run(self, builder: &Builder<'_>) {
83c7162d
XL
748 builder.ensure(Compiletest {
749 compiler: self.compiler,
750 target: self.target,
751 mode: "ui",
752 suite: "rustdoc-ui",
48663c56 753 path: Some("src/test/rustdoc-ui"),
83c7162d
XL
754 compare_mode: None,
755 })
756 }
757}
758
2c00a5a8 759#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
0531ce1d 760pub struct Tidy;
2c00a5a8
XL
761
762impl Step for Tidy {
763 type Output = ();
764 const DEFAULT: bool = true;
765 const ONLY_HOSTS: bool = true;
2c00a5a8 766
0531ce1d 767 /// Runs the `tidy` tool.
2c00a5a8
XL
768 ///
769 /// This tool in `src/tools` checks up on various bits and pieces of style and
770 /// otherwise just implements a few lint-like checks that are specific to the
771 /// compiler itself.
9fa01778 772 fn run(self, builder: &Builder<'_>) {
2c00a5a8 773 let mut cmd = builder.tool_cmd(Tool::Tidy);
83c7162d
XL
774 cmd.arg(builder.src.join("src"));
775 cmd.arg(&builder.initial_cargo);
776 if !builder.config.vendor {
2c00a5a8
XL
777 cmd.arg("--no-vendor");
778 }
dc9dc135
XL
779 if builder.is_verbose() {
780 cmd.arg("--verbose");
2c00a5a8 781 }
0531ce1d 782
a1dfa0c6 783 builder.info("tidy check");
83c7162d 784 try_run(builder, &mut cmd);
2c00a5a8
XL
785 }
786
9fa01778 787 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2c00a5a8
XL
788 run.path("src/tools/tidy")
789 }
790
9fa01778 791 fn make_run(run: RunConfig<'_>) {
0531ce1d 792 run.builder.ensure(Tidy);
2c00a5a8
XL
793 }
794}
795
9fa01778 796fn testdir(builder: &Builder<'_>, host: Interned<String>) -> PathBuf {
83c7162d 797 builder.out.join(host).join("test")
2c00a5a8
XL
798}
799
800macro_rules! default_test {
801 ($name:ident { path: $path:expr, mode: $mode:expr, suite: $suite:expr }) => {
802 test!($name { path: $path, mode: $mode, suite: $suite, default: true, host: false });
803 }
804}
805
83c7162d
XL
806macro_rules! default_test_with_compare_mode {
807 ($name:ident { path: $path:expr, mode: $mode:expr, suite: $suite:expr,
808 compare_mode: $compare_mode:expr }) => {
809 test_with_compare_mode!($name { path: $path, mode: $mode, suite: $suite, default: true,
810 host: false, compare_mode: $compare_mode });
811 }
812}
813
2c00a5a8
XL
814macro_rules! host_test {
815 ($name:ident { path: $path:expr, mode: $mode:expr, suite: $suite:expr }) => {
816 test!($name { path: $path, mode: $mode, suite: $suite, default: true, host: true });
817 }
818}
819
820macro_rules! test {
83c7162d
XL
821 ($name:ident { path: $path:expr, mode: $mode:expr, suite: $suite:expr, default: $default:expr,
822 host: $host:expr }) => {
823 test_definitions!($name { path: $path, mode: $mode, suite: $suite, default: $default,
824 host: $host, compare_mode: None });
825 }
826}
827
828macro_rules! test_with_compare_mode {
829 ($name:ident { path: $path:expr, mode: $mode:expr, suite: $suite:expr, default: $default:expr,
830 host: $host:expr, compare_mode: $compare_mode:expr }) => {
831 test_definitions!($name { path: $path, mode: $mode, suite: $suite, default: $default,
832 host: $host, compare_mode: Some($compare_mode) });
833 }
834}
835
836macro_rules! test_definitions {
2c00a5a8
XL
837 ($name:ident {
838 path: $path:expr,
839 mode: $mode:expr,
840 suite: $suite:expr,
841 default: $default:expr,
83c7162d
XL
842 host: $host:expr,
843 compare_mode: $compare_mode:expr
2c00a5a8
XL
844 }) => {
845 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
846 pub struct $name {
847 pub compiler: Compiler,
848 pub target: Interned<String>,
849 }
850
851 impl Step for $name {
852 type Output = ();
853 const DEFAULT: bool = $default;
854 const ONLY_HOSTS: bool = $host;
855
9fa01778 856 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
94b46f34 857 run.suite_path($path)
2c00a5a8
XL
858 }
859
9fa01778 860 fn make_run(run: RunConfig<'_>) {
2c00a5a8
XL
861 let compiler = run.builder.compiler(run.builder.top_stage, run.host);
862
863 run.builder.ensure($name {
864 compiler,
865 target: run.target,
866 });
867 }
868
9fa01778 869 fn run(self, builder: &Builder<'_>) {
2c00a5a8
XL
870 builder.ensure(Compiletest {
871 compiler: self.compiler,
872 target: self.target,
873 mode: $mode,
874 suite: $suite,
94b46f34 875 path: Some($path),
83c7162d 876 compare_mode: $compare_mode,
2c00a5a8
XL
877 })
878 }
879 }
880 }
881}
882
83c7162d 883default_test_with_compare_mode!(Ui {
2c00a5a8
XL
884 path: "src/test/ui",
885 mode: "ui",
83c7162d
XL
886 suite: "ui",
887 compare_mode: "nll"
2c00a5a8
XL
888});
889
2c00a5a8
XL
890default_test!(CompileFail {
891 path: "src/test/compile-fail",
892 mode: "compile-fail",
893 suite: "compile-fail"
894});
895
2c00a5a8
XL
896default_test!(RunFail {
897 path: "src/test/run-fail",
898 mode: "run-fail",
899 suite: "run-fail"
900});
901
902default_test!(RunPassValgrind {
903 path: "src/test/run-pass-valgrind",
904 mode: "run-pass-valgrind",
905 suite: "run-pass-valgrind"
906});
907
908default_test!(MirOpt {
909 path: "src/test/mir-opt",
910 mode: "mir-opt",
911 suite: "mir-opt"
912});
913
914default_test!(Codegen {
915 path: "src/test/codegen",
916 mode: "codegen",
917 suite: "codegen"
918});
919
920default_test!(CodegenUnits {
921 path: "src/test/codegen-units",
922 mode: "codegen-units",
923 suite: "codegen-units"
924});
925
926default_test!(Incremental {
927 path: "src/test/incremental",
928 mode: "incremental",
929 suite: "incremental"
930});
931
932default_test!(Debuginfo {
933 path: "src/test/debuginfo",
0bf4aa26 934 mode: "debuginfo",
2c00a5a8
XL
935 suite: "debuginfo"
936});
937
938host_test!(UiFullDeps {
939 path: "src/test/ui-fulldeps",
940 mode: "ui",
941 suite: "ui-fulldeps"
942});
943
2c00a5a8
XL
944host_test!(Rustdoc {
945 path: "src/test/rustdoc",
946 mode: "rustdoc",
947 suite: "rustdoc"
948});
949
532ac7d7 950host_test!(Pretty {
2c00a5a8
XL
951 path: "src/test/pretty",
952 mode: "pretty",
532ac7d7 953 suite: "pretty"
2c00a5a8 954});
2c00a5a8
XL
955test!(RunFailPretty {
956 path: "src/test/run-fail/pretty",
957 mode: "pretty",
958 suite: "run-fail",
959 default: false,
960 host: true
961});
962test!(RunPassValgrindPretty {
963 path: "src/test/run-pass-valgrind/pretty",
964 mode: "pretty",
965 suite: "run-pass-valgrind",
966 default: false,
967 host: true
968});
2c00a5a8 969
94b46f34 970default_test!(RunMake {
2c00a5a8
XL
971 path: "src/test/run-make",
972 mode: "run-make",
973 suite: "run-make"
974});
975
0531ce1d
XL
976host_test!(RunMakeFullDeps {
977 path: "src/test/run-make-fulldeps",
978 mode: "run-make",
979 suite: "run-make-fulldeps"
980});
981
532ac7d7
XL
982default_test!(Assembly {
983 path: "src/test/assembly",
984 mode: "assembly",
985 suite: "assembly"
986});
987
2c00a5a8
XL
988#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
989struct Compiletest {
990 compiler: Compiler,
991 target: Interned<String>,
992 mode: &'static str,
993 suite: &'static str,
94b46f34 994 path: Option<&'static str>,
83c7162d 995 compare_mode: Option<&'static str>,
2c00a5a8
XL
996}
997
998impl Step for Compiletest {
999 type Output = ();
1000
9fa01778 1001 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2c00a5a8
XL
1002 run.never()
1003 }
1004
1005 /// Executes the `compiletest` tool to run a suite of tests.
1006 ///
1007 /// Compiles all tests with `compiler` for `target` with the specified
1008 /// compiletest `mode` and `suite` arguments. For example `mode` can be
1009 /// "run-pass" or `suite` can be something like `debuginfo`.
9fa01778 1010 fn run(self, builder: &Builder<'_>) {
2c00a5a8
XL
1011 let compiler = self.compiler;
1012 let target = self.target;
1013 let mode = self.mode;
1014 let suite = self.suite;
94b46f34
XL
1015
1016 // Path for test suite
1017 let suite_path = self.path.unwrap_or("");
2c00a5a8
XL
1018
1019 // Skip codegen tests if they aren't enabled in configuration.
83c7162d 1020 if !builder.config.codegen_tests && suite == "codegen" {
2c00a5a8
XL
1021 return;
1022 }
1023
1024 if suite == "debuginfo" {
dc9dc135 1025 let msvc = builder.config.build.contains("msvc");
0bf4aa26
XL
1026 if mode == "debuginfo" {
1027 return builder.ensure(Compiletest {
dc9dc135 1028 mode: if msvc { "debuginfo-cdb" } else { "debuginfo-gdb+lldb" },
0bf4aa26
XL
1029 ..self
1030 });
2c00a5a8
XL
1031 }
1032
1033 builder.ensure(dist::DebuggerScripts {
1034 sysroot: builder.sysroot(compiler),
94b46f34 1035 host: target,
2c00a5a8
XL
1036 });
1037 }
1038
532ac7d7 1039 if suite.ends_with("fulldeps") {
2c00a5a8
XL
1040 builder.ensure(compile::Rustc { compiler, target });
1041 }
1042
e1599b0c
XL
1043 builder.ensure(compile::Std { compiler, target });
1044 // ensure that `libproc_macro` is available on the host.
1045 builder.ensure(compile::Std { compiler, target: compiler.host });
b7449926 1046
a1dfa0c6
XL
1047 // Also provide `rust_test_helpers` for the host.
1048 builder.ensure(native::TestHelpers { target: compiler.host });
1049
48663c56
XL
1050 // wasm32 can't build the test helpers
1051 if !target.contains("wasm32") {
1052 builder.ensure(native::TestHelpers { target });
1053 }
2c00a5a8
XL
1054 builder.ensure(RemoteCopyLibs { compiler, target });
1055
2c00a5a8
XL
1056 let mut cmd = builder.tool_cmd(Tool::Compiletest);
1057
1058 // compiletest currently has... a lot of arguments, so let's just pass all
1059 // of them!
1060
94b46f34
XL
1061 cmd.arg("--compile-lib-path")
1062 .arg(builder.rustc_libdir(compiler));
1063 cmd.arg("--run-lib-path")
1064 .arg(builder.sysroot_libdir(compiler, target));
2c00a5a8
XL
1065 cmd.arg("--rustc-path").arg(builder.rustc(compiler));
1066
9fa01778 1067 let is_rustdoc = suite.ends_with("rustdoc-ui") || suite.ends_with("rustdoc-js");
83c7162d 1068
2c00a5a8 1069 // Avoid depending on rustdoc when we don't need it.
94b46f34
XL
1070 if mode == "rustdoc"
1071 || (mode == "run-make" && suite.ends_with("fulldeps"))
9fa01778
XL
1072 || (mode == "ui" && is_rustdoc)
1073 || mode == "js-doc-test"
94b46f34
XL
1074 {
1075 cmd.arg("--rustdoc-path")
532ac7d7 1076 .arg(builder.rustdoc(compiler));
2c00a5a8
XL
1077 }
1078
94b46f34
XL
1079 cmd.arg("--src-base")
1080 .arg(builder.src.join("src/test").join(suite));
1081 cmd.arg("--build-base")
1082 .arg(testdir(builder, compiler.host).join(suite));
1083 cmd.arg("--stage-id")
1084 .arg(format!("stage{}-{}", compiler.stage, target));
2c00a5a8
XL
1085 cmd.arg("--mode").arg(mode);
1086 cmd.arg("--target").arg(target);
1087 cmd.arg("--host").arg(&*compiler.host);
94b46f34
XL
1088 cmd.arg("--llvm-filecheck")
1089 .arg(builder.llvm_filecheck(builder.config.build));
1090
1091 if builder.config.cmd.bless() {
1092 cmd.arg("--bless");
1093 }
1094
a1dfa0c6
XL
1095 let compare_mode = builder.config.cmd.compare_mode().or_else(|| {
1096 if builder.config.test_compare_mode {
1097 self.compare_mode
1098 } else {
1099 None
1100 }
1101 });
2c00a5a8 1102
dc9dc135
XL
1103 if let Some(ref pass) = builder.config.cmd.pass() {
1104 cmd.arg("--pass");
1105 cmd.arg(pass);
1106 }
1107
83c7162d 1108 if let Some(ref nodejs) = builder.config.nodejs {
2c00a5a8
XL
1109 cmd.arg("--nodejs").arg(nodejs);
1110 }
1111
9fa01778 1112 let mut flags = if is_rustdoc {
83c7162d
XL
1113 Vec::new()
1114 } else {
1115 vec!["-Crpath".to_string()]
1116 };
9fa01778 1117 if !is_rustdoc {
83c7162d
XL
1118 if builder.config.rust_optimize_tests {
1119 flags.push("-O".to_string());
1120 }
2c00a5a8 1121 }
dc9dc135 1122 flags.push(format!("-Cdebuginfo={}", builder.config.rust_debuginfo_level_tests));
83c7162d
XL
1123 flags.push("-Zunstable-options".to_string());
1124 flags.push(builder.config.cmd.rustc_args().join(" "));
2c00a5a8 1125
83c7162d 1126 if let Some(linker) = builder.linker(target) {
2c00a5a8
XL
1127 cmd.arg("--linker").arg(linker);
1128 }
1129
a1dfa0c6
XL
1130 let mut hostflags = flags.clone();
1131 hostflags.push(format!(
1132 "-Lnative={}",
1133 builder.test_helpers_out(compiler.host).display()
1134 ));
2c00a5a8
XL
1135 cmd.arg("--host-rustcflags").arg(hostflags.join(" "));
1136
0bf4aa26 1137 let mut targetflags = flags;
94b46f34
XL
1138 targetflags.push(format!(
1139 "-Lnative={}",
1140 builder.test_helpers_out(target).display()
1141 ));
2c00a5a8
XL
1142 cmd.arg("--target-rustcflags").arg(targetflags.join(" "));
1143
83c7162d 1144 cmd.arg("--docck-python").arg(builder.python());
2c00a5a8 1145
83c7162d 1146 if builder.config.build.ends_with("apple-darwin") {
2c00a5a8
XL
1147 // Force /usr/bin/python on macOS for LLDB tests because we're loading the
1148 // LLDB plugin's compiled module which only works with the system python
1149 // (namely not Homebrew-installed python)
1150 cmd.arg("--lldb-python").arg("/usr/bin/python");
1151 } else {
83c7162d 1152 cmd.arg("--lldb-python").arg(builder.python());
2c00a5a8
XL
1153 }
1154
83c7162d 1155 if let Some(ref gdb) = builder.config.gdb {
2c00a5a8
XL
1156 cmd.arg("--gdb").arg(gdb);
1157 }
0bf4aa26
XL
1158
1159 let run = |cmd: &mut Command| {
1160 cmd.output().map(|output| {
1161 String::from_utf8_lossy(&output.stdout)
1162 .lines().next().unwrap_or_else(|| {
1163 panic!("{:?} failed {:?}", cmd, output)
1164 }).to_string()
1165 })
1166 };
1167 let lldb_exe = if builder.config.lldb_enabled && !target.contains("emscripten") {
1168 // Test against the lldb that was just built.
9fa01778 1169 builder.llvm_out(target).join("bin").join("lldb")
0bf4aa26
XL
1170 } else {
1171 PathBuf::from("lldb")
1172 };
1173 let lldb_version = Command::new(&lldb_exe)
1174 .arg("--version")
1175 .output()
1176 .map(|output| { String::from_utf8_lossy(&output.stdout).to_string() })
1177 .ok();
1178 if let Some(ref vers) = lldb_version {
2c00a5a8 1179 cmd.arg("--lldb-version").arg(vers);
0bf4aa26
XL
1180 let lldb_python_dir = run(Command::new(&lldb_exe).arg("-P")).ok();
1181 if let Some(ref dir) = lldb_python_dir {
1182 cmd.arg("--lldb-python-dir").arg(dir);
1183 }
2c00a5a8
XL
1184 }
1185
dc9dc135
XL
1186 if util::forcing_clang_based_tests() {
1187 let clang_exe = builder.llvm_out(target).join("bin").join("clang");
1188 cmd.arg("--run-clang-based-tests-with").arg(clang_exe);
9fa01778
XL
1189 }
1190
94b46f34
XL
1191 // Get paths from cmd args
1192 let paths = match &builder.config.cmd {
1193 Subcommand::Test { ref paths, .. } => &paths[..],
1194 _ => &[],
1195 };
1196
1197 // Get test-args by striping suite path
1198 let mut test_args: Vec<&str> = paths
1199 .iter()
8faf50e0
XL
1200 .map(|p| {
1201 match p.strip_prefix(".") {
1202 Ok(path) => path,
1203 Err(_) => p,
1204 }
1205 })
48663c56
XL
1206 .filter(|p| p.starts_with(suite_path) && (p.is_dir() || p.is_file()))
1207 .filter_map(|p| {
1208 // Since test suite paths are themselves directories, if we don't
1209 // specify a directory or file, we'll get an empty string here
1210 // (the result of the test suite directory without its suite prefix).
1211 // Therefore, we need to filter these out, as only the first --test-args
1212 // flag is respected, so providing an empty --test-args conflicts with
1213 // any following it.
1214 match p.strip_prefix(suite_path).ok().and_then(|p| p.to_str()) {
1215 Some(s) if s != "" => Some(s),
1216 _ => None,
1217 }
1218 })
94b46f34
XL
1219 .collect();
1220
1221 test_args.append(&mut builder.config.cmd.test_args());
1222
1223 cmd.args(&test_args);
2c00a5a8 1224
83c7162d 1225 if builder.is_verbose() {
2c00a5a8
XL
1226 cmd.arg("--verbose");
1227 }
1228
94b46f34 1229 if !builder.config.verbose_tests {
2c00a5a8
XL
1230 cmd.arg("--quiet");
1231 }
1232
532ac7d7 1233 if builder.config.llvm_enabled() {
0531ce1d 1234 let llvm_config = builder.ensure(native::Llvm {
83c7162d 1235 target: builder.config.build,
0531ce1d
XL
1236 emscripten: false,
1237 });
83c7162d
XL
1238 if !builder.config.dry_run {
1239 let llvm_version = output(Command::new(&llvm_config).arg("--version"));
1240 cmd.arg("--llvm-version").arg(llvm_version);
1241 }
1242 if !builder.is_rust_llvm(target) {
2c00a5a8
XL
1243 cmd.arg("--system-llvm");
1244 }
1245
1246 // Only pass correct values for these flags for the `run-make` suite as it
1247 // requires that a C++ compiler was configured which isn't always the case.
94b46f34 1248 if !builder.config.dry_run && suite == "run-make-fulldeps" {
2c00a5a8
XL
1249 let llvm_components = output(Command::new(&llvm_config).arg("--components"));
1250 let llvm_cxxflags = output(Command::new(&llvm_config).arg("--cxxflags"));
94b46f34
XL
1251 cmd.arg("--cc")
1252 .arg(builder.cc(target))
1253 .arg("--cxx")
1254 .arg(builder.cxx(target).unwrap())
1255 .arg("--cflags")
b7449926 1256 .arg(builder.cflags(target, GitRepo::Rustc).join(" "))
94b46f34
XL
1257 .arg("--llvm-components")
1258 .arg(llvm_components.trim())
1259 .arg("--llvm-cxxflags")
1260 .arg(llvm_cxxflags.trim());
83c7162d 1261 if let Some(ar) = builder.ar(target) {
2c00a5a8
XL
1262 cmd.arg("--ar").arg(ar);
1263 }
48663c56
XL
1264
1265 // The llvm/bin directory contains many useful cross-platform
1266 // tools. Pass the path to run-make tests so they can use them.
1267 let llvm_bin_path = llvm_config.parent()
1268 .expect("Expected llvm-config to be contained in directory");
1269 assert!(llvm_bin_path.is_dir());
1270 cmd.arg("--llvm-bin-dir").arg(llvm_bin_path);
1271
1272 // If LLD is available, add it to the PATH
1273 if builder.config.lld_enabled {
1274 let lld_install_root = builder.ensure(native::Lld {
1275 target: builder.config.build,
1276 });
1277
1278 let lld_bin_path = lld_install_root.join("bin");
1279
1280 let old_path = env::var_os("PATH").unwrap_or_default();
1281 let new_path = env::join_paths(std::iter::once(lld_bin_path)
1282 .chain(env::split_paths(&old_path)))
1283 .expect("Could not add LLD bin path to PATH");
1284 cmd.env("PATH", new_path);
1285 }
2c00a5a8
XL
1286 }
1287 }
2c00a5a8 1288
94b46f34
XL
1289 if suite != "run-make-fulldeps" {
1290 cmd.arg("--cc")
1291 .arg("")
1292 .arg("--cxx")
1293 .arg("")
1294 .arg("--cflags")
1295 .arg("")
1296 .arg("--llvm-components")
1297 .arg("")
1298 .arg("--llvm-cxxflags")
1299 .arg("");
2c00a5a8
XL
1300 }
1301
83c7162d 1302 if builder.remote_tested(target) {
94b46f34
XL
1303 cmd.arg("--remote-test-client")
1304 .arg(builder.tool_exe(Tool::RemoteTestClient));
2c00a5a8
XL
1305 }
1306
1307 // Running a C compiler on MSVC requires a few env vars to be set, to be
1308 // sure to set them here.
1309 //
1310 // Note that if we encounter `PATH` we make sure to append to our own `PATH`
1311 // rather than stomp over it.
1312 if target.contains("msvc") {
83c7162d 1313 for &(ref k, ref v) in builder.cc[&target].env() {
2c00a5a8
XL
1314 if k != "PATH" {
1315 cmd.env(k, v);
1316 }
1317 }
1318 }
1319 cmd.env("RUSTC_BOOTSTRAP", "1");
83c7162d 1320 builder.add_rust_test_threads(&mut cmd);
2c00a5a8 1321
83c7162d 1322 if builder.config.sanitizers {
48663c56 1323 cmd.env("RUSTC_SANITIZER_SUPPORT", "1");
2c00a5a8
XL
1324 }
1325
83c7162d 1326 if builder.config.profiler {
48663c56 1327 cmd.env("RUSTC_PROFILER_SUPPORT", "1");
2c00a5a8
XL
1328 }
1329
e1599b0c
XL
1330 let tmp = builder.out.join("tmp");
1331 std::fs::create_dir_all(&tmp).unwrap();
1332 cmd.env("RUST_TEST_TMPDIR", tmp);
1333
2c00a5a8
XL
1334
1335 cmd.arg("--adb-path").arg("adb");
1336 cmd.arg("--adb-test-dir").arg(ADB_TEST_DIR);
1337 if target.contains("android") {
1338 // Assume that cc for this target comes from the android sysroot
1339 cmd.arg("--android-cross-path")
94b46f34 1340 .arg(builder.cc(target).parent().unwrap().parent().unwrap());
2c00a5a8
XL
1341 } else {
1342 cmd.arg("--android-cross-path").arg("");
1343 }
1344
532ac7d7
XL
1345 if builder.config.cmd.rustfix_coverage() {
1346 cmd.arg("--rustfix-coverage");
1347 }
1348
83c7162d
XL
1349 builder.ci_env.force_coloring_in_ci(&mut cmd);
1350
94b46f34
XL
1351 builder.info(&format!(
1352 "Check compiletest suite={} mode={} ({} -> {})",
1353 suite, mode, &compiler.host, target
1354 ));
83c7162d
XL
1355 let _time = util::timeit(&builder);
1356 try_run(builder, &mut cmd);
1357
1358 if let Some(compare_mode) = compare_mode {
1359 cmd.arg("--compare-mode").arg(compare_mode);
94b46f34
XL
1360 builder.info(&format!(
1361 "Check compiletest suite={} mode={} compare_mode={} ({} -> {})",
1362 suite, mode, compare_mode, &compiler.host, target
1363 ));
83c7162d
XL
1364 let _time = util::timeit(&builder);
1365 try_run(builder, &mut cmd);
1366 }
2c00a5a8
XL
1367 }
1368}
1369
1370#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
0531ce1d 1371struct DocTest {
2c00a5a8 1372 compiler: Compiler,
0531ce1d
XL
1373 path: &'static str,
1374 name: &'static str,
1375 is_ext_doc: bool,
2c00a5a8
XL
1376}
1377
0531ce1d 1378impl Step for DocTest {
2c00a5a8 1379 type Output = ();
2c00a5a8
XL
1380 const ONLY_HOSTS: bool = true;
1381
9fa01778 1382 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
0531ce1d 1383 run.never()
2c00a5a8
XL
1384 }
1385
9fa01778 1386 /// Runs `rustdoc --test` for all documentation in `src/doc`.
2c00a5a8 1387 ///
0731742a 1388 /// This will run all tests in our markdown documentation (e.g., the book)
2c00a5a8
XL
1389 /// located in `src/doc`. The `rustdoc` that's run is the one that sits next to
1390 /// `compiler`.
9fa01778 1391 fn run(self, builder: &Builder<'_>) {
2c00a5a8
XL
1392 let compiler = self.compiler;
1393
e1599b0c 1394 builder.ensure(compile::Std {
94b46f34
XL
1395 compiler,
1396 target: compiler.host,
1397 });
2c00a5a8
XL
1398
1399 // Do a breadth-first traversal of the `src/doc` directory and just run
1400 // tests for all files that end in `*.md`
83c7162d
XL
1401 let mut stack = vec![builder.src.join(self.path)];
1402 let _time = util::timeit(&builder);
2c00a5a8 1403
83c7162d 1404 let mut files = Vec::new();
2c00a5a8
XL
1405 while let Some(p) = stack.pop() {
1406 if p.is_dir() {
1407 stack.extend(t!(p.read_dir()).map(|p| t!(p).path()));
94b46f34 1408 continue;
2c00a5a8
XL
1409 }
1410
1411 if p.extension().and_then(|s| s.to_str()) != Some("md") {
1412 continue;
1413 }
1414
1415 // The nostarch directory in the book is for no starch, and so isn't
83c7162d 1416 // guaranteed to builder. We don't care if it doesn't build, so skip it.
2c00a5a8
XL
1417 if p.to_str().map_or(false, |p| p.contains("nostarch")) {
1418 continue;
1419 }
1420
83c7162d
XL
1421 files.push(p);
1422 }
1423
1424 files.sort();
1425
8faf50e0 1426 let mut toolstate = ToolState::TestPass;
83c7162d 1427 for file in files {
8faf50e0
XL
1428 if !markdown_test(builder, compiler, &file) {
1429 toolstate = ToolState::TestFail;
0531ce1d 1430 }
2c00a5a8 1431 }
8faf50e0
XL
1432 if self.is_ext_doc {
1433 builder.save_toolstate(self.name, toolstate);
1434 }
2c00a5a8
XL
1435 }
1436}
1437
0531ce1d
XL
1438macro_rules! test_book {
1439 ($($name:ident, $path:expr, $book_name:expr, default=$default:expr;)+) => {
1440 $(
1441 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1442 pub struct $name {
1443 compiler: Compiler,
1444 }
1445
1446 impl Step for $name {
1447 type Output = ();
1448 const DEFAULT: bool = $default;
1449 const ONLY_HOSTS: bool = true;
1450
9fa01778 1451 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
0531ce1d
XL
1452 run.path($path)
1453 }
1454
9fa01778 1455 fn make_run(run: RunConfig<'_>) {
0531ce1d
XL
1456 run.builder.ensure($name {
1457 compiler: run.builder.compiler(run.builder.top_stage, run.host),
1458 });
1459 }
1460
9fa01778 1461 fn run(self, builder: &Builder<'_>) {
0531ce1d
XL
1462 builder.ensure(DocTest {
1463 compiler: self.compiler,
1464 path: $path,
1465 name: $book_name,
1466 is_ext_doc: !$default,
1467 });
1468 }
1469 }
1470 )+
1471 }
1472}
1473
1474test_book!(
1475 Nomicon, "src/doc/nomicon", "nomicon", default=false;
1476 Reference, "src/doc/reference", "reference", default=false;
1477 RustdocBook, "src/doc/rustdoc", "rustdoc", default=true;
83c7162d 1478 RustcBook, "src/doc/rustc", "rustc", default=true;
0531ce1d 1479 RustByExample, "src/doc/rust-by-example", "rust-by-example", default=false;
9fa01778 1480 EmbeddedBook, "src/doc/embedded-book", "embedded-book", default=false;
0531ce1d
XL
1481 TheBook, "src/doc/book", "book", default=false;
1482 UnstableBook, "src/doc/unstable-book", "unstable-book", default=true;
532ac7d7 1483 EditionGuide, "src/doc/edition-guide", "edition-guide", default=false;
0531ce1d
XL
1484);
1485
2c00a5a8
XL
1486#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1487pub struct ErrorIndex {
1488 compiler: Compiler,
1489}
1490
1491impl Step for ErrorIndex {
1492 type Output = ();
1493 const DEFAULT: bool = true;
1494 const ONLY_HOSTS: bool = true;
1495
9fa01778 1496 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2c00a5a8
XL
1497 run.path("src/tools/error_index_generator")
1498 }
1499
9fa01778 1500 fn make_run(run: RunConfig<'_>) {
2c00a5a8
XL
1501 run.builder.ensure(ErrorIndex {
1502 compiler: run.builder.compiler(run.builder.top_stage, run.host),
1503 });
1504 }
1505
9fa01778 1506 /// Runs the error index generator tool to execute the tests located in the error
2c00a5a8
XL
1507 /// index.
1508 ///
1509 /// The `error_index_generator` tool lives in `src/tools` and is used to
1510 /// generate a markdown file from the error indexes of the code base which is
1511 /// then passed to `rustdoc --test`.
9fa01778 1512 fn run(self, builder: &Builder<'_>) {
2c00a5a8
XL
1513 let compiler = self.compiler;
1514
94b46f34
XL
1515 builder.ensure(compile::Std {
1516 compiler,
1517 target: compiler.host,
1518 });
2c00a5a8 1519
83c7162d 1520 let dir = testdir(builder, compiler.host);
2c00a5a8
XL
1521 t!(fs::create_dir_all(&dir));
1522 let output = dir.join("error-index.md");
1523
532ac7d7
XL
1524 let mut tool = tool::ErrorIndex::command(
1525 builder,
1526 builder.compiler(compiler.stage, builder.config.build),
1527 );
0531ce1d
XL
1528 tool.arg("markdown")
1529 .arg(&output)
e1599b0c 1530 .env("CFG_BUILD", &builder.config.build);
0531ce1d 1531
83c7162d
XL
1532 builder.info(&format!("Testing error-index stage{}", compiler.stage));
1533 let _time = util::timeit(&builder);
416331ca 1534 builder.run_quiet(&mut tool);
2c00a5a8
XL
1535 markdown_test(builder, compiler, &output);
1536 }
1537}
1538
9fa01778 1539fn markdown_test(builder: &Builder<'_>, compiler: Compiler, markdown: &Path) -> bool {
0731742a
XL
1540 match fs::read_to_string(markdown) {
1541 Ok(contents) => {
83c7162d
XL
1542 if !contents.contains("```") {
1543 return true;
1544 }
1545 }
94b46f34 1546 Err(_) => {}
2c00a5a8
XL
1547 }
1548
83c7162d 1549 builder.info(&format!("doc tests for: {}", markdown.display()));
532ac7d7 1550 let mut cmd = builder.rustdoc_cmd(compiler);
83c7162d 1551 builder.add_rust_test_threads(&mut cmd);
2c00a5a8
XL
1552 cmd.arg("--test");
1553 cmd.arg(markdown);
1554 cmd.env("RUSTC_BOOTSTRAP", "1");
1555
83c7162d 1556 let test_args = builder.config.cmd.test_args().join(" ");
2c00a5a8
XL
1557 cmd.arg("--test-args").arg(test_args);
1558
94b46f34 1559 if builder.config.verbose_tests {
83c7162d 1560 try_run(builder, &mut cmd)
94b46f34
XL
1561 } else {
1562 try_run_quiet(builder, &mut cmd)
2c00a5a8
XL
1563 }
1564}
1565
416331ca
XL
1566#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1567pub struct RustcGuide;
1568
1569impl Step for RustcGuide {
1570 type Output = ();
1571 const DEFAULT: bool = false;
1572 const ONLY_HOSTS: bool = true;
1573
1574 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1575 run.path("src/doc/rustc-guide")
1576 }
1577
1578 fn make_run(run: RunConfig<'_>) {
1579 run.builder.ensure(RustcGuide);
1580 }
1581
1582 fn run(self, builder: &Builder<'_>) {
1583 let src = builder.src.join("src/doc/rustc-guide");
1584 let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook);
1585 let toolstate = if try_run(builder, rustbook_cmd.arg("linkcheck").arg(&src)) {
1586 ToolState::TestPass
1587 } else {
1588 ToolState::TestFail
1589 };
1590 builder.save_toolstate("rustc-guide", toolstate);
1591 }
1592}
1593
2c00a5a8
XL
1594#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1595pub struct CrateLibrustc {
1596 compiler: Compiler,
1597 target: Interned<String>,
1598 test_kind: TestKind,
1599 krate: Interned<String>,
1600}
1601
1602impl Step for CrateLibrustc {
1603 type Output = ();
1604 const DEFAULT: bool = true;
1605 const ONLY_HOSTS: bool = true;
1606
9fa01778 1607 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2c00a5a8
XL
1608 run.krate("rustc-main")
1609 }
1610
9fa01778 1611 fn make_run(run: RunConfig<'_>) {
2c00a5a8
XL
1612 let builder = run.builder;
1613 let compiler = builder.compiler(builder.top_stage, run.host);
1614
1615 for krate in builder.in_tree_crates("rustc-main") {
1616 if run.path.ends_with(&krate.path) {
94b46f34 1617 let test_kind = builder.kind.into();
2c00a5a8
XL
1618
1619 builder.ensure(CrateLibrustc {
1620 compiler,
1621 target: run.target,
1622 test_kind,
1623 krate: krate.name,
1624 });
1625 }
1626 }
1627 }
1628
9fa01778 1629 fn run(self, builder: &Builder<'_>) {
2c00a5a8
XL
1630 builder.ensure(Crate {
1631 compiler: self.compiler,
1632 target: self.target,
94b46f34 1633 mode: Mode::Rustc,
2c00a5a8
XL
1634 test_kind: self.test_kind,
1635 krate: self.krate,
1636 });
1637 }
1638}
1639
1640#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1641pub struct CrateNotDefault {
1642 compiler: Compiler,
1643 target: Interned<String>,
1644 test_kind: TestKind,
1645 krate: &'static str,
1646}
1647
1648impl Step for CrateNotDefault {
1649 type Output = ();
1650
9fa01778 1651 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
a1dfa0c6 1652 run.path("src/librustc_asan")
2c00a5a8
XL
1653 .path("src/librustc_lsan")
1654 .path("src/librustc_msan")
1655 .path("src/librustc_tsan")
1656 }
1657
9fa01778 1658 fn make_run(run: RunConfig<'_>) {
2c00a5a8
XL
1659 let builder = run.builder;
1660 let compiler = builder.compiler(builder.top_stage, run.host);
1661
94b46f34 1662 let test_kind = builder.kind.into();
2c00a5a8
XL
1663
1664 builder.ensure(CrateNotDefault {
1665 compiler,
1666 target: run.target,
1667 test_kind,
1668 krate: match run.path {
2c00a5a8
XL
1669 _ if run.path.ends_with("src/librustc_asan") => "rustc_asan",
1670 _ if run.path.ends_with("src/librustc_lsan") => "rustc_lsan",
1671 _ if run.path.ends_with("src/librustc_msan") => "rustc_msan",
1672 _ if run.path.ends_with("src/librustc_tsan") => "rustc_tsan",
1673 _ => panic!("unexpected path {:?}", run.path),
1674 },
1675 });
1676 }
1677
9fa01778 1678 fn run(self, builder: &Builder<'_>) {
2c00a5a8
XL
1679 builder.ensure(Crate {
1680 compiler: self.compiler,
1681 target: self.target,
94b46f34 1682 mode: Mode::Std,
2c00a5a8
XL
1683 test_kind: self.test_kind,
1684 krate: INTERNER.intern_str(self.krate),
1685 });
1686 }
1687}
1688
83c7162d 1689#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
2c00a5a8 1690pub struct Crate {
83c7162d
XL
1691 pub compiler: Compiler,
1692 pub target: Interned<String>,
1693 pub mode: Mode,
1694 pub test_kind: TestKind,
1695 pub krate: Interned<String>,
2c00a5a8
XL
1696}
1697
1698impl Step for Crate {
1699 type Output = ();
1700 const DEFAULT: bool = true;
1701
9fa01778 1702 fn should_run(mut run: ShouldRun<'_>) -> ShouldRun<'_> {
2c00a5a8 1703 let builder = run.builder;
e1599b0c 1704 for krate in run.builder.in_tree_crates("test") {
0731742a 1705 if !(krate.name.starts_with("rustc_") && krate.name.ends_with("san")) {
2c00a5a8
XL
1706 run = run.path(krate.local_path(&builder).to_str().unwrap());
1707 }
1708 }
1709 run
1710 }
1711
9fa01778 1712 fn make_run(run: RunConfig<'_>) {
2c00a5a8
XL
1713 let builder = run.builder;
1714 let compiler = builder.compiler(builder.top_stage, run.host);
1715
1716 let make = |mode: Mode, krate: &CargoCrate| {
94b46f34 1717 let test_kind = builder.kind.into();
2c00a5a8
XL
1718
1719 builder.ensure(Crate {
1720 compiler,
1721 target: run.target,
1722 mode,
1723 test_kind,
1724 krate: krate.name,
1725 });
1726 };
1727
2c00a5a8
XL
1728 for krate in builder.in_tree_crates("test") {
1729 if run.path.ends_with(&krate.local_path(&builder)) {
e1599b0c 1730 make(Mode::Std, krate);
2c00a5a8
XL
1731 }
1732 }
1733 }
1734
9fa01778 1735 /// Runs all unit tests plus documentation tests for a given crate defined
2c00a5a8
XL
1736 /// by a `Cargo.toml` (single manifest)
1737 ///
1738 /// This is what runs tests for crates like the standard library, compiler, etc.
1739 /// It essentially is the driver for running `cargo test`.
1740 ///
1741 /// Currently this runs all tests for a DAG by passing a bunch of `-p foo`
1742 /// arguments, and those arguments are discovered from `cargo metadata`.
9fa01778 1743 fn run(self, builder: &Builder<'_>) {
2c00a5a8
XL
1744 let compiler = self.compiler;
1745 let target = self.target;
1746 let mode = self.mode;
1747 let test_kind = self.test_kind;
1748 let krate = self.krate;
1749
e1599b0c 1750 builder.ensure(compile::Std { compiler, target });
2c00a5a8
XL
1751 builder.ensure(RemoteCopyLibs { compiler, target });
1752
dc9dc135
XL
1753 // If we're not doing a full bootstrap but we're testing a stage2
1754 // version of libstd, then what we're actually testing is the libstd
1755 // produced in stage1. Reflect that here by updating the compiler that
1756 // we're working with automatically.
1757 let compiler = builder.compiler_for(compiler.stage, compiler.host, target);
2c00a5a8
XL
1758
1759 let mut cargo = builder.cargo(compiler, mode, target, test_kind.subcommand());
1760 match mode {
94b46f34 1761 Mode::Std => {
0531ce1d 1762 compile::std_cargo(builder, &compiler, target, &mut cargo);
2c00a5a8 1763 }
94b46f34 1764 Mode::Rustc => {
2c00a5a8 1765 builder.ensure(compile::Rustc { compiler, target });
83c7162d 1766 compile::rustc_cargo(builder, &mut cargo);
2c00a5a8
XL
1767 }
1768 _ => panic!("can only test libraries"),
1769 };
2c00a5a8
XL
1770
1771 // Build up the base `cargo test` command.
1772 //
1773 // Pass in some standard flags then iterate over the graph we've discovered
1774 // in `cargo metadata` with the maps above and figure out what `-p`
1775 // arguments need to get passed.
83c7162d 1776 if test_kind.subcommand() == "test" && !builder.fail_fast {
2c00a5a8
XL
1777 cargo.arg("--no-fail-fast");
1778 }
83c7162d
XL
1779 match builder.doc_tests {
1780 DocTests::Only => {
1781 cargo.arg("--doc");
1782 }
1783 DocTests::No => {
1784 cargo.args(&["--lib", "--bins", "--examples", "--tests", "--benches"]);
1785 }
1786 DocTests::Yes => {}
0531ce1d 1787 }
2c00a5a8
XL
1788
1789 cargo.arg("-p").arg(krate);
1790
1791 // The tests are going to run with the *target* libraries, so we need to
1792 // ensure that those libraries show up in the LD_LIBRARY_PATH equivalent.
1793 //
1794 // Note that to run the compiler we need to run with the *host* libraries,
1795 // but our wrapper scripts arrange for that to be the case anyway.
1796 let mut dylib_path = dylib_path();
1797 dylib_path.insert(0, PathBuf::from(&*builder.sysroot_libdir(compiler, target)));
1798 cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());
1799
1800 cargo.arg("--");
83c7162d 1801 cargo.args(&builder.config.cmd.test_args());
2c00a5a8 1802
94b46f34 1803 if !builder.config.verbose_tests {
2c00a5a8
XL
1804 cargo.arg("--quiet");
1805 }
1806
2c00a5a8 1807 if target.contains("emscripten") {
94b46f34
XL
1808 cargo.env(
1809 format!("CARGO_TARGET_{}_RUNNER", envify(&target)),
1810 builder
1811 .config
1812 .nodejs
1813 .as_ref()
1814 .expect("nodejs not configured"),
1815 );
2c00a5a8 1816 } else if target.starts_with("wasm32") {
94b46f34
XL
1817 let node = builder
1818 .config
1819 .nodejs
1820 .as_ref()
2c00a5a8 1821 .expect("nodejs not configured");
94b46f34
XL
1822 let runner = format!(
1823 "{} {}/src/etc/wasm32-shim.js",
1824 node.display(),
1825 builder.src.display()
1826 );
2c00a5a8 1827 cargo.env(format!("CARGO_TARGET_{}_RUNNER", envify(&target)), &runner);
83c7162d 1828 } else if builder.remote_tested(target) {
94b46f34
XL
1829 cargo.env(
1830 format!("CARGO_TARGET_{}_RUNNER", envify(&target)),
1831 format!("{} run", builder.tool_exe(Tool::RemoteTestClient).display()),
1832 );
2c00a5a8 1833 }
0531ce1d 1834
94b46f34
XL
1835 builder.info(&format!(
1836 "{} {} stage{} ({} -> {})",
1837 test_kind, krate, compiler.stage, &compiler.host, target
1838 ));
83c7162d 1839 let _time = util::timeit(&builder);
e1599b0c 1840 try_run(builder, &mut cargo.into());
2c00a5a8
XL
1841 }
1842}
1843
1844#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1845pub struct CrateRustdoc {
1846 host: Interned<String>,
1847 test_kind: TestKind,
1848}
1849
1850impl Step for CrateRustdoc {
1851 type Output = ();
1852 const DEFAULT: bool = true;
1853 const ONLY_HOSTS: bool = true;
1854
9fa01778 1855 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2c00a5a8
XL
1856 run.paths(&["src/librustdoc", "src/tools/rustdoc"])
1857 }
1858
9fa01778 1859 fn make_run(run: RunConfig<'_>) {
2c00a5a8
XL
1860 let builder = run.builder;
1861
94b46f34 1862 let test_kind = builder.kind.into();
2c00a5a8
XL
1863
1864 builder.ensure(CrateRustdoc {
1865 host: run.host,
1866 test_kind,
1867 });
1868 }
1869
9fa01778 1870 fn run(self, builder: &Builder<'_>) {
2c00a5a8
XL
1871 let test_kind = self.test_kind;
1872
1873 let compiler = builder.compiler(builder.top_stage, self.host);
1874 let target = compiler.host;
8faf50e0 1875 builder.ensure(compile::Rustc { compiler, target });
2c00a5a8
XL
1876
1877 let mut cargo = tool::prepare_tool_cargo(builder,
1878 compiler,
94b46f34 1879 Mode::ToolRustc,
2c00a5a8
XL
1880 target,
1881 test_kind.subcommand(),
8faf50e0 1882 "src/tools/rustdoc",
0bf4aa26
XL
1883 SourceType::InTree,
1884 &[]);
83c7162d 1885 if test_kind.subcommand() == "test" && !builder.fail_fast {
2c00a5a8
XL
1886 cargo.arg("--no-fail-fast");
1887 }
1888
1889 cargo.arg("-p").arg("rustdoc:0.0.0");
1890
1891 cargo.arg("--");
83c7162d 1892 cargo.args(&builder.config.cmd.test_args());
2c00a5a8 1893
48663c56
XL
1894 if self.host.contains("musl") {
1895 cargo.arg("'-Ctarget-feature=-crt-static'");
1896 }
1897
94b46f34 1898 if !builder.config.verbose_tests {
2c00a5a8
XL
1899 cargo.arg("--quiet");
1900 }
1901
94b46f34
XL
1902 builder.info(&format!(
1903 "{} rustdoc stage{} ({} -> {})",
1904 test_kind, compiler.stage, &compiler.host, target
1905 ));
83c7162d 1906 let _time = util::timeit(&builder);
2c00a5a8 1907
e1599b0c 1908 try_run(builder, &mut cargo.into());
2c00a5a8
XL
1909 }
1910}
1911
2c00a5a8
XL
1912/// Some test suites are run inside emulators or on remote devices, and most
1913/// of our test binaries are linked dynamically which means we need to ship
1914/// the standard library and such to the emulator ahead of time. This step
1915/// represents this and is a dependency of all test suites.
1916///
9fa01778 1917/// Most of the time this is a no-op. For some steps such as shipping data to
2c00a5a8
XL
1918/// QEMU we have to build our own tools so we've got conditional dependencies
1919/// on those programs as well. Note that the remote test client is built for
1920/// the build target (us) and the server is built for the target.
1921#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1922pub struct RemoteCopyLibs {
1923 compiler: Compiler,
1924 target: Interned<String>,
1925}
1926
1927impl Step for RemoteCopyLibs {
1928 type Output = ();
1929
9fa01778 1930 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2c00a5a8
XL
1931 run.never()
1932 }
1933
9fa01778 1934 fn run(self, builder: &Builder<'_>) {
2c00a5a8
XL
1935 let compiler = self.compiler;
1936 let target = self.target;
83c7162d 1937 if !builder.remote_tested(target) {
94b46f34 1938 return;
2c00a5a8
XL
1939 }
1940
e1599b0c 1941 builder.ensure(compile::Std { compiler, target });
2c00a5a8 1942
83c7162d
XL
1943 builder.info(&format!("REMOTE copy libs to emulator ({})", target));
1944 t!(fs::create_dir_all(builder.out.join("tmp")));
2c00a5a8 1945
8faf50e0
XL
1946 let server = builder.ensure(tool::RemoteTestServer {
1947 compiler: compiler.with_stage(0),
1948 target,
1949 });
2c00a5a8
XL
1950
1951 // Spawn the emulator and wait for it to come online
1952 let tool = builder.tool_exe(Tool::RemoteTestClient);
1953 let mut cmd = Command::new(&tool);
1954 cmd.arg("spawn-emulator")
94b46f34
XL
1955 .arg(target)
1956 .arg(&server)
1957 .arg(builder.out.join("tmp"));
83c7162d 1958 if let Some(rootfs) = builder.qemu_rootfs(target) {
2c00a5a8
XL
1959 cmd.arg(rootfs);
1960 }
83c7162d 1961 builder.run(&mut cmd);
2c00a5a8
XL
1962
1963 // Push all our dylibs to the emulator
1964 for f in t!(builder.sysroot_libdir(compiler, target).read_dir()) {
1965 let f = t!(f);
1966 let name = f.file_name().into_string().unwrap();
1967 if util::is_dylib(&name) {
94b46f34 1968 builder.run(Command::new(&tool).arg("push").arg(f.path()));
2c00a5a8
XL
1969 }
1970 }
1971 }
1972}
1973
1974#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1975pub struct Distcheck;
1976
1977impl Step for Distcheck {
1978 type Output = ();
2c00a5a8 1979
9fa01778 1980 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2c00a5a8
XL
1981 run.path("distcheck")
1982 }
1983
9fa01778 1984 fn make_run(run: RunConfig<'_>) {
2c00a5a8
XL
1985 run.builder.ensure(Distcheck);
1986 }
1987
9fa01778
XL
1988 /// Runs "distcheck", a 'make check' from a tarball
1989 fn run(self, builder: &Builder<'_>) {
a1dfa0c6 1990 builder.info("Distcheck");
83c7162d 1991 let dir = builder.out.join("tmp").join("distcheck");
2c00a5a8
XL
1992 let _ = fs::remove_dir_all(&dir);
1993 t!(fs::create_dir_all(&dir));
1994
1995 // Guarantee that these are built before we begin running.
1996 builder.ensure(dist::PlainSourceTarball);
1997 builder.ensure(dist::Src);
1998
1999 let mut cmd = Command::new("tar");
2000 cmd.arg("-xzf")
94b46f34
XL
2001 .arg(builder.ensure(dist::PlainSourceTarball))
2002 .arg("--strip-components=1")
2003 .current_dir(&dir);
83c7162d 2004 builder.run(&mut cmd);
94b46f34
XL
2005 builder.run(
2006 Command::new("./configure")
2007 .args(&builder.config.configure_args)
2008 .arg("--enable-vendor")
2009 .current_dir(&dir),
2010 );
2011 builder.run(
2012 Command::new(build_helper::make(&builder.config.build))
2013 .arg("check")
2014 .current_dir(&dir),
2015 );
2c00a5a8
XL
2016
2017 // Now make sure that rust-src has all of libstd's dependencies
a1dfa0c6 2018 builder.info("Distcheck rust-src");
83c7162d 2019 let dir = builder.out.join("tmp").join("distcheck-src");
2c00a5a8
XL
2020 let _ = fs::remove_dir_all(&dir);
2021 t!(fs::create_dir_all(&dir));
2022
2023 let mut cmd = Command::new("tar");
2024 cmd.arg("-xzf")
94b46f34
XL
2025 .arg(builder.ensure(dist::Src))
2026 .arg("--strip-components=1")
2027 .current_dir(&dir);
83c7162d 2028 builder.run(&mut cmd);
2c00a5a8
XL
2029
2030 let toml = dir.join("rust-src/lib/rustlib/src/rust/src/libstd/Cargo.toml");
94b46f34
XL
2031 builder.run(
2032 Command::new(&builder.initial_cargo)
2033 .arg("generate-lockfile")
2034 .arg("--manifest-path")
2035 .arg(&toml)
2036 .current_dir(&dir),
2037 );
2c00a5a8
XL
2038 }
2039}
2040
2041#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
2042pub struct Bootstrap;
2043
2044impl Step for Bootstrap {
2045 type Output = ();
2046 const DEFAULT: bool = true;
2047 const ONLY_HOSTS: bool = true;
2c00a5a8 2048
9fa01778
XL
2049 /// Tests the build system itself.
2050 fn run(self, builder: &Builder<'_>) {
83c7162d 2051 let mut cmd = Command::new(&builder.initial_cargo);
2c00a5a8 2052 cmd.arg("test")
94b46f34
XL
2053 .current_dir(builder.src.join("src/bootstrap"))
2054 .env("RUSTFLAGS", "-Cdebuginfo=2")
2055 .env("CARGO_TARGET_DIR", builder.out.join("bootstrap"))
2056 .env("RUSTC_BOOTSTRAP", "1")
2057 .env("RUSTC", &builder.initial_rustc);
0531ce1d
XL
2058 if let Some(flags) = option_env!("RUSTFLAGS") {
2059 // Use the same rustc flags for testing as for "normal" compilation,
2060 // so that Cargo doesn’t recompile the entire dependency graph every time:
2061 // https://github.com/rust-lang/rust/issues/49215
2062 cmd.env("RUSTFLAGS", flags);
2063 }
83c7162d 2064 if !builder.fail_fast {
2c00a5a8
XL
2065 cmd.arg("--no-fail-fast");
2066 }
83c7162d 2067 cmd.arg("--").args(&builder.config.cmd.test_args());
94b46f34
XL
2068 // rustbuild tests are racy on directory creation so just run them one at a time.
2069 // Since there's not many this shouldn't be a problem.
2070 cmd.arg("--test-threads=1");
83c7162d 2071 try_run(builder, &mut cmd);
2c00a5a8
XL
2072 }
2073
9fa01778 2074 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2c00a5a8
XL
2075 run.path("src/bootstrap")
2076 }
2077
9fa01778 2078 fn make_run(run: RunConfig<'_>) {
2c00a5a8
XL
2079 run.builder.ensure(Bootstrap);
2080 }
2081}