1 //! Implementation of the test-related targets of the build system.
3 //! This file implements the various regression test suites that we execute on
7 use std
::ffi
::OsString
;
11 use std
::path
::{Path, PathBuf}
;
12 use std
::process
::{Command, Stdio}
;
14 use build_helper
::{self, output, t}
;
16 use crate::builder
::{Builder, Compiler, Kind, RunConfig, ShouldRun, Step}
;
17 use crate::cache
::Interned
;
19 use crate::config
::TargetSelection
;
21 use crate::flags
::Subcommand
;
23 use crate::tool
::{self, SourceType, Tool}
;
24 use crate::toolstate
::ToolState
;
25 use crate::util
::{self, add_link_lib_path, dylib_path, dylib_path_var}
;
26 use crate::Crate
as CargoCrate
;
27 use crate::{envify, CLang, DocTests, GitRepo, Mode}
;
29 const ADB_TEST_DIR
: &str = "/data/tmp/work";
31 /// The two modes of the test runner; tests or benchmarks.
32 #[derive(Debug, PartialEq, Eq, Hash, Copy, Clone, PartialOrd, Ord)]
36 /// Run `cargo bench`.
40 impl From
<Kind
> for TestKind
{
41 fn from(kind
: Kind
) -> Self {
43 Kind
::Test
=> TestKind
::Test
,
44 Kind
::Bench
=> TestKind
::Bench
,
45 _
=> panic
!("unexpected kind in crate: {:?}", kind
),
51 // Return the cargo subcommand for this test kind
52 fn subcommand(self) -> &'
static str {
54 TestKind
::Test
=> "test",
55 TestKind
::Bench
=> "bench",
60 impl fmt
::Display
for TestKind
{
61 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
62 f
.write_str(match *self {
63 TestKind
::Test
=> "Testing",
64 TestKind
::Bench
=> "Benchmarking",
69 fn try_run(builder
: &Builder
<'_
>, cmd
: &mut Command
) -> bool
{
70 if !builder
.fail_fast
{
71 if !builder
.try_run(cmd
) {
72 let mut failures
= builder
.delayed_failures
.borrow_mut();
73 failures
.push(format
!("{:?}", cmd
));
82 fn try_run_quiet(builder
: &Builder
<'_
>, cmd
: &mut Command
) -> bool
{
83 if !builder
.fail_fast
{
84 if !builder
.try_run_quiet(cmd
) {
85 let mut failures
= builder
.delayed_failures
.borrow_mut();
86 failures
.push(format
!("{:?}", cmd
));
90 builder
.run_quiet(cmd
);
95 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
96 pub struct Linkcheck
{
97 host
: TargetSelection
,
100 impl Step
for Linkcheck
{
102 const ONLY_HOSTS
: bool
= true;
103 const DEFAULT
: bool
= true;
105 /// Runs the `linkchecker` tool as compiled in `stage` by the `host` compiler.
107 /// This tool in `src/tools` will verify the validity of all our links in the
108 /// documentation to ensure we don't have a bunch of dead ones.
109 fn run(self, builder
: &Builder
<'_
>) {
110 let host
= self.host
;
111 let hosts
= &builder
.hosts
;
112 let targets
= &builder
.targets
;
114 // if we have different hosts and targets, some things may be built for
115 // the host (e.g. rustc) and others for the target (e.g. std). The
116 // documentation built for each will contain broken links to
117 // docs built for the other platform (e.g. rustc linking to cargo)
118 if (hosts
!= targets
) && !hosts
.is_empty() && !targets
.is_empty() {
120 "Linkcheck currently does not support builds with different hosts and targets.
121 You can skip linkcheck with --exclude src/tools/linkchecker"
125 builder
.info(&format
!("Linkcheck ({})", host
));
127 // Test the linkchecker itself.
128 let bootstrap_host
= builder
.config
.build
;
129 let compiler
= builder
.compiler(0, bootstrap_host
);
130 let cargo
= tool
::prepare_tool_cargo(
136 "src/tools/linkchecker",
140 try_run(builder
, &mut cargo
.into());
142 // Build all the default documentation.
143 builder
.default_doc(&[]);
145 // Run the linkchecker.
146 let _time
= util
::timeit(&builder
);
149 builder
.tool_cmd(Tool
::Linkchecker
).arg(builder
.out
.join(host
.triple
).join("doc")),
153 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
154 let builder
= run
.builder
;
155 let run
= run
.path("src/tools/linkchecker");
156 run
.default_condition(builder
.config
.docs
)
159 fn make_run(run
: RunConfig
<'_
>) {
160 run
.builder
.ensure(Linkcheck { host: run.target }
);
164 fn check_if_tidy_is_installed() -> bool
{
167 .stdout(Stdio
::null())
169 .map_or(false, |status
| status
.success())
172 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
173 pub struct HtmlCheck
{
174 target
: TargetSelection
,
177 impl Step
for HtmlCheck
{
179 const DEFAULT
: bool
= true;
180 const ONLY_HOSTS
: bool
= true;
182 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
183 let run
= run
.path("src/tools/html-checker");
184 run
.lazy_default_condition(Box
::new(check_if_tidy_is_installed
))
187 fn make_run(run
: RunConfig
<'_
>) {
188 run
.builder
.ensure(HtmlCheck { target: run.target }
);
191 fn run(self, builder
: &Builder
<'_
>) {
192 if !check_if_tidy_is_installed() {
193 eprintln
!("not running HTML-check tool because `tidy` is missing");
195 "Note that `tidy` is not the in-tree `src/tools/tidy` but needs to be installed"
197 panic
!("Cannot run html-check tests");
199 // Ensure that a few different kinds of documentation are available.
200 builder
.default_doc(&[]);
201 builder
.ensure(crate::doc
::Rustc { target: self.target, stage: builder.top_stage }
);
203 try_run(builder
, builder
.tool_cmd(Tool
::HtmlChecker
).arg(builder
.doc_out(self.target
)));
207 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
208 pub struct Cargotest
{
210 host
: TargetSelection
,
213 impl Step
for Cargotest
{
215 const ONLY_HOSTS
: bool
= true;
217 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
218 run
.path("src/tools/cargotest")
221 fn make_run(run
: RunConfig
<'_
>) {
222 run
.builder
.ensure(Cargotest { stage: run.builder.top_stage, host: run.target }
);
225 /// Runs the `cargotest` tool as compiled in `stage` by the `host` compiler.
227 /// This tool in `src/tools` will check out a few Rust projects and run `cargo
228 /// test` to ensure that we don't regress the test suites there.
229 fn run(self, builder
: &Builder
<'_
>) {
230 let compiler
= builder
.compiler(self.stage
, self.host
);
231 builder
.ensure(compile
::Rustc { compiler, target: compiler.host }
);
232 let cargo
= builder
.ensure(tool
::Cargo { compiler, target: compiler.host }
);
234 // Note that this is a short, cryptic, and not scoped directory name. This
235 // is currently to minimize the length of path on Windows where we otherwise
236 // quickly run into path name limit constraints.
237 let out_dir
= builder
.out
.join("ct");
238 t
!(fs
::create_dir_all(&out_dir
));
240 let _time
= util
::timeit(&builder
);
241 let mut cmd
= builder
.tool_cmd(Tool
::CargoTest
);
246 .args(builder
.config
.cmd
.test_args())
247 .env("RUSTC", builder
.rustc(compiler
))
248 .env("RUSTDOC", builder
.rustdoc(compiler
)),
253 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
256 host
: TargetSelection
,
259 impl Step
for Cargo
{
261 const ONLY_HOSTS
: bool
= true;
263 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
264 run
.path("src/tools/cargo")
267 fn make_run(run
: RunConfig
<'_
>) {
268 run
.builder
.ensure(Cargo { stage: run.builder.top_stage, host: run.target }
);
271 /// Runs `cargo test` for `cargo` packaged with Rust.
272 fn run(self, builder
: &Builder
<'_
>) {
273 let compiler
= builder
.compiler(self.stage
, self.host
);
275 builder
.ensure(tool
::Cargo { compiler, target: self.host }
);
276 let mut cargo
= tool
::prepare_tool_cargo(
283 SourceType
::Submodule
,
287 if !builder
.fail_fast
{
288 cargo
.arg("--no-fail-fast");
290 cargo
.arg("--").args(builder
.config
.cmd
.test_args());
292 // Don't run cross-compile tests, we may not have cross-compiled libstd libs
294 cargo
.env("CFG_DISABLE_CROSS_TESTS", "1");
295 // Disable a test that has issues with mingw.
296 cargo
.env("CARGO_TEST_DISABLE_GIT_CLI", "1");
297 // Forcibly disable tests using nightly features since any changes to
298 // those features won't be able to land.
299 cargo
.env("CARGO_TEST_DISABLE_NIGHTLY", "1");
301 cargo
.env("PATH", &path_for_cargo(builder
, compiler
));
303 try_run(builder
, &mut cargo
.into());
307 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
310 host
: TargetSelection
,
315 const ONLY_HOSTS
: bool
= true;
317 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
318 run
.path("src/tools/rls")
321 fn make_run(run
: RunConfig
<'_
>) {
322 run
.builder
.ensure(Rls { stage: run.builder.top_stage, host: run.target }
);
325 /// Runs `cargo test` for the rls.
326 fn run(self, builder
: &Builder
<'_
>) {
327 let stage
= self.stage
;
328 let host
= self.host
;
329 let compiler
= builder
.compiler(stage
, host
);
332 builder
.ensure(tool
::Rls { compiler, target: self.host, extra_features: Vec::new() }
);
333 if build_result
.is_none() {
334 eprintln
!("failed to test rls: could not build");
338 let mut cargo
= tool
::prepare_tool_cargo(
345 SourceType
::Submodule
,
349 cargo
.add_rustc_lib_path(builder
, compiler
);
350 cargo
.arg("--").args(builder
.config
.cmd
.test_args());
352 if try_run(builder
, &mut cargo
.into()) {
353 builder
.save_toolstate("rls", ToolState
::TestPass
);
358 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
361 host
: TargetSelection
,
364 impl Step
for Rustfmt
{
366 const ONLY_HOSTS
: bool
= true;
368 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
369 run
.path("src/tools/rustfmt")
372 fn make_run(run
: RunConfig
<'_
>) {
373 run
.builder
.ensure(Rustfmt { stage: run.builder.top_stage, host: run.target }
);
376 /// Runs `cargo test` for rustfmt.
377 fn run(self, builder
: &Builder
<'_
>) {
378 let stage
= self.stage
;
379 let host
= self.host
;
380 let compiler
= builder
.compiler(stage
, host
);
383 .ensure(tool
::Rustfmt { compiler, target: self.host, extra_features: Vec::new() }
)
384 .expect("in-tree tool");
386 let mut cargo
= tool
::prepare_tool_cargo(
397 let dir
= testdir(builder
, compiler
.host
);
398 t
!(fs
::create_dir_all(&dir
));
399 cargo
.env("RUSTFMT_TEST_DIR", dir
);
401 cargo
.add_rustc_lib_path(builder
, compiler
);
403 builder
.run(&mut cargo
.into());
407 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
408 pub struct RustDemangler
{
410 host
: TargetSelection
,
413 impl Step
for RustDemangler
{
415 const ONLY_HOSTS
: bool
= true;
417 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
418 run
.path("src/tools/rust-demangler")
421 fn make_run(run
: RunConfig
<'_
>) {
422 run
.builder
.ensure(RustDemangler { stage: run.builder.top_stage, host: run.target }
);
425 /// Runs `cargo test` for rust-demangler.
426 fn run(self, builder
: &Builder
<'_
>) {
427 let stage
= self.stage
;
428 let host
= self.host
;
429 let compiler
= builder
.compiler(stage
, host
);
431 let rust_demangler
= builder
432 .ensure(tool
::RustDemangler { compiler, target: self.host, extra_features: Vec::new() }
)
433 .expect("in-tree tool");
434 let mut cargo
= tool
::prepare_tool_cargo(
440 "src/tools/rust-demangler",
445 let dir
= testdir(builder
, compiler
.host
);
446 t
!(fs
::create_dir_all(&dir
));
448 cargo
.env("RUST_DEMANGLER_DRIVER_PATH", rust_demangler
);
450 cargo
.arg("--").args(builder
.config
.cmd
.test_args());
452 cargo
.add_rustc_lib_path(builder
, compiler
);
454 builder
.run(&mut cargo
.into());
458 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
461 host
: TargetSelection
,
466 const ONLY_HOSTS
: bool
= true;
468 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
469 run
.path("src/tools/miri")
472 fn make_run(run
: RunConfig
<'_
>) {
473 run
.builder
.ensure(Miri { stage: run.builder.top_stage, host: run.target }
);
476 /// Runs `cargo test` for miri.
477 fn run(self, builder
: &Builder
<'_
>) {
478 let stage
= self.stage
;
479 let host
= self.host
;
480 let compiler
= builder
.compiler(stage
, host
);
483 builder
.ensure(tool
::Miri { compiler, target: self.host, extra_features: Vec::new() }
);
484 let cargo_miri
= builder
.ensure(tool
::CargoMiri
{
487 extra_features
: Vec
::new(),
489 if let (Some(miri
), Some(_cargo_miri
)) = (miri
, cargo_miri
) {
491 builder
.cargo(compiler
, Mode
::ToolRustc
, SourceType
::Submodule
, host
, "install");
493 // Configure `cargo install` path. cargo adds a `bin/`.
494 cargo
.env("CARGO_INSTALL_ROOT", &builder
.out
);
496 let mut cargo
= Command
::from(cargo
);
497 if !try_run(builder
, &mut cargo
) {
501 // # Run `cargo miri setup`.
502 let mut cargo
= tool
::prepare_tool_cargo(
508 "src/tools/miri/cargo-miri",
509 SourceType
::Submodule
,
512 cargo
.add_rustc_lib_path(builder
, compiler
);
513 cargo
.arg("--").arg("miri").arg("setup");
515 // Tell `cargo miri setup` where to find the sources.
516 cargo
.env("XARGO_RUST_SRC", builder
.src
.join("library"));
517 // Tell it where to find Miri.
518 cargo
.env("MIRI", &miri
);
520 cargo
.env("RUST_BACKTRACE", "1");
521 // Let cargo-miri know where xargo ended up.
522 cargo
.env("XARGO_CHECK", builder
.out
.join("bin").join("xargo-check"));
524 let mut cargo
= Command
::from(cargo
);
525 if !try_run(builder
, &mut cargo
) {
529 // # Determine where Miri put its sysroot.
530 // To this end, we run `cargo miri setup --print-sysroot` and capture the output.
531 // (We do this separately from the above so that when the setup actually
532 // happens we get some output.)
533 // We re-use the `cargo` from above.
534 cargo
.arg("--print-sysroot");
536 // FIXME: Is there a way in which we can re-use the usual `run` helpers?
537 let miri_sysroot
= if builder
.config
.dry_run
{
540 builder
.verbose(&format
!("running: {:?}", cargo
));
543 .expect("We already ran `cargo miri setup` before and that worked");
544 assert
!(out
.status
.success(), "`cargo miri setup` returned with non-0 exit code");
545 // Output is "<sysroot>\n".
546 let stdout
= String
::from_utf8(out
.stdout
)
547 .expect("`cargo miri setup` stdout is not valid UTF-8");
548 let sysroot
= stdout
.trim_end();
549 builder
.verbose(&format
!("`cargo miri setup --print-sysroot` said: {:?}", sysroot
));
553 // # Run `cargo test`.
554 let mut cargo
= tool
::prepare_tool_cargo(
561 SourceType
::Submodule
,
564 cargo
.add_rustc_lib_path(builder
, compiler
);
566 // miri tests need to know about the stage sysroot
567 cargo
.env("MIRI_SYSROOT", miri_sysroot
);
568 cargo
.env("RUSTC_LIB_PATH", builder
.rustc_libdir(compiler
));
569 cargo
.env("MIRI", miri
);
571 cargo
.arg("--").args(builder
.config
.cmd
.test_args());
573 let mut cargo
= Command
::from(cargo
);
574 if !try_run(builder
, &mut cargo
) {
578 // # Run `cargo test` with `-Zmir-opt-level=4`.
579 cargo
.env("MIRIFLAGS", "-O -Zmir-opt-level=4");
580 if !try_run(builder
, &mut cargo
) {
585 builder
.save_toolstate("miri", ToolState
::TestPass
);
587 eprintln
!("failed to test miri: could not build");
592 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
593 pub struct CompiletestTest
{
594 host
: TargetSelection
,
597 impl Step
for CompiletestTest
{
600 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
601 run
.path("src/tools/compiletest")
604 fn make_run(run
: RunConfig
<'_
>) {
605 run
.builder
.ensure(CompiletestTest { host: run.target }
);
608 /// Runs `cargo test` for compiletest.
609 fn run(self, builder
: &Builder
<'_
>) {
610 let host
= self.host
;
611 let compiler
= builder
.compiler(0, host
);
613 // We need `ToolStd` for the locally-built sysroot because
614 // compiletest uses unstable features of the `test` crate.
615 builder
.ensure(compile
::Std { compiler, target: host }
);
616 let cargo
= tool
::prepare_tool_cargo(
622 "src/tools/compiletest",
627 try_run(builder
, &mut cargo
.into());
631 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
634 host
: TargetSelection
,
637 impl Step
for Clippy
{
639 const ONLY_HOSTS
: bool
= true;
640 const DEFAULT
: bool
= false;
642 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
643 run
.path("src/tools/clippy")
646 fn make_run(run
: RunConfig
<'_
>) {
647 run
.builder
.ensure(Clippy { stage: run.builder.top_stage, host: run.target }
);
650 /// Runs `cargo test` for clippy.
651 fn run(self, builder
: &Builder
<'_
>) {
652 let stage
= self.stage
;
653 let host
= self.host
;
654 let compiler
= builder
.compiler(stage
, host
);
657 .ensure(tool
::Clippy { compiler, target: self.host, extra_features: Vec::new() }
)
658 .expect("in-tree tool");
659 let mut cargo
= tool
::prepare_tool_cargo(
670 // clippy tests need to know about the stage sysroot
671 cargo
.env("SYSROOT", builder
.sysroot(compiler
));
672 cargo
.env("RUSTC_TEST_SUITE", builder
.rustc(compiler
));
673 cargo
.env("RUSTC_LIB_PATH", builder
.rustc_libdir(compiler
));
674 let host_libs
= builder
.stage_out(compiler
, Mode
::ToolRustc
).join(builder
.cargo_dir());
675 cargo
.env("HOST_LIBS", host_libs
);
677 cargo
.arg("--").args(builder
.config
.cmd
.test_args());
679 cargo
.add_rustc_lib_path(builder
, compiler
);
681 if builder
.try_run(&mut cargo
.into()) {
682 // The tests succeeded; nothing to do.
686 if !builder
.config
.cmd
.bless() {
687 std
::process
::exit(1);
690 let mut cargo
= builder
.cargo(compiler
, Mode
::ToolRustc
, SourceType
::InTree
, host
, "run");
691 cargo
.arg("-p").arg("clippy_dev");
692 // clippy_dev gets confused if it can't find `clippy/Cargo.toml`
693 cargo
.current_dir(&builder
.src
.join("src").join("tools").join("clippy"));
694 if builder
.config
.rust_optimize
{
695 cargo
.env("PROFILE", "release");
697 cargo
.env("PROFILE", "debug");
701 builder
.run(&mut cargo
.into());
705 fn path_for_cargo(builder
: &Builder
<'_
>, compiler
: Compiler
) -> OsString
{
706 // Configure PATH to find the right rustc. NB. we have to use PATH
707 // and not RUSTC because the Cargo test suite has tests that will
708 // fail if rustc is not spelled `rustc`.
709 let path
= builder
.sysroot(compiler
).join("bin");
710 let old_path
= env
::var_os("PATH").unwrap_or_default();
711 env
::join_paths(iter
::once(path
).chain(env
::split_paths(&old_path
))).expect("")
714 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
715 pub struct RustdocTheme
{
716 pub compiler
: Compiler
,
719 impl Step
for RustdocTheme
{
721 const DEFAULT
: bool
= true;
722 const ONLY_HOSTS
: bool
= true;
724 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
725 run
.path("src/tools/rustdoc-themes")
728 fn make_run(run
: RunConfig
<'_
>) {
729 let compiler
= run
.builder
.compiler(run
.builder
.top_stage
, run
.target
);
731 run
.builder
.ensure(RustdocTheme { compiler }
);
734 fn run(self, builder
: &Builder
<'_
>) {
735 let rustdoc
= builder
.out
.join("bootstrap/debug/rustdoc");
736 let mut cmd
= builder
.tool_cmd(Tool
::RustdocTheme
);
737 cmd
.arg(rustdoc
.to_str().unwrap())
738 .arg(builder
.src
.join("src/librustdoc/html/static/css/themes").to_str().unwrap())
739 .env("RUSTC_STAGE", self.compiler
.stage
.to_string())
740 .env("RUSTC_SYSROOT", builder
.sysroot(self.compiler
))
741 .env("RUSTDOC_LIBDIR", builder
.sysroot_libdir(self.compiler
, self.compiler
.host
))
742 .env("CFG_RELEASE_CHANNEL", &builder
.config
.channel
)
743 .env("RUSTDOC_REAL", builder
.rustdoc(self.compiler
))
744 .env("RUSTC_BOOTSTRAP", "1");
745 if let Some(linker
) = builder
.linker(self.compiler
.host
) {
746 cmd
.env("RUSTDOC_LINKER", linker
);
748 if builder
.is_fuse_ld_lld(self.compiler
.host
) {
749 cmd
.env("RUSTDOC_FUSE_LD_LLD", "1");
751 try_run(builder
, &mut cmd
);
755 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
756 pub struct RustdocJSStd
{
757 pub target
: TargetSelection
,
760 impl Step
for RustdocJSStd
{
762 const DEFAULT
: bool
= true;
763 const ONLY_HOSTS
: bool
= true;
765 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
766 run
.suite_path("src/test/rustdoc-js-std")
769 fn make_run(run
: RunConfig
<'_
>) {
770 run
.builder
.ensure(RustdocJSStd { target: run.target }
);
773 fn run(self, builder
: &Builder
<'_
>) {
774 if let Some(ref nodejs
) = builder
.config
.nodejs
{
775 let mut command
= Command
::new(nodejs
);
777 .arg(builder
.src
.join("src/tools/rustdoc-js/tester.js"))
780 .arg("--resource-suffix")
781 .arg(&builder
.version
)
783 .arg(builder
.doc_out(self.target
))
784 .arg("--test-folder")
785 .arg(builder
.src
.join("src/test/rustdoc-js-std"));
786 for path
in &builder
.paths
{
788 util
::is_valid_test_suite_arg(path
, "src/test/rustdoc-js-std", builder
)
790 if !p
.ends_with(".js") {
791 eprintln
!("A non-js file was given: `{}`", path
.display());
792 panic
!("Cannot run rustdoc-js-std tests");
794 command
.arg("--test-file").arg(path
);
797 builder
.ensure(crate::doc
::Std { target: self.target, stage: builder.top_stage }
);
798 builder
.run(&mut command
);
800 builder
.info("No nodejs found, skipping \"src/test/rustdoc-js-std\" tests");
805 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
806 pub struct RustdocJSNotStd
{
807 pub target
: TargetSelection
,
808 pub compiler
: Compiler
,
811 impl Step
for RustdocJSNotStd
{
813 const DEFAULT
: bool
= true;
814 const ONLY_HOSTS
: bool
= true;
816 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
817 run
.suite_path("src/test/rustdoc-js")
820 fn make_run(run
: RunConfig
<'_
>) {
821 let compiler
= run
.builder
.compiler(run
.builder
.top_stage
, run
.build_triple());
822 run
.builder
.ensure(RustdocJSNotStd { target: run.target, compiler }
);
825 fn run(self, builder
: &Builder
<'_
>) {
826 if builder
.config
.nodejs
.is_some() {
827 builder
.ensure(Compiletest
{
828 compiler
: self.compiler
,
832 path
: "src/test/rustdoc-js",
836 builder
.info("No nodejs found, skipping \"src/test/rustdoc-js\" tests");
841 fn check_if_browser_ui_test_is_installed_global(npm
: &Path
, global
: bool
) -> bool
{
842 let mut command
= Command
::new(&npm
);
843 command
.arg("list").arg("--depth=0");
845 command
.arg("--global");
849 .map(|output
| String
::from_utf8_lossy(&output
.stdout
).into_owned())
850 .unwrap_or(String
::new());
851 lines
.contains(&" browser-ui-test@")
854 fn check_if_browser_ui_test_is_installed(npm
: &Path
) -> bool
{
855 check_if_browser_ui_test_is_installed_global(npm
, false)
856 || check_if_browser_ui_test_is_installed_global(npm
, true)
859 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
860 pub struct RustdocGUI
{
861 pub target
: TargetSelection
,
862 pub compiler
: Compiler
,
865 impl Step
for RustdocGUI
{
867 const DEFAULT
: bool
= true;
868 const ONLY_HOSTS
: bool
= true;
870 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
871 let builder
= run
.builder
;
872 let run
= run
.suite_path("src/test/rustdoc-gui");
873 run
.lazy_default_condition(Box
::new(move || {
874 builder
.config
.nodejs
.is_some()
879 .map(|p
| check_if_browser_ui_test_is_installed(p
))
884 fn make_run(run
: RunConfig
<'_
>) {
885 let compiler
= run
.builder
.compiler(run
.builder
.top_stage
, run
.build_triple());
886 run
.builder
.ensure(RustdocGUI { target: run.target, compiler }
);
889 fn run(self, builder
: &Builder
<'_
>) {
890 let nodejs
= builder
.config
.nodejs
.as_ref().expect("nodejs isn't available");
891 let npm
= builder
.config
.npm
.as_ref().expect("npm isn't available");
893 builder
.ensure(compile
::Std { compiler: self.compiler, target: self.target }
);
895 // The goal here is to check if the necessary packages are installed, and if not, we
897 if !check_if_browser_ui_test_is_installed(&npm
) {
899 "error: rustdoc-gui test suite cannot be run because npm `browser-ui-test` \
900 dependency is missing",
903 "If you want to install the `{0}` dependency, run `npm install {0}`",
906 panic
!("Cannot run rustdoc-gui tests");
909 let out_dir
= builder
.test_out(self.target
).join("rustdoc-gui");
911 // We remove existing folder to be sure there won't be artifacts remaining.
912 builder
.clear_if_dirty(&out_dir
, &builder
.rustdoc(self.compiler
));
914 let src_path
= builder
.build
.src
.join("src/test/rustdoc-gui/src");
915 // We generate docs for the libraries present in the rustdoc-gui's src folder.
916 for entry
in src_path
.read_dir().expect("read_dir call failed") {
917 if let Ok(entry
) = entry
{
918 let path
= entry
.path();
924 let mut cargo
= Command
::new(&builder
.initial_cargo
);
929 .env("RUSTDOC", builder
.rustdoc(self.compiler
))
930 .env("RUSTC", builder
.rustc(self.compiler
))
932 // FIXME: implement a `// compile-flags` command or similar
933 // instead of hard-coding this test
934 if entry
.file_name() == "link_to_definition" {
935 cargo
.env("RUSTDOCFLAGS", "-Zunstable-options --generate-link-to-definition");
937 builder
.run(&mut cargo
);
941 // We now run GUI tests.
942 let mut command
= Command
::new(&nodejs
);
944 .arg(builder
.build
.src
.join("src/tools/rustdoc-gui/tester.js"))
946 .arg(&builder
.jobs().to_string())
948 .arg(out_dir
.join("doc"))
949 .arg("--tests-folder")
950 .arg(builder
.build
.src
.join("src/test/rustdoc-gui"));
951 for path
in &builder
.paths
{
952 if let Some(p
) = util
::is_valid_test_suite_arg(path
, "src/test/rustdoc-gui", builder
) {
953 if !p
.ends_with(".goml") {
954 eprintln
!("A non-goml file was given: `{}`", path
.display());
955 panic
!("Cannot run rustdoc-gui tests");
957 if let Some(name
) = path
.file_name().and_then(|f
| f
.to_str()) {
958 command
.arg("--file").arg(name
);
962 for test_arg
in builder
.config
.cmd
.test_args() {
963 command
.arg(test_arg
);
965 builder
.run(&mut command
);
969 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
974 const DEFAULT
: bool
= true;
975 const ONLY_HOSTS
: bool
= true;
977 /// Runs the `tidy` tool.
979 /// This tool in `src/tools` checks up on various bits and pieces of style and
980 /// otherwise just implements a few lint-like checks that are specific to the
983 /// Once tidy passes, this step also runs `fmt --check` if tests are being run
984 /// for the `dev` or `nightly` channels.
985 fn run(self, builder
: &Builder
<'_
>) {
986 let mut cmd
= builder
.tool_cmd(Tool
::Tidy
);
987 cmd
.arg(&builder
.src
);
988 cmd
.arg(&builder
.initial_cargo
);
989 cmd
.arg(&builder
.out
);
990 cmd
.arg(builder
.jobs().to_string());
991 if builder
.is_verbose() {
992 cmd
.arg("--verbose");
995 builder
.info("tidy check");
996 try_run(builder
, &mut cmd
);
998 if builder
.config
.channel
== "dev" || builder
.config
.channel
== "nightly" {
999 builder
.info("fmt check");
1000 if builder
.config
.initial_rustfmt
.is_none() {
1001 let inferred_rustfmt_dir
= builder
.config
.initial_rustc
.parent().unwrap();
1004 error: no `rustfmt` binary found in {PATH}
1005 info: `rust.channel` is currently set to \"{CHAN}\"
1006 help: if you are testing a beta branch, set `rust.channel` to \"beta\" in the `config.toml` file
1007 help: to skip test's attempt to check tidiness, pass `--exclude src/tools/tidy` to `x.py test`",
1008 PATH
= inferred_rustfmt_dir
.display(),
1009 CHAN
= builder
.config
.channel
,
1011 std
::process
::exit(1);
1013 crate::format
::format(&builder
.build
, !builder
.config
.cmd
.bless(), &[]);
1017 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
1018 run
.path("src/tools/tidy")
1021 fn make_run(run
: RunConfig
<'_
>) {
1022 run
.builder
.ensure(Tidy
);
1026 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1027 pub struct ExpandYamlAnchors
;
1029 impl Step
for ExpandYamlAnchors
{
1031 const ONLY_HOSTS
: bool
= true;
1033 /// Ensure the `generate-ci-config` tool was run locally.
1035 /// The tool in `src/tools` reads the CI definition in `src/ci/builders.yml` and generates the
1036 /// appropriate configuration for all our CI providers. This step ensures the tool was called
1037 /// by the user before committing CI changes.
1038 fn run(self, builder
: &Builder
<'_
>) {
1039 builder
.info("Ensuring the YAML anchors in the GitHub Actions config were expanded");
1042 &mut builder
.tool_cmd(Tool
::ExpandYamlAnchors
).arg("check").arg(&builder
.src
),
1046 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
1047 run
.path("src/tools/expand-yaml-anchors")
1050 fn make_run(run
: RunConfig
<'_
>) {
1051 run
.builder
.ensure(ExpandYamlAnchors
);
1055 fn testdir(builder
: &Builder
<'_
>, host
: TargetSelection
) -> PathBuf
{
1056 builder
.out
.join(host
.triple
).join("test")
1059 macro_rules
! default_test
{
1060 ($name
:ident { path: $path:expr, mode: $mode:expr, suite: $suite:expr }
) => {
1061 test
!($name { path: $path, mode: $mode, suite: $suite, default: true, host: false }
);
1065 macro_rules
! default_test_with_compare_mode
{
1066 ($name
:ident
{ path
: $path
:expr
, mode
: $mode
:expr
, suite
: $suite
:expr
,
1067 compare_mode
: $compare_mode
:expr
}) => {
1068 test_with_compare_mode
!($name
{
1074 compare_mode
: $compare_mode
1079 macro_rules
! host_test
{
1080 ($name
:ident { path: $path:expr, mode: $mode:expr, suite: $suite:expr }
) => {
1081 test
!($name { path: $path, mode: $mode, suite: $suite, default: true, host: true }
);
1086 ($name
:ident
{ path
: $path
:expr
, mode
: $mode
:expr
, suite
: $suite
:expr
, default: $
default:expr
,
1087 host
: $host
:expr
}) => {
1088 test_definitions
!($name
{
1099 macro_rules
! test_with_compare_mode
{
1100 ($name
:ident
{ path
: $path
:expr
, mode
: $mode
:expr
, suite
: $suite
:expr
, default: $
default:expr
,
1101 host
: $host
:expr
, compare_mode
: $compare_mode
:expr
}) => {
1102 test_definitions
!($name
{
1108 compare_mode
: Some($compare_mode
)
1113 macro_rules
! test_definitions
{
1118 default: $
default:expr
,
1120 compare_mode
: $compare_mode
:expr
1122 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1124 pub compiler
: Compiler
,
1125 pub target
: TargetSelection
,
1128 impl Step
for $name
{
1130 const DEFAULT
: bool
= $
default;
1131 const ONLY_HOSTS
: bool
= $host
;
1133 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
1134 run
.suite_path($path
)
1137 fn make_run(run
: RunConfig
<'_
>) {
1138 let compiler
= run
.builder
.compiler(run
.builder
.top_stage
, run
.build_triple());
1140 run
.builder
.ensure($name { compiler, target: run.target }
);
1143 fn run(self, builder
: &Builder
<'_
>) {
1144 builder
.ensure(Compiletest
{
1145 compiler
: self.compiler
,
1146 target
: self.target
,
1150 compare_mode
: $compare_mode
,
1157 default_test_with_compare_mode
!(Ui
{
1158 path
: "src/test/ui",
1164 default_test
!(RunPassValgrind
{
1165 path
: "src/test/run-pass-valgrind",
1166 mode
: "run-pass-valgrind",
1167 suite
: "run-pass-valgrind"
1170 default_test
!(MirOpt { path: "src/test/mir-opt", mode: "mir-opt", suite: "mir-opt" }
);
1172 default_test
!(Codegen { path: "src/test/codegen", mode: "codegen", suite: "codegen" }
);
1174 default_test
!(CodegenUnits
{
1175 path
: "src/test/codegen-units",
1176 mode
: "codegen-units",
1177 suite
: "codegen-units"
1180 default_test
!(Incremental
{
1181 path
: "src/test/incremental",
1182 mode
: "incremental",
1183 suite
: "incremental"
1186 default_test_with_compare_mode
!(Debuginfo
{
1187 path
: "src/test/debuginfo",
1190 compare_mode
: "split-dwarf"
1193 host_test
!(UiFullDeps { path: "src/test/ui-fulldeps", mode: "ui", suite: "ui-fulldeps" }
);
1195 host_test
!(Rustdoc { path: "src/test/rustdoc", mode: "rustdoc", suite: "rustdoc" }
);
1196 host_test
!(RustdocUi { path: "src/test/rustdoc-ui", mode: "ui", suite: "rustdoc-ui" }
);
1198 host_test
!(RustdocJson
{
1199 path
: "src/test/rustdoc-json",
1200 mode
: "rustdoc-json",
1201 suite
: "rustdoc-json"
1204 host_test
!(Pretty { path: "src/test/pretty", mode: "pretty", suite: "pretty" }
);
1206 default_test
!(RunMake { path: "src/test/run-make", mode: "run-make", suite: "run-make" }
);
1208 host_test
!(RunMakeFullDeps
{
1209 path
: "src/test/run-make-fulldeps",
1211 suite
: "run-make-fulldeps"
1214 default_test
!(Assembly { path: "src/test/assembly", mode: "assembly", suite: "assembly" }
);
1216 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1217 struct Compiletest
{
1219 target
: TargetSelection
,
1221 suite
: &'
static str,
1223 compare_mode
: Option
<&'
static str>,
1226 impl Step
for Compiletest
{
1229 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
1233 /// Executes the `compiletest` tool to run a suite of tests.
1235 /// Compiles all tests with `compiler` for `target` with the specified
1236 /// compiletest `mode` and `suite` arguments. For example `mode` can be
1237 /// "run-pass" or `suite` can be something like `debuginfo`.
1238 fn run(self, builder
: &Builder
<'_
>) {
1239 if builder
.top_stage
== 0 && env
::var("COMPILETEST_FORCE_STAGE0").is_err() {
1241 error: `--stage 0` runs compiletest on the beta compiler, not your local changes, and will almost always cause tests to fail
1242 help: to test the compiler, use `--stage 1` instead
1243 help: to test the standard library, use `--stage 0 library/std` instead
1244 note: if you're sure you want to do this, please open an issue as to why. In the meantime, you can override this with `COMPILETEST_FORCE_STAGE0=1`."
1246 std
::process
::exit(1);
1249 let compiler
= self.compiler
;
1250 let target
= self.target
;
1251 let mode
= self.mode
;
1252 let suite
= self.suite
;
1254 // Path for test suite
1255 let suite_path
= self.path
;
1257 // Skip codegen tests if they aren't enabled in configuration.
1258 if !builder
.config
.codegen_tests
&& suite
== "codegen" {
1262 if suite
== "debuginfo" {
1264 .ensure(dist
::DebuggerScripts { sysroot: builder.sysroot(compiler), host: target }
);
1267 if suite
.ends_with("fulldeps") {
1268 builder
.ensure(compile
::Rustc { compiler, target }
);
1271 builder
.ensure(compile
::Std { compiler, target }
);
1272 // ensure that `libproc_macro` is available on the host.
1273 builder
.ensure(compile
::Std { compiler, target: compiler.host }
);
1275 // Also provide `rust_test_helpers` for the host.
1276 builder
.ensure(native
::TestHelpers { target: compiler.host }
);
1278 // As well as the target, except for plain wasm32, which can't build it
1279 if !target
.contains("wasm") || target
.contains("emscripten") {
1280 builder
.ensure(native
::TestHelpers { target }
);
1283 builder
.ensure(RemoteCopyLibs { compiler, target }
);
1285 let mut cmd
= builder
.tool_cmd(Tool
::Compiletest
);
1287 // compiletest currently has... a lot of arguments, so let's just pass all
1290 cmd
.arg("--compile-lib-path").arg(builder
.rustc_libdir(compiler
));
1291 cmd
.arg("--run-lib-path").arg(builder
.sysroot_libdir(compiler
, target
));
1292 cmd
.arg("--rustc-path").arg(builder
.rustc(compiler
));
1294 let is_rustdoc
= suite
.ends_with("rustdoc-ui") || suite
.ends_with("rustdoc-js");
1296 // Avoid depending on rustdoc when we don't need it.
1297 if mode
== "rustdoc"
1298 || mode
== "run-make"
1299 || (mode
== "ui" && is_rustdoc
)
1300 || mode
== "js-doc-test"
1301 || mode
== "rustdoc-json"
1303 cmd
.arg("--rustdoc-path").arg(builder
.rustdoc(compiler
));
1306 if mode
== "rustdoc-json" {
1307 // Use the beta compiler for jsondocck
1308 let json_compiler
= compiler
.with_stage(0);
1309 cmd
.arg("--jsondocck-path")
1310 .arg(builder
.ensure(tool
::JsonDocCk { compiler: json_compiler, target }
));
1313 if mode
== "run-make" && suite
.ends_with("fulldeps") {
1314 let rust_demangler
= builder
1315 .ensure(tool
::RustDemangler { compiler, target, extra_features: Vec::new() }
)
1316 .expect("in-tree tool");
1317 cmd
.arg("--rust-demangler-path").arg(rust_demangler
);
1320 cmd
.arg("--src-base").arg(builder
.src
.join("src/test").join(suite
));
1321 cmd
.arg("--build-base").arg(testdir(builder
, compiler
.host
).join(suite
));
1322 cmd
.arg("--stage-id").arg(format
!("stage{}-{}", compiler
.stage
, target
));
1323 cmd
.arg("--suite").arg(suite
);
1324 cmd
.arg("--mode").arg(mode
);
1325 cmd
.arg("--target").arg(target
.rustc_target_arg());
1326 cmd
.arg("--host").arg(&*compiler
.host
.triple
);
1327 cmd
.arg("--llvm-filecheck").arg(builder
.llvm_filecheck(builder
.config
.build
));
1329 if builder
.config
.cmd
.bless() {
1333 if builder
.config
.cmd
.force_rerun() {
1334 cmd
.arg("--force-rerun");
1338 builder
.config
.cmd
.compare_mode().or_else(|| {
1339 if builder
.config
.test_compare_mode { self.compare_mode }
else { None }
1342 if let Some(ref pass
) = builder
.config
.cmd
.pass() {
1347 if let Some(ref run
) = builder
.config
.cmd
.run() {
1352 if let Some(ref nodejs
) = builder
.config
.nodejs
{
1353 cmd
.arg("--nodejs").arg(nodejs
);
1355 if let Some(ref npm
) = builder
.config
.npm
{
1356 cmd
.arg("--npm").arg(npm
);
1359 let mut flags
= if is_rustdoc { Vec::new() }
else { vec!["-Crpath".to_string()] }
;
1361 if builder
.config
.rust_optimize_tests
{
1362 flags
.push("-O".to_string());
1365 flags
.push(format
!("-Cdebuginfo={}", builder
.config
.rust_debuginfo_level_tests
));
1366 flags
.push(builder
.config
.cmd
.rustc_args().join(" "));
1368 if let Some(linker
) = builder
.linker(target
) {
1369 cmd
.arg("--linker").arg(linker
);
1372 let mut hostflags
= flags
.clone();
1373 hostflags
.push(format
!("-Lnative={}", builder
.test_helpers_out(compiler
.host
).display()));
1374 hostflags
.extend(builder
.lld_flags(compiler
.host
));
1375 cmd
.arg("--host-rustcflags").arg(hostflags
.join(" "));
1377 let mut targetflags
= flags
;
1378 targetflags
.push(format
!("-Lnative={}", builder
.test_helpers_out(target
).display()));
1379 targetflags
.extend(builder
.lld_flags(target
));
1380 cmd
.arg("--target-rustcflags").arg(targetflags
.join(" "));
1382 cmd
.arg("--docck-python").arg(builder
.python());
1384 if builder
.config
.build
.ends_with("apple-darwin") {
1385 // Force /usr/bin/python3 on macOS for LLDB tests because we're loading the
1386 // LLDB plugin's compiled module which only works with the system python
1387 // (namely not Homebrew-installed python)
1388 cmd
.arg("--lldb-python").arg("/usr/bin/python3");
1390 cmd
.arg("--lldb-python").arg(builder
.python());
1393 if let Some(ref gdb
) = builder
.config
.gdb
{
1394 cmd
.arg("--gdb").arg(gdb
);
1397 let run
= |cmd
: &mut Command
| {
1398 cmd
.output().map(|output
| {
1399 String
::from_utf8_lossy(&output
.stdout
)
1402 .unwrap_or_else(|| panic
!("{:?} failed {:?}", cmd
, output
))
1406 let lldb_exe
= "lldb";
1407 let lldb_version
= Command
::new(lldb_exe
)
1410 .map(|output
| String
::from_utf8_lossy(&output
.stdout
).to_string())
1412 if let Some(ref vers
) = lldb_version
{
1413 cmd
.arg("--lldb-version").arg(vers
);
1414 let lldb_python_dir
= run(Command
::new(lldb_exe
).arg("-P")).ok();
1415 if let Some(ref dir
) = lldb_python_dir
{
1416 cmd
.arg("--lldb-python-dir").arg(dir
);
1420 if util
::forcing_clang_based_tests() {
1421 let clang_exe
= builder
.llvm_out(target
).join("bin").join("clang");
1422 cmd
.arg("--run-clang-based-tests-with").arg(clang_exe
);
1425 // Get paths from cmd args
1426 let paths
= match &builder
.config
.cmd
{
1427 Subcommand
::Test { ref paths, .. }
=> &paths
[..],
1431 // Get test-args by striping suite path
1432 let mut test_args
: Vec
<&str> = paths
1434 .filter_map(|p
| util
::is_valid_test_suite_arg(p
, suite_path
, builder
))
1437 test_args
.append(&mut builder
.config
.cmd
.test_args());
1439 cmd
.args(&test_args
);
1441 if builder
.is_verbose() {
1442 cmd
.arg("--verbose");
1445 if !builder
.config
.verbose_tests
{
1449 let mut llvm_components_passed
= false;
1450 let mut copts_passed
= false;
1451 if builder
.config
.llvm_enabled() {
1452 let llvm_config
= builder
.ensure(native
::Llvm { target: builder.config.build }
);
1453 if !builder
.config
.dry_run
{
1454 let llvm_version
= output(Command
::new(&llvm_config
).arg("--version"));
1455 let llvm_components
= output(Command
::new(&llvm_config
).arg("--components"));
1456 // Remove trailing newline from llvm-config output.
1457 cmd
.arg("--llvm-version")
1458 .arg(llvm_version
.trim())
1459 .arg("--llvm-components")
1460 .arg(llvm_components
.trim());
1461 llvm_components_passed
= true;
1463 if !builder
.is_rust_llvm(target
) {
1464 cmd
.arg("--system-llvm");
1467 // Tests that use compiler libraries may inherit the `-lLLVM` link
1468 // requirement, but the `-L` library path is not propagated across
1469 // separate compilations. We can add LLVM's library path to the
1470 // platform-specific environment variable as a workaround.
1471 if !builder
.config
.dry_run
&& suite
.ends_with("fulldeps") {
1472 let llvm_libdir
= output(Command
::new(&llvm_config
).arg("--libdir"));
1473 add_link_lib_path(vec
![llvm_libdir
.trim().into()], &mut cmd
);
1476 // Only pass correct values for these flags for the `run-make` suite as it
1477 // requires that a C++ compiler was configured which isn't always the case.
1478 if !builder
.config
.dry_run
&& matches
!(suite
, "run-make" | "run-make-fulldeps") {
1479 // The llvm/bin directory contains many useful cross-platform
1480 // tools. Pass the path to run-make tests so they can use them.
1481 let llvm_bin_path
= llvm_config
1483 .expect("Expected llvm-config to be contained in directory");
1484 assert
!(llvm_bin_path
.is_dir());
1485 cmd
.arg("--llvm-bin-dir").arg(llvm_bin_path
);
1487 // If LLD is available, add it to the PATH
1488 if builder
.config
.lld_enabled
{
1489 let lld_install_root
=
1490 builder
.ensure(native
::Lld { target: builder.config.build }
);
1492 let lld_bin_path
= lld_install_root
.join("bin");
1494 let old_path
= env
::var_os("PATH").unwrap_or_default();
1495 let new_path
= env
::join_paths(
1496 std
::iter
::once(lld_bin_path
).chain(env
::split_paths(&old_path
)),
1498 .expect("Could not add LLD bin path to PATH");
1499 cmd
.env("PATH", new_path
);
1504 // Only pass correct values for these flags for the `run-make` suite as it
1505 // requires that a C++ compiler was configured which isn't always the case.
1506 if !builder
.config
.dry_run
&& matches
!(suite
, "run-make" | "run-make-fulldeps") {
1508 .arg(builder
.cc(target
))
1510 .arg(builder
.cxx(target
).unwrap())
1512 .arg(builder
.cflags(target
, GitRepo
::Rustc
, CLang
::C
).join(" "))
1514 .arg(builder
.cflags(target
, GitRepo
::Rustc
, CLang
::Cxx
).join(" "));
1515 copts_passed
= true;
1516 if let Some(ar
) = builder
.ar(target
) {
1517 cmd
.arg("--ar").arg(ar
);
1521 if !llvm_components_passed
{
1522 cmd
.arg("--llvm-components").arg("");
1535 if builder
.remote_tested(target
) {
1536 cmd
.arg("--remote-test-client").arg(builder
.tool_exe(Tool
::RemoteTestClient
));
1539 // Running a C compiler on MSVC requires a few env vars to be set, to be
1540 // sure to set them here.
1542 // Note that if we encounter `PATH` we make sure to append to our own `PATH`
1543 // rather than stomp over it.
1544 if target
.contains("msvc") {
1545 for &(ref k
, ref v
) in builder
.cc
[&target
].env() {
1551 cmd
.env("RUSTC_BOOTSTRAP", "1");
1552 // Override the rustc version used in symbol hashes to reduce the amount of normalization
1553 // needed when diffing test output.
1554 cmd
.env("RUSTC_FORCE_RUSTC_VERSION", "compiletest");
1555 cmd
.env("DOC_RUST_LANG_ORG_CHANNEL", builder
.doc_rust_lang_org_channel());
1556 builder
.add_rust_test_threads(&mut cmd
);
1558 if builder
.config
.sanitizers_enabled(target
) {
1559 cmd
.env("RUSTC_SANITIZER_SUPPORT", "1");
1562 if builder
.config
.profiler_enabled(target
) {
1563 cmd
.env("RUSTC_PROFILER_SUPPORT", "1");
1566 let tmp
= builder
.out
.join("tmp");
1567 std
::fs
::create_dir_all(&tmp
).unwrap();
1568 cmd
.env("RUST_TEST_TMPDIR", tmp
);
1570 cmd
.arg("--adb-path").arg("adb");
1571 cmd
.arg("--adb-test-dir").arg(ADB_TEST_DIR
);
1572 if target
.contains("android") {
1573 // Assume that cc for this target comes from the android sysroot
1574 cmd
.arg("--android-cross-path")
1575 .arg(builder
.cc(target
).parent().unwrap().parent().unwrap());
1577 cmd
.arg("--android-cross-path").arg("");
1580 if builder
.config
.cmd
.rustfix_coverage() {
1581 cmd
.arg("--rustfix-coverage");
1584 cmd
.env("BOOTSTRAP_CARGO", &builder
.initial_cargo
);
1586 cmd
.arg("--channel").arg(&builder
.config
.channel
);
1588 builder
.ci_env
.force_coloring_in_ci(&mut cmd
);
1590 builder
.info(&format
!(
1591 "Check compiletest suite={} mode={} ({} -> {})",
1592 suite
, mode
, &compiler
.host
, target
1594 let _time
= util
::timeit(&builder
);
1595 try_run(builder
, &mut cmd
);
1597 if let Some(compare_mode
) = compare_mode
{
1598 cmd
.arg("--compare-mode").arg(compare_mode
);
1599 builder
.info(&format
!(
1600 "Check compiletest suite={} mode={} compare_mode={} ({} -> {})",
1601 suite
, mode
, compare_mode
, &compiler
.host
, target
1603 let _time
= util
::timeit(&builder
);
1604 try_run(builder
, &mut cmd
);
1609 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
1617 impl Step
for BookTest
{
1619 const ONLY_HOSTS
: bool
= true;
1621 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
1625 /// Runs the documentation tests for a book in `src/doc`.
1627 /// This uses the `rustdoc` that sits next to `compiler`.
1628 fn run(self, builder
: &Builder
<'_
>) {
1629 // External docs are different from local because:
1630 // - Some books need pre-processing by mdbook before being tested.
1631 // - They need to save their state to toolstate.
1632 // - They are only tested on the "checktools" builders.
1634 // The local docs are tested by default, and we don't want to pay the
1635 // cost of building mdbook, so they use `rustdoc --test` directly.
1636 // Also, the unstable book is special because SUMMARY.md is generated,
1637 // so it is easier to just run `rustdoc` on its files.
1638 if self.is_ext_doc
{
1639 self.run_ext_doc(builder
);
1641 self.run_local_doc(builder
);
1647 /// This runs the equivalent of `mdbook test` (via the rustbook wrapper)
1648 /// which in turn runs `rustdoc --test` on each file in the book.
1649 fn run_ext_doc(self, builder
: &Builder
<'_
>) {
1650 let compiler
= self.compiler
;
1652 builder
.ensure(compile
::Std { compiler, target: compiler.host }
);
1654 // mdbook just executes a binary named "rustdoc", so we need to update
1655 // PATH so that it points to our rustdoc.
1656 let mut rustdoc_path
= builder
.rustdoc(compiler
);
1658 let old_path
= env
::var_os("PATH").unwrap_or_default();
1659 let new_path
= env
::join_paths(iter
::once(rustdoc_path
).chain(env
::split_paths(&old_path
)))
1660 .expect("could not add rustdoc to PATH");
1662 let mut rustbook_cmd
= builder
.tool_cmd(Tool
::Rustbook
);
1663 let path
= builder
.src
.join(&self.path
);
1664 rustbook_cmd
.env("PATH", new_path
).arg("test").arg(path
);
1665 builder
.add_rust_test_threads(&mut rustbook_cmd
);
1666 builder
.info(&format
!("Testing rustbook {}", self.path
.display()));
1667 let _time
= util
::timeit(&builder
);
1668 let toolstate
= if try_run(builder
, &mut rustbook_cmd
) {
1673 builder
.save_toolstate(self.name
, toolstate
);
1676 /// This runs `rustdoc --test` on all `.md` files in the path.
1677 fn run_local_doc(self, builder
: &Builder
<'_
>) {
1678 let compiler
= self.compiler
;
1680 builder
.ensure(compile
::Std { compiler, target: compiler.host }
);
1682 // Do a breadth-first traversal of the `src/doc` directory and just run
1683 // tests for all files that end in `*.md`
1684 let mut stack
= vec
![builder
.src
.join(self.path
)];
1685 let _time
= util
::timeit(&builder
);
1686 let mut files
= Vec
::new();
1687 while let Some(p
) = stack
.pop() {
1689 stack
.extend(t
!(p
.read_dir()).map(|p
| t
!(p
).path()));
1693 if p
.extension().and_then(|s
| s
.to_str()) != Some("md") {
1703 markdown_test(builder
, compiler
, &file
);
1708 macro_rules
! test_book
{
1709 ($
($name
:ident
, $path
:expr
, $book_name
:expr
, default=$
default:expr
;)+) => {
1711 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1716 impl Step
for $name
{
1718 const DEFAULT
: bool
= $
default;
1719 const ONLY_HOSTS
: bool
= true;
1721 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
1725 fn make_run(run
: RunConfig
<'_
>) {
1726 run
.builder
.ensure($name
{
1727 compiler
: run
.builder
.compiler(run
.builder
.top_stage
, run
.target
),
1731 fn run(self, builder
: &Builder
<'_
>) {
1732 builder
.ensure(BookTest
{
1733 compiler
: self.compiler
,
1734 path
: PathBuf
::from($path
),
1736 is_ext_doc
: !$
default,
1745 Nomicon
, "src/doc/nomicon", "nomicon", default=false;
1746 Reference
, "src/doc/reference", "reference", default=false;
1747 RustdocBook
, "src/doc/rustdoc", "rustdoc", default=true;
1748 RustcBook
, "src/doc/rustc", "rustc", default=true;
1749 RustByExample
, "src/doc/rust-by-example", "rust-by-example", default=false;
1750 EmbeddedBook
, "src/doc/embedded-book", "embedded-book", default=false;
1751 TheBook
, "src/doc/book", "book", default=false;
1752 UnstableBook
, "src/doc/unstable-book", "unstable-book", default=true;
1753 EditionGuide
, "src/doc/edition-guide", "edition-guide", default=false;
1756 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1757 pub struct ErrorIndex
{
1761 impl Step
for ErrorIndex
{
1763 const DEFAULT
: bool
= true;
1764 const ONLY_HOSTS
: bool
= true;
1766 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
1767 run
.path("src/tools/error_index_generator")
1770 fn make_run(run
: RunConfig
<'_
>) {
1771 // error_index_generator depends on librustdoc. Use the compiler that
1772 // is normally used to build rustdoc for other tests (like compiletest
1773 // tests in src/test/rustdoc) so that it shares the same artifacts.
1774 let compiler
= run
.builder
.compiler(run
.builder
.top_stage
, run
.builder
.config
.build
);
1775 run
.builder
.ensure(ErrorIndex { compiler }
);
1778 /// Runs the error index generator tool to execute the tests located in the error
1781 /// The `error_index_generator` tool lives in `src/tools` and is used to
1782 /// generate a markdown file from the error indexes of the code base which is
1783 /// then passed to `rustdoc --test`.
1784 fn run(self, builder
: &Builder
<'_
>) {
1785 let compiler
= self.compiler
;
1787 let dir
= testdir(builder
, compiler
.host
);
1788 t
!(fs
::create_dir_all(&dir
));
1789 let output
= dir
.join("error-index.md");
1791 let mut tool
= tool
::ErrorIndex
::command(builder
);
1792 tool
.arg("markdown").arg(&output
);
1794 builder
.info(&format
!("Testing error-index stage{}", compiler
.stage
));
1795 let _time
= util
::timeit(&builder
);
1796 builder
.run_quiet(&mut tool
);
1797 // The tests themselves need to link to std, so make sure it is
1799 builder
.ensure(compile
::Std { compiler, target: compiler.host }
);
1800 markdown_test(builder
, compiler
, &output
);
1804 fn markdown_test(builder
: &Builder
<'_
>, compiler
: Compiler
, markdown
: &Path
) -> bool
{
1805 if let Ok(contents
) = fs
::read_to_string(markdown
) {
1806 if !contents
.contains("```") {
1811 builder
.info(&format
!("doc tests for: {}", markdown
.display()));
1812 let mut cmd
= builder
.rustdoc_cmd(compiler
);
1813 builder
.add_rust_test_threads(&mut cmd
);
1814 // allow for unstable options such as new editions
1816 cmd
.arg("unstable-options");
1819 cmd
.env("RUSTC_BOOTSTRAP", "1");
1821 let test_args
= builder
.config
.cmd
.test_args().join(" ");
1822 cmd
.arg("--test-args").arg(test_args
);
1824 if builder
.config
.verbose_tests
{
1825 try_run(builder
, &mut cmd
)
1827 try_run_quiet(builder
, &mut cmd
)
1831 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1832 pub struct RustcGuide
;
1834 impl Step
for RustcGuide
{
1836 const DEFAULT
: bool
= false;
1837 const ONLY_HOSTS
: bool
= true;
1839 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
1840 run
.path("src/doc/rustc-dev-guide")
1843 fn make_run(run
: RunConfig
<'_
>) {
1844 run
.builder
.ensure(RustcGuide
);
1847 fn run(self, builder
: &Builder
<'_
>) {
1848 let relative_path
= Path
::new("src").join("doc").join("rustc-dev-guide");
1849 builder
.update_submodule(&relative_path
);
1851 let src
= builder
.src
.join(relative_path
);
1852 let mut rustbook_cmd
= builder
.tool_cmd(Tool
::Rustbook
);
1853 let toolstate
= if try_run(builder
, rustbook_cmd
.arg("linkcheck").arg(&src
)) {
1858 builder
.save_toolstate("rustc-dev-guide", toolstate
);
1862 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1863 pub struct CrateLibrustc
{
1865 target
: TargetSelection
,
1866 test_kind
: TestKind
,
1867 krate
: Interned
<String
>,
1870 impl Step
for CrateLibrustc
{
1872 const DEFAULT
: bool
= true;
1873 const ONLY_HOSTS
: bool
= true;
1875 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
1876 run
.krate("rustc-main")
1879 fn make_run(run
: RunConfig
<'_
>) {
1880 let builder
= run
.builder
;
1881 let compiler
= builder
.compiler(builder
.top_stage
, run
.build_triple());
1883 for krate
in builder
.in_tree_crates("rustc-main", Some(run
.target
)) {
1884 if krate
.path
.ends_with(&run
.path
) {
1885 let test_kind
= builder
.kind
.into();
1887 builder
.ensure(CrateLibrustc
{
1897 fn run(self, builder
: &Builder
<'_
>) {
1898 builder
.ensure(Crate
{
1899 compiler
: self.compiler
,
1900 target
: self.target
,
1902 test_kind
: self.test_kind
,
1908 #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
1910 pub compiler
: Compiler
,
1911 pub target
: TargetSelection
,
1913 pub test_kind
: TestKind
,
1914 pub krate
: Interned
<String
>,
1917 impl Step
for Crate
{
1919 const DEFAULT
: bool
= true;
1921 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
1925 fn make_run(run
: RunConfig
<'_
>) {
1926 let builder
= run
.builder
;
1927 let compiler
= builder
.compiler(builder
.top_stage
, run
.build_triple());
1929 let make
= |mode
: Mode
, krate
: &CargoCrate
| {
1930 let test_kind
= builder
.kind
.into();
1932 builder
.ensure(Crate
{
1941 for krate
in builder
.in_tree_crates("test", Some(run
.target
)) {
1942 if krate
.path
.ends_with(&run
.path
) {
1943 make(Mode
::Std
, krate
);
1948 /// Runs all unit tests plus documentation tests for a given crate defined
1949 /// by a `Cargo.toml` (single manifest)
1951 /// This is what runs tests for crates like the standard library, compiler, etc.
1952 /// It essentially is the driver for running `cargo test`.
1954 /// Currently this runs all tests for a DAG by passing a bunch of `-p foo`
1955 /// arguments, and those arguments are discovered from `cargo metadata`.
1956 fn run(self, builder
: &Builder
<'_
>) {
1957 let compiler
= self.compiler
;
1958 let target
= self.target
;
1959 let mode
= self.mode
;
1960 let test_kind
= self.test_kind
;
1961 let krate
= self.krate
;
1963 builder
.ensure(compile
::Std { compiler, target }
);
1964 builder
.ensure(RemoteCopyLibs { compiler, target }
);
1966 // If we're not doing a full bootstrap but we're testing a stage2
1967 // version of libstd, then what we're actually testing is the libstd
1968 // produced in stage1. Reflect that here by updating the compiler that
1969 // we're working with automatically.
1970 let compiler
= builder
.compiler_for(compiler
.stage
, compiler
.host
, target
);
1973 builder
.cargo(compiler
, mode
, SourceType
::InTree
, target
, test_kind
.subcommand());
1976 compile
::std_cargo(builder
, target
, compiler
.stage
, &mut cargo
);
1979 builder
.ensure(compile
::Rustc { compiler, target }
);
1980 compile
::rustc_cargo(builder
, &mut cargo
, target
);
1982 _
=> panic
!("can only test libraries"),
1985 // Build up the base `cargo test` command.
1987 // Pass in some standard flags then iterate over the graph we've discovered
1988 // in `cargo metadata` with the maps above and figure out what `-p`
1989 // arguments need to get passed.
1990 if test_kind
.subcommand() == "test" && !builder
.fail_fast
{
1991 cargo
.arg("--no-fail-fast");
1993 match builder
.doc_tests
{
1998 cargo
.args(&["--lib", "--bins", "--examples", "--tests", "--benches"]);
2003 cargo
.arg("-p").arg(krate
);
2005 // The tests are going to run with the *target* libraries, so we need to
2006 // ensure that those libraries show up in the LD_LIBRARY_PATH equivalent.
2008 // Note that to run the compiler we need to run with the *host* libraries,
2009 // but our wrapper scripts arrange for that to be the case anyway.
2010 let mut dylib_path
= dylib_path();
2011 dylib_path
.insert(0, PathBuf
::from(&*builder
.sysroot_libdir(compiler
, target
)));
2012 cargo
.env(dylib_path_var(), env
::join_paths(&dylib_path
).unwrap());
2015 cargo
.args(&builder
.config
.cmd
.test_args());
2017 if !builder
.config
.verbose_tests
{
2018 cargo
.arg("--quiet");
2021 if target
.contains("emscripten") {
2023 format
!("CARGO_TARGET_{}_RUNNER", envify(&target
.triple
)),
2024 builder
.config
.nodejs
.as_ref().expect("nodejs not configured"),
2026 } else if target
.starts_with("wasm32") {
2027 let node
= builder
.config
.nodejs
.as_ref().expect("nodejs not configured");
2029 format
!("{} {}/src/etc/wasm32-shim.js", node
.display(), builder
.src
.display());
2030 cargo
.env(format
!("CARGO_TARGET_{}_RUNNER", envify(&target
.triple
)), &runner
);
2031 } else if builder
.remote_tested(target
) {
2033 format
!("CARGO_TARGET_{}_RUNNER", envify(&target
.triple
)),
2034 format
!("{} run 0", builder
.tool_exe(Tool
::RemoteTestClient
).display()),
2038 builder
.info(&format
!(
2039 "{} {} stage{} ({} -> {})",
2040 test_kind
, krate
, compiler
.stage
, &compiler
.host
, target
2042 let _time
= util
::timeit(&builder
);
2043 try_run(builder
, &mut cargo
.into());
2047 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
2048 pub struct CrateRustdoc
{
2049 host
: TargetSelection
,
2050 test_kind
: TestKind
,
2053 impl Step
for CrateRustdoc
{
2055 const DEFAULT
: bool
= true;
2056 const ONLY_HOSTS
: bool
= true;
2058 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
2059 run
.paths(&["src/librustdoc", "src/tools/rustdoc"])
2062 fn make_run(run
: RunConfig
<'_
>) {
2063 let builder
= run
.builder
;
2065 let test_kind
= builder
.kind
.into();
2067 builder
.ensure(CrateRustdoc { host: run.target, test_kind }
);
2070 fn run(self, builder
: &Builder
<'_
>) {
2071 let test_kind
= self.test_kind
;
2072 let target
= self.host
;
2074 // Use the previous stage compiler to reuse the artifacts that are
2075 // created when running compiletest for src/test/rustdoc. If this used
2076 // `compiler`, then it would cause rustdoc to be built *again*, which
2077 // isn't really necessary.
2078 let compiler
= builder
.compiler_for(builder
.top_stage
, target
, target
);
2079 builder
.ensure(compile
::Rustc { compiler, target }
);
2081 let mut cargo
= tool
::prepare_tool_cargo(
2086 test_kind
.subcommand(),
2087 "src/tools/rustdoc",
2091 if test_kind
.subcommand() == "test" && !builder
.fail_fast
{
2092 cargo
.arg("--no-fail-fast");
2095 cargo
.arg("-p").arg("rustdoc:0.0.0");
2098 cargo
.args(&builder
.config
.cmd
.test_args());
2100 if self.host
.contains("musl") {
2101 cargo
.arg("'-Ctarget-feature=-crt-static'");
2104 // This is needed for running doctests on librustdoc. This is a bit of
2105 // an unfortunate interaction with how bootstrap works and how cargo
2106 // sets up the dylib path, and the fact that the doctest (in
2107 // html/markdown.rs) links to rustc-private libs. For stage1, the
2108 // compiler host dylibs (in stage1/lib) are not the same as the target
2109 // dylibs (in stage1/lib/rustlib/...). This is different from a normal
2110 // rust distribution where they are the same.
2112 // On the cargo side, normal tests use `target_process` which handles
2113 // setting up the dylib for a *target* (stage1/lib/rustlib/... in this
2114 // case). However, for doctests it uses `rustdoc_process` which only
2115 // sets up the dylib path for the *host* (stage1/lib), which is the
2118 // It should be considered to just stop running doctests on
2119 // librustdoc. There is only one test, and it doesn't look too
2120 // important. There might be other ways to avoid this, but it seems
2121 // pretty convoluted.
2123 // See also https://github.com/rust-lang/rust/issues/13983 where the
2124 // host vs target dylibs for rustdoc are consistently tricky to deal
2126 let mut dylib_path
= dylib_path();
2127 dylib_path
.insert(0, PathBuf
::from(&*builder
.sysroot_libdir(compiler
, target
)));
2128 cargo
.env(dylib_path_var(), env
::join_paths(&dylib_path
).unwrap());
2130 if !builder
.config
.verbose_tests
{
2131 cargo
.arg("--quiet");
2134 builder
.info(&format
!(
2135 "{} rustdoc stage{} ({} -> {})",
2136 test_kind
, compiler
.stage
, &compiler
.host
, target
2138 let _time
= util
::timeit(&builder
);
2140 try_run(builder
, &mut cargo
.into());
2144 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
2145 pub struct CrateRustdocJsonTypes
{
2146 host
: TargetSelection
,
2147 test_kind
: TestKind
,
2150 impl Step
for CrateRustdocJsonTypes
{
2152 const DEFAULT
: bool
= true;
2153 const ONLY_HOSTS
: bool
= true;
2155 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
2156 run
.path("src/rustdoc-json-types")
2159 fn make_run(run
: RunConfig
<'_
>) {
2160 let builder
= run
.builder
;
2162 let test_kind
= builder
.kind
.into();
2164 builder
.ensure(CrateRustdocJsonTypes { host: run.target, test_kind }
);
2167 fn run(self, builder
: &Builder
<'_
>) {
2168 let test_kind
= self.test_kind
;
2169 let target
= self.host
;
2171 // Use the previous stage compiler to reuse the artifacts that are
2172 // created when running compiletest for src/test/rustdoc. If this used
2173 // `compiler`, then it would cause rustdoc to be built *again*, which
2174 // isn't really necessary.
2175 let compiler
= builder
.compiler_for(builder
.top_stage
, target
, target
);
2176 builder
.ensure(compile
::Rustc { compiler, target }
);
2178 let mut cargo
= tool
::prepare_tool_cargo(
2183 test_kind
.subcommand(),
2184 "src/rustdoc-json-types",
2188 if test_kind
.subcommand() == "test" && !builder
.fail_fast
{
2189 cargo
.arg("--no-fail-fast");
2192 cargo
.arg("-p").arg("rustdoc-json-types");
2195 cargo
.args(&builder
.config
.cmd
.test_args());
2197 if self.host
.contains("musl") {
2198 cargo
.arg("'-Ctarget-feature=-crt-static'");
2201 if !builder
.config
.verbose_tests
{
2202 cargo
.arg("--quiet");
2205 builder
.info(&format
!(
2206 "{} rustdoc-json-types stage{} ({} -> {})",
2207 test_kind
, compiler
.stage
, &compiler
.host
, target
2209 let _time
= util
::timeit(&builder
);
2211 try_run(builder
, &mut cargo
.into());
2215 /// Some test suites are run inside emulators or on remote devices, and most
2216 /// of our test binaries are linked dynamically which means we need to ship
2217 /// the standard library and such to the emulator ahead of time. This step
2218 /// represents this and is a dependency of all test suites.
2220 /// Most of the time this is a no-op. For some steps such as shipping data to
2221 /// QEMU we have to build our own tools so we've got conditional dependencies
2222 /// on those programs as well. Note that the remote test client is built for
2223 /// the build target (us) and the server is built for the target.
2224 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
2225 pub struct RemoteCopyLibs
{
2227 target
: TargetSelection
,
2230 impl Step
for RemoteCopyLibs
{
2233 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
2237 fn run(self, builder
: &Builder
<'_
>) {
2238 let compiler
= self.compiler
;
2239 let target
= self.target
;
2240 if !builder
.remote_tested(target
) {
2244 builder
.ensure(compile
::Std { compiler, target }
);
2246 builder
.info(&format
!("REMOTE copy libs to emulator ({})", target
));
2247 t
!(fs
::create_dir_all(builder
.out
.join("tmp")));
2249 let server
= builder
.ensure(tool
::RemoteTestServer { compiler, target }
);
2251 // Spawn the emulator and wait for it to come online
2252 let tool
= builder
.tool_exe(Tool
::RemoteTestClient
);
2253 let mut cmd
= Command
::new(&tool
);
2254 cmd
.arg("spawn-emulator").arg(target
.triple
).arg(&server
).arg(builder
.out
.join("tmp"));
2255 if let Some(rootfs
) = builder
.qemu_rootfs(target
) {
2258 builder
.run(&mut cmd
);
2260 // Push all our dylibs to the emulator
2261 for f
in t
!(builder
.sysroot_libdir(compiler
, target
).read_dir()) {
2263 let name
= f
.file_name().into_string().unwrap();
2264 if util
::is_dylib(&name
) {
2265 builder
.run(Command
::new(&tool
).arg("push").arg(f
.path()));
2271 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
2272 pub struct Distcheck
;
2274 impl Step
for Distcheck
{
2277 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
2278 run
.path("distcheck")
2281 fn make_run(run
: RunConfig
<'_
>) {
2282 run
.builder
.ensure(Distcheck
);
2285 /// Runs "distcheck", a 'make check' from a tarball
2286 fn run(self, builder
: &Builder
<'_
>) {
2287 builder
.info("Distcheck");
2288 let dir
= builder
.out
.join("tmp").join("distcheck");
2289 let _
= fs
::remove_dir_all(&dir
);
2290 t
!(fs
::create_dir_all(&dir
));
2292 // Guarantee that these are built before we begin running.
2293 builder
.ensure(dist
::PlainSourceTarball
);
2294 builder
.ensure(dist
::Src
);
2296 let mut cmd
= Command
::new("tar");
2298 .arg(builder
.ensure(dist
::PlainSourceTarball
).tarball())
2299 .arg("--strip-components=1")
2301 builder
.run(&mut cmd
);
2303 Command
::new("./configure")
2304 .args(&builder
.config
.configure_args
)
2305 .arg("--enable-vendor")
2309 Command
::new(build_helper
::make(&builder
.config
.build
.triple
))
2314 // Now make sure that rust-src has all of libstd's dependencies
2315 builder
.info("Distcheck rust-src");
2316 let dir
= builder
.out
.join("tmp").join("distcheck-src");
2317 let _
= fs
::remove_dir_all(&dir
);
2318 t
!(fs
::create_dir_all(&dir
));
2320 let mut cmd
= Command
::new("tar");
2322 .arg(builder
.ensure(dist
::Src
).tarball())
2323 .arg("--strip-components=1")
2325 builder
.run(&mut cmd
);
2327 let toml
= dir
.join("rust-src/lib/rustlib/src/rust/library/std/Cargo.toml");
2329 Command
::new(&builder
.initial_cargo
)
2330 .arg("generate-lockfile")
2331 .arg("--manifest-path")
2338 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
2339 pub struct Bootstrap
;
2341 impl Step
for Bootstrap
{
2343 const DEFAULT
: bool
= true;
2344 const ONLY_HOSTS
: bool
= true;
2346 /// Tests the build system itself.
2347 fn run(self, builder
: &Builder
<'_
>) {
2348 let mut cmd
= Command
::new(&builder
.initial_cargo
);
2350 .current_dir(builder
.src
.join("src/bootstrap"))
2351 .env("RUSTFLAGS", "-Cdebuginfo=2")
2352 .env("CARGO_TARGET_DIR", builder
.out
.join("bootstrap"))
2353 .env("BOOTSTRAP_OUTPUT_DIRECTORY", &builder
.config
.out
)
2354 .env("BOOTSTRAP_INITIAL_CARGO", &builder
.config
.initial_cargo
)
2355 .env("RUSTC_BOOTSTRAP", "1")
2356 .env("RUSTC", &builder
.initial_rustc
);
2357 if let Some(flags
) = option_env
!("RUSTFLAGS") {
2358 // Use the same rustc flags for testing as for "normal" compilation,
2359 // so that Cargo doesn’t recompile the entire dependency graph every time:
2360 // https://github.com/rust-lang/rust/issues/49215
2361 cmd
.env("RUSTFLAGS", flags
);
2363 if !builder
.fail_fast
{
2364 cmd
.arg("--no-fail-fast");
2366 cmd
.arg("--").args(&builder
.config
.cmd
.test_args());
2367 // rustbuild tests are racy on directory creation so just run them one at a time.
2368 // Since there's not many this shouldn't be a problem.
2369 cmd
.arg("--test-threads=1");
2370 try_run(builder
, &mut cmd
);
2373 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
2374 run
.path("src/bootstrap")
2377 fn make_run(run
: RunConfig
<'_
>) {
2378 run
.builder
.ensure(Bootstrap
);
2382 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
2383 pub struct TierCheck
{
2384 pub compiler
: Compiler
,
2387 impl Step
for TierCheck
{
2389 const DEFAULT
: bool
= true;
2390 const ONLY_HOSTS
: bool
= true;
2392 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
2393 run
.path("src/tools/tier-check")
2396 fn make_run(run
: RunConfig
<'_
>) {
2398 run
.builder
.compiler_for(run
.builder
.top_stage
, run
.builder
.build
.build
, run
.target
);
2399 run
.builder
.ensure(TierCheck { compiler }
);
2402 /// Tests the Platform Support page in the rustc book.
2403 fn run(self, builder
: &Builder
<'_
>) {
2404 builder
.ensure(compile
::Std { compiler: self.compiler, target: self.compiler.host }
);
2405 let mut cargo
= tool
::prepare_tool_cargo(
2411 "src/tools/tier-check",
2415 cargo
.arg(builder
.src
.join("src/doc/rustc/src/platform-support.md"));
2416 cargo
.arg(&builder
.rustc(self.compiler
));
2417 if builder
.is_verbose() {
2418 cargo
.arg("--verbose");
2421 builder
.info("platform support check");
2422 try_run(builder
, &mut cargo
.into());
2426 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
2427 pub struct LintDocs
{
2428 pub compiler
: Compiler
,
2429 pub target
: TargetSelection
,
2432 impl Step
for LintDocs
{
2434 const DEFAULT
: bool
= true;
2435 const ONLY_HOSTS
: bool
= true;
2437 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
2438 run
.path("src/tools/lint-docs")
2441 fn make_run(run
: RunConfig
<'_
>) {
2442 run
.builder
.ensure(LintDocs
{
2443 compiler
: run
.builder
.compiler(run
.builder
.top_stage
, run
.builder
.config
.build
),
2448 /// Tests that the lint examples in the rustc book generate the correct
2449 /// lints and have the expected format.
2450 fn run(self, builder
: &Builder
<'_
>) {
2451 builder
.ensure(crate::doc
::RustcBook
{
2452 compiler
: self.compiler
,
2453 target
: self.target
,