1use std::collections::HashSet;
7use std::env::split_paths;
8use std::ffi::{OsStr, OsString};
9use std::path::{Path, PathBuf};
10use std::{env, fs, iter};
11
12use build_helper::exit;
13
14use crate::core::build_steps::compile::{Std, run_cargo};
15use crate::core::build_steps::doc::{DocumentationFormat, prepare_doc_compiler};
16use crate::core::build_steps::gcc::{Gcc, add_cg_gcc_cargo_flags};
17use crate::core::build_steps::llvm::get_llvm_version;
18use crate::core::build_steps::run::{get_completion_paths, get_help_path};
19use crate::core::build_steps::synthetic_targets::MirOptPanicAbortSyntheticTarget;
20use crate::core::build_steps::tool::{
21 self, RustcPrivateCompilers, SourceType, TEST_FLOAT_PARSE_ALLOW_FEATURES, Tool,
22 ToolTargetBuildMode, get_tool_target_compiler,
23};
24use crate::core::build_steps::toolstate::ToolState;
25use crate::core::build_steps::{compile, dist, llvm};
26use crate::core::builder::{
27 self, Alias, Builder, Compiler, Kind, RunConfig, ShouldRun, Step, StepMetadata,
28 crate_description,
29};
30use crate::core::config::TargetSelection;
31use crate::core::config::flags::{Subcommand, get_completion, top_level_help};
32use crate::core::debuggers;
33use crate::utils::build_stamp::{self, BuildStamp};
34use crate::utils::exec::{BootstrapCommand, command};
35use crate::utils::helpers::{
36 self, LldThreads, add_dylib_path, add_rustdoc_cargo_linker_args, dylib_path, dylib_path_var,
37 linker_args, linker_flags, t, target_supports_cranelift_backend, up_to_date,
38};
39use crate::utils::render_tests::{add_flags_and_try_run_tests, try_run_tests};
40use crate::{CLang, CodegenBackendKind, DocTests, GitRepo, Mode, PathSet, envify};
41
42#[derive(Debug, Clone, PartialEq, Eq, Hash)]
44pub struct CrateBootstrap {
45 path: PathBuf,
46 host: TargetSelection,
47}
48
49impl Step for CrateBootstrap {
50 type Output = ();
51 const IS_HOST: bool = true;
52 const DEFAULT: bool = true;
53
54 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
55 run.path("src/tools/jsondoclint")
60 .path("src/tools/replace-version-placeholder")
61 .path("src/tools/coverage-dump")
62 .alias("tidyselftest")
65 }
66
67 fn make_run(run: RunConfig<'_>) {
68 for path in run.paths {
71 let path = path.assert_single_path().path.clone();
72 run.builder.ensure(CrateBootstrap { host: run.target, path });
73 }
74 }
75
76 fn run(self, builder: &Builder<'_>) {
77 let bootstrap_host = builder.config.host_target;
78 let compiler = builder.compiler(0, bootstrap_host);
79 let mut path = self.path.to_str().unwrap();
80
81 if path == "tidyselftest" {
83 path = "src/tools/tidy";
84 }
85
86 let cargo = tool::prepare_tool_cargo(
87 builder,
88 compiler,
89 Mode::ToolBootstrap,
90 bootstrap_host,
91 Kind::Test,
92 path,
93 SourceType::InTree,
94 &[],
95 );
96
97 let crate_name = path.rsplit_once('/').unwrap().1;
98 run_cargo_test(cargo, &[], &[], crate_name, bootstrap_host, builder);
99 }
100
101 fn metadata(&self) -> Option<StepMetadata> {
102 Some(
103 StepMetadata::test("crate-bootstrap", self.host)
104 .with_metadata(self.path.as_path().to_string_lossy().to_string()),
105 )
106 }
107}
108
109#[derive(Debug, Clone, PartialEq, Eq, Hash)]
110pub struct Linkcheck {
111 host: TargetSelection,
112}
113
114impl Step for Linkcheck {
115 type Output = ();
116 const IS_HOST: bool = true;
117 const DEFAULT: bool = true;
118
119 fn run(self, builder: &Builder<'_>) {
124 let host = self.host;
125 let hosts = &builder.hosts;
126 let targets = &builder.targets;
127
128 if (hosts != targets) && !hosts.is_empty() && !targets.is_empty() {
133 panic!(
134 "Linkcheck currently does not support builds with different hosts and targets.
135You can skip linkcheck with --skip src/tools/linkchecker"
136 );
137 }
138
139 builder.info(&format!("Linkcheck ({host})"));
140
141 let bootstrap_host = builder.config.host_target;
143 let compiler = builder.compiler(0, bootstrap_host);
144
145 let cargo = tool::prepare_tool_cargo(
146 builder,
147 compiler,
148 Mode::ToolBootstrap,
149 bootstrap_host,
150 Kind::Test,
151 "src/tools/linkchecker",
152 SourceType::InTree,
153 &[],
154 );
155 run_cargo_test(cargo, &[], &[], "linkchecker self tests", bootstrap_host, builder);
156
157 if builder.doc_tests == DocTests::No {
158 return;
159 }
160
161 builder.run_default_doc_steps();
163
164 let linkchecker = builder.tool_cmd(Tool::Linkchecker);
166
167 let _guard = builder.msg_test("Linkcheck", bootstrap_host, 1);
169 let _time = helpers::timeit(builder);
170 linkchecker.delay_failure().arg(builder.out.join(host).join("doc")).run(builder);
171 }
172
173 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
174 let builder = run.builder;
175 let run = run.path("src/tools/linkchecker");
176 run.default_condition(builder.config.docs)
177 }
178
179 fn make_run(run: RunConfig<'_>) {
180 run.builder.ensure(Linkcheck { host: run.target });
181 }
182
183 fn metadata(&self) -> Option<StepMetadata> {
184 Some(StepMetadata::test("link-check", self.host))
185 }
186}
187
188fn check_if_tidy_is_installed(builder: &Builder<'_>) -> bool {
189 command("tidy").allow_failure().arg("--version").run_capture_stdout(builder).is_success()
190}
191
192#[derive(Debug, Clone, PartialEq, Eq, Hash)]
193pub struct HtmlCheck {
194 target: TargetSelection,
195}
196
197impl Step for HtmlCheck {
198 type Output = ();
199 const DEFAULT: bool = true;
200 const IS_HOST: bool = true;
201
202 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
203 let builder = run.builder;
204 let run = run.path("src/tools/html-checker");
205 run.lazy_default_condition(Box::new(|| check_if_tidy_is_installed(builder)))
206 }
207
208 fn make_run(run: RunConfig<'_>) {
209 run.builder.ensure(HtmlCheck { target: run.target });
210 }
211
212 fn run(self, builder: &Builder<'_>) {
213 if !check_if_tidy_is_installed(builder) {
214 eprintln!("not running HTML-check tool because `tidy` is missing");
215 eprintln!(
216 "You need the HTML tidy tool https://www.html-tidy.org/, this tool is *not* part of the rust project and needs to be installed separately, for example via your package manager."
217 );
218 panic!("Cannot run html-check tests");
219 }
220 builder.run_default_doc_steps();
222 builder.ensure(crate::core::build_steps::doc::Rustc::for_stage(
223 builder,
224 builder.top_stage,
225 self.target,
226 ));
227
228 builder
229 .tool_cmd(Tool::HtmlChecker)
230 .delay_failure()
231 .arg(builder.doc_out(self.target))
232 .run(builder);
233 }
234
235 fn metadata(&self) -> Option<StepMetadata> {
236 Some(StepMetadata::test("html-check", self.target))
237 }
238}
239
240#[derive(Debug, Clone, PartialEq, Eq, Hash)]
244pub struct Cargotest {
245 build_compiler: Compiler,
246 host: TargetSelection,
247}
248
249impl Step for Cargotest {
250 type Output = ();
251 const IS_HOST: bool = true;
252
253 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
254 run.path("src/tools/cargotest")
255 }
256
257 fn make_run(run: RunConfig<'_>) {
258 if run.builder.top_stage == 0 {
259 eprintln!(
260 "ERROR: running cargotest with stage 0 is currently unsupported. Use at least stage 1."
261 );
262 exit!(1);
263 }
264 run.builder.ensure(Cargotest {
268 build_compiler: run.builder.compiler(run.builder.top_stage - 1, run.target),
269 host: run.target,
270 });
271 }
272
273 fn run(self, builder: &Builder<'_>) {
278 let cargo =
288 builder.ensure(tool::Cargo::from_build_compiler(self.build_compiler, self.host));
289 let tested_compiler = builder.compiler(self.build_compiler.stage + 1, self.host);
290 builder.std(tested_compiler, self.host);
291
292 let out_dir = builder.out.join("ct");
296 t!(fs::create_dir_all(&out_dir));
297
298 let _time = helpers::timeit(builder);
299 let mut cmd = builder.tool_cmd(Tool::CargoTest);
300 cmd.arg(&cargo.tool_path)
301 .arg(&out_dir)
302 .args(builder.config.test_args())
303 .env("RUSTC", builder.rustc(tested_compiler))
304 .env("RUSTDOC", builder.rustdoc_for_compiler(tested_compiler));
305 add_rustdoc_cargo_linker_args(&mut cmd, builder, tested_compiler.host, LldThreads::No);
306 cmd.delay_failure().run(builder);
307 }
308
309 fn metadata(&self) -> Option<StepMetadata> {
310 Some(StepMetadata::test("cargotest", self.host).stage(self.build_compiler.stage + 1))
311 }
312}
313
314#[derive(Debug, Clone, PartialEq, Eq, Hash)]
317pub struct Cargo {
318 build_compiler: Compiler,
319 host: TargetSelection,
320}
321
322impl Cargo {
323 const CRATE_PATH: &str = "src/tools/cargo";
324}
325
326impl Step for Cargo {
327 type Output = ();
328 const IS_HOST: bool = true;
329
330 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
331 run.path(Self::CRATE_PATH)
332 }
333
334 fn make_run(run: RunConfig<'_>) {
335 run.builder.ensure(Cargo {
336 build_compiler: get_tool_target_compiler(
337 run.builder,
338 ToolTargetBuildMode::Build(run.target),
339 ),
340 host: run.target,
341 });
342 }
343
344 fn run(self, builder: &Builder<'_>) {
346 builder.ensure(tool::Cargo::from_build_compiler(self.build_compiler, self.host));
350
351 let tested_compiler = builder.compiler(self.build_compiler.stage + 1, self.host);
352 builder.std(tested_compiler, self.host);
353 builder.rustdoc_for_compiler(tested_compiler);
357
358 let cargo = tool::prepare_tool_cargo(
359 builder,
360 self.build_compiler,
361 Mode::ToolTarget,
362 self.host,
363 Kind::Test,
364 Self::CRATE_PATH,
365 SourceType::Submodule,
366 &[],
367 );
368
369 let mut cargo = prepare_cargo_test(cargo, &[], &[], self.host, builder);
371
372 cargo.env("CFG_DISABLE_CROSS_TESTS", "1");
375 cargo.env("CARGO_TEST_DISABLE_NIGHTLY", "1");
378
379 cargo.env("PATH", bin_path_for_cargo(builder, tested_compiler));
383
384 let mut existing_dylib_paths = cargo
389 .get_envs()
390 .find(|(k, _)| *k == OsStr::new(dylib_path_var()))
391 .and_then(|(_, v)| v)
392 .map(|value| split_paths(value).collect::<Vec<PathBuf>>())
393 .unwrap_or_default();
394 existing_dylib_paths.insert(0, builder.rustc_libdir(tested_compiler));
395 add_dylib_path(existing_dylib_paths, &mut cargo);
396
397 cargo.env("CARGO_RUSTC_CURRENT_DIR", builder.src.display().to_string());
401
402 #[cfg(feature = "build-metrics")]
403 builder.metrics.begin_test_suite(
404 build_helper::metrics::TestSuiteMetadata::CargoPackage {
405 crates: vec!["cargo".into()],
406 target: self.host.triple.to_string(),
407 host: self.host.triple.to_string(),
408 stage: self.build_compiler.stage + 1,
409 },
410 builder,
411 );
412
413 let _time = helpers::timeit(builder);
414 add_flags_and_try_run_tests(builder, &mut cargo);
415 }
416
417 fn metadata(&self) -> Option<StepMetadata> {
418 Some(StepMetadata::test("cargo", self.host).built_by(self.build_compiler))
419 }
420}
421
422#[derive(Debug, Clone, PartialEq, Eq, Hash)]
423pub struct RustAnalyzer {
424 compilers: RustcPrivateCompilers,
425}
426
427impl Step for RustAnalyzer {
428 type Output = ();
429 const IS_HOST: bool = true;
430 const DEFAULT: bool = true;
431
432 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
433 run.path("src/tools/rust-analyzer")
434 }
435
436 fn make_run(run: RunConfig<'_>) {
437 run.builder.ensure(Self {
438 compilers: RustcPrivateCompilers::new(
439 run.builder,
440 run.builder.top_stage,
441 run.builder.host_target,
442 ),
443 });
444 }
445
446 fn run(self, builder: &Builder<'_>) {
448 let host = self.compilers.target();
449
450 let workspace_path = "src/tools/rust-analyzer";
451 let crate_path = "src/tools/rust-analyzer/crates/proc-macro-srv";
454 let mut cargo = tool::prepare_tool_cargo(
455 builder,
456 self.compilers.build_compiler(),
457 Mode::ToolRustcPrivate,
458 host,
459 Kind::Test,
460 crate_path,
461 SourceType::InTree,
462 &["in-rust-tree".to_owned()],
463 );
464 cargo.allow_features(tool::RustAnalyzer::ALLOW_FEATURES);
465
466 let dir = builder.src.join(workspace_path);
467 cargo.env("CARGO_WORKSPACE_DIR", &dir);
470
471 cargo.env("SKIP_SLOW_TESTS", "1");
474
475 cargo.add_rustc_lib_path(builder);
476 run_cargo_test(cargo, &[], &[], "rust-analyzer", host, builder);
477 }
478
479 fn metadata(&self) -> Option<StepMetadata> {
480 Some(
481 StepMetadata::test("rust-analyzer", self.compilers.target())
482 .built_by(self.compilers.build_compiler()),
483 )
484 }
485}
486
487#[derive(Debug, Clone, PartialEq, Eq, Hash)]
489pub struct Rustfmt {
490 compilers: RustcPrivateCompilers,
491}
492
493impl Step for Rustfmt {
494 type Output = ();
495 const IS_HOST: bool = true;
496
497 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
498 run.path("src/tools/rustfmt")
499 }
500
501 fn make_run(run: RunConfig<'_>) {
502 run.builder.ensure(Rustfmt {
503 compilers: RustcPrivateCompilers::new(
504 run.builder,
505 run.builder.top_stage,
506 run.builder.host_target,
507 ),
508 });
509 }
510
511 fn run(self, builder: &Builder<'_>) {
513 let tool_result = builder.ensure(tool::Rustfmt::from_compilers(self.compilers));
514 let build_compiler = tool_result.build_compiler;
515 let target = self.compilers.target();
516
517 let mut cargo = tool::prepare_tool_cargo(
518 builder,
519 build_compiler,
520 Mode::ToolRustcPrivate,
521 target,
522 Kind::Test,
523 "src/tools/rustfmt",
524 SourceType::InTree,
525 &[],
526 );
527
528 let dir = testdir(builder, target);
529 t!(fs::create_dir_all(&dir));
530 cargo.env("RUSTFMT_TEST_DIR", dir);
531
532 cargo.add_rustc_lib_path(builder);
533
534 run_cargo_test(cargo, &[], &[], "rustfmt", target, builder);
535 }
536
537 fn metadata(&self) -> Option<StepMetadata> {
538 Some(
539 StepMetadata::test("rustfmt", self.compilers.target())
540 .built_by(self.compilers.build_compiler()),
541 )
542 }
543}
544
545#[derive(Debug, Clone, PartialEq, Eq, Hash)]
546pub struct Miri {
547 target: TargetSelection,
548}
549
550impl Miri {
551 pub fn build_miri_sysroot(
553 builder: &Builder<'_>,
554 compiler: Compiler,
555 target: TargetSelection,
556 ) -> PathBuf {
557 let miri_sysroot = builder.out.join(compiler.host).join("miri-sysroot");
558 let mut cargo = builder::Cargo::new(
559 builder,
560 compiler,
561 Mode::Std,
562 SourceType::Submodule,
563 target,
564 Kind::MiriSetup,
565 );
566
567 cargo.env("MIRI_LIB_SRC", builder.src.join("library"));
569 cargo.env("MIRI_SYSROOT", &miri_sysroot);
571
572 let mut cargo = BootstrapCommand::from(cargo);
573 let _guard =
574 builder.msg(Kind::Build, "miri sysroot", Mode::ToolRustcPrivate, compiler, target);
575 cargo.run(builder);
576
577 cargo.arg("--print-sysroot");
583
584 builder.do_if_verbose(|| println!("running: {cargo:?}"));
585 let stdout = cargo.run_capture_stdout(builder).stdout();
586 let sysroot = stdout.trim_end();
588 builder.do_if_verbose(|| println!("`cargo miri setup --print-sysroot` said: {sysroot:?}"));
589 PathBuf::from(sysroot)
590 }
591}
592
593impl Step for Miri {
594 type Output = ();
595
596 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
597 run.path("src/tools/miri")
598 }
599
600 fn make_run(run: RunConfig<'_>) {
601 run.builder.ensure(Miri { target: run.target });
602 }
603
604 fn run(self, builder: &Builder<'_>) {
606 let host = builder.build.host_target;
607 let target = self.target;
608 let stage = builder.top_stage;
609 if stage == 0 {
610 eprintln!("miri cannot be tested at stage 0");
611 std::process::exit(1);
612 }
613
614 let compilers = RustcPrivateCompilers::new(builder, stage, host);
616
617 let miri = builder.ensure(tool::Miri::from_compilers(compilers));
619 builder.ensure(tool::CargoMiri::from_compilers(compilers));
621
622 let target_compiler = compilers.target_compiler();
623
624 let miri_sysroot = Miri::build_miri_sysroot(builder, target_compiler, target);
627 builder.std(target_compiler, host);
628 let host_sysroot = builder.sysroot(target_compiler);
629
630 if !builder.config.dry_run() {
633 let ui_test_dep_dir = builder
636 .stage_out(miri.build_compiler, Mode::ToolStd)
637 .join(host)
638 .join("tmp")
639 .join("miri_ui");
640 build_stamp::clear_if_dirty(builder, &ui_test_dep_dir, &miri_sysroot);
644 }
645
646 let mut cargo = tool::prepare_tool_cargo(
649 builder,
650 miri.build_compiler,
651 Mode::ToolRustcPrivate,
652 host,
653 Kind::Test,
654 "src/tools/miri",
655 SourceType::InTree,
656 &[],
657 );
658
659 cargo.add_rustc_lib_path(builder);
660
661 let mut cargo = prepare_cargo_test(cargo, &[], &[], host, builder);
664
665 cargo.env("MIRI_SYSROOT", &miri_sysroot);
667 cargo.env("MIRI_HOST_SYSROOT", &host_sysroot);
668 cargo.env("MIRI", &miri.tool_path);
669
670 cargo.env("MIRI_TEST_TARGET", target.rustc_target_arg());
672
673 {
674 let _guard = builder.msg_test("miri", target, target_compiler.stage);
675 let _time = helpers::timeit(builder);
676 cargo.run(builder);
677 }
678
679 if builder.config.test_args().is_empty() {
681 cargo.env("MIRIFLAGS", "-O -Zmir-opt-level=4 -Cdebug-assertions=yes");
682 cargo.env("MIRI_SKIP_UI_CHECKS", "1");
684 cargo.env_remove("RUSTC_BLESS");
686 cargo.args(["tests/pass", "tests/panic"]);
688
689 {
690 let _guard =
691 builder.msg_test("miri (mir-opt-level 4)", target, target_compiler.stage);
692 let _time = helpers::timeit(builder);
693 cargo.run(builder);
694 }
695 }
696 }
697}
698
699#[derive(Debug, Clone, PartialEq, Eq, Hash)]
702pub struct CargoMiri {
703 target: TargetSelection,
704}
705
706impl Step for CargoMiri {
707 type Output = ();
708
709 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
710 run.path("src/tools/miri/cargo-miri")
711 }
712
713 fn make_run(run: RunConfig<'_>) {
714 run.builder.ensure(CargoMiri { target: run.target });
715 }
716
717 fn run(self, builder: &Builder<'_>) {
719 let host = builder.build.host_target;
720 let target = self.target;
721 let stage = builder.top_stage;
722 if stage == 0 {
723 eprintln!("cargo-miri cannot be tested at stage 0");
724 std::process::exit(1);
725 }
726
727 let build_compiler = builder.compiler(stage, host);
729
730 let mut cargo = tool::prepare_tool_cargo(
735 builder,
736 build_compiler,
737 Mode::ToolStd, target,
739 Kind::MiriTest,
740 "src/tools/miri/test-cargo-miri",
741 SourceType::Submodule,
742 &[],
743 );
744
745 match builder.doc_tests {
748 DocTests::Yes => {}
749 DocTests::No => {
750 cargo.args(["--lib", "--bins", "--examples", "--tests", "--benches"]);
751 }
752 DocTests::Only => {
753 cargo.arg("--doc");
754 }
755 }
756 cargo.arg("--").args(builder.config.test_args());
757
758 let mut cargo = BootstrapCommand::from(cargo);
760 {
761 let _guard = builder.msg_test("cargo-miri", target, stage);
762 let _time = helpers::timeit(builder);
763 cargo.run(builder);
764 }
765 }
766}
767
768#[derive(Debug, Clone, PartialEq, Eq, Hash)]
769pub struct CompiletestTest {
770 host: TargetSelection,
771}
772
773impl Step for CompiletestTest {
774 type Output = ();
775
776 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
777 run.path("src/tools/compiletest")
778 }
779
780 fn make_run(run: RunConfig<'_>) {
781 run.builder.ensure(CompiletestTest { host: run.target });
782 }
783
784 fn run(self, builder: &Builder<'_>) {
786 let host = self.host;
787
788 if builder.top_stage == 0 && !builder.config.compiletest_allow_stage0 {
794 eprintln!("\
795ERROR: `--stage 0` causes compiletest to query information from the stage0 (precompiled) compiler, instead of the in-tree compiler, which can cause some tests to fail inappropriately
796NOTE: if you're sure you want to do this, please open an issue as to why. In the meantime, you can override this with `--set build.compiletest-allow-stage0=true`."
797 );
798 crate::exit!(1);
799 }
800
801 let bootstrap_compiler = builder.compiler(0, host);
802 let staged_compiler = builder.compiler(builder.top_stage, host);
803
804 let mut cargo = tool::prepare_tool_cargo(
805 builder,
806 bootstrap_compiler,
807 Mode::ToolBootstrap,
808 host,
809 Kind::Test,
810 "src/tools/compiletest",
811 SourceType::InTree,
812 &[],
813 );
814
815 cargo.env("TEST_RUSTC", builder.rustc(staged_compiler));
819
820 run_cargo_test(cargo, &[], &[], "compiletest self test", host, builder);
821 }
822}
823
824#[derive(Debug, Clone, PartialEq, Eq, Hash)]
825pub struct Clippy {
826 compilers: RustcPrivateCompilers,
827}
828
829impl Step for Clippy {
830 type Output = ();
831 const IS_HOST: bool = true;
832 const DEFAULT: bool = false;
833
834 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
835 run.suite_path("src/tools/clippy/tests").path("src/tools/clippy")
836 }
837
838 fn make_run(run: RunConfig<'_>) {
839 run.builder.ensure(Clippy {
840 compilers: RustcPrivateCompilers::new(
841 run.builder,
842 run.builder.top_stage,
843 run.builder.host_target,
844 ),
845 });
846 }
847
848 fn run(self, builder: &Builder<'_>) {
850 let target = self.compilers.target();
851
852 let compilers = self.compilers;
856 let target_compiler = compilers.target_compiler();
857
858 let tool_result = builder.ensure(tool::Clippy::from_compilers(compilers));
859 let build_compiler = tool_result.build_compiler;
860 let mut cargo = tool::prepare_tool_cargo(
861 builder,
862 build_compiler,
863 Mode::ToolRustcPrivate,
864 target,
865 Kind::Test,
866 "src/tools/clippy",
867 SourceType::InTree,
868 &[],
869 );
870
871 cargo.env("RUSTC_TEST_SUITE", builder.rustc(build_compiler));
872 cargo.env("RUSTC_LIB_PATH", builder.rustc_libdir(build_compiler));
873 let host_libs =
874 builder.stage_out(build_compiler, Mode::ToolRustcPrivate).join(builder.cargo_dir());
875 cargo.env("HOST_LIBS", host_libs);
876
877 builder.std(target_compiler, target);
879 cargo.env("TEST_SYSROOT", builder.sysroot(target_compiler));
880 cargo.env("TEST_RUSTC", builder.rustc(target_compiler));
881 cargo.env("TEST_RUSTC_LIB", builder.rustc_libdir(target_compiler));
882
883 'partially_test: {
885 let paths = &builder.config.paths[..];
886 let mut test_names = Vec::new();
887 for path in paths {
888 if let Some(path) =
889 helpers::is_valid_test_suite_arg(path, "src/tools/clippy/tests", builder)
890 {
891 test_names.push(path);
892 } else if path.ends_with("src/tools/clippy") {
893 break 'partially_test;
895 }
896 }
897 cargo.env("TESTNAME", test_names.join(","));
898 }
899
900 cargo.add_rustc_lib_path(builder);
901 let cargo = prepare_cargo_test(cargo, &[], &[], target, builder);
902
903 let _guard = builder.msg_test("clippy", target, target_compiler.stage);
904
905 if cargo.allow_failure().run(builder) {
907 return;
909 }
910
911 if !builder.config.cmd.bless() {
912 crate::exit!(1);
913 }
914 }
915
916 fn metadata(&self) -> Option<StepMetadata> {
917 Some(
918 StepMetadata::test("clippy", self.compilers.target())
919 .built_by(self.compilers.build_compiler()),
920 )
921 }
922}
923
924fn bin_path_for_cargo(builder: &Builder<'_>, compiler: Compiler) -> OsString {
925 let path = builder.sysroot(compiler).join("bin");
926 let old_path = env::var_os("PATH").unwrap_or_default();
927 env::join_paths(iter::once(path).chain(env::split_paths(&old_path))).expect("")
928}
929
930#[derive(Debug, Clone, Hash, PartialEq, Eq)]
932pub struct RustdocTheme {
933 test_compiler: Compiler,
935}
936
937impl Step for RustdocTheme {
938 type Output = ();
939 const DEFAULT: bool = true;
940 const IS_HOST: bool = true;
941
942 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
943 run.path("src/tools/rustdoc-themes")
944 }
945
946 fn make_run(run: RunConfig<'_>) {
947 let test_compiler = run.builder.compiler(run.builder.top_stage, run.target);
948
949 run.builder.ensure(RustdocTheme { test_compiler });
950 }
951
952 fn run(self, builder: &Builder<'_>) {
953 let rustdoc = builder.bootstrap_out.join("rustdoc");
954 let mut cmd = builder.tool_cmd(Tool::RustdocTheme);
955 cmd.arg(rustdoc.to_str().unwrap())
956 .arg(builder.src.join("src/librustdoc/html/static/css/rustdoc.css").to_str().unwrap())
957 .env("RUSTC_STAGE", self.test_compiler.stage.to_string())
958 .env("RUSTC_SYSROOT", builder.sysroot(self.test_compiler))
959 .env(
960 "RUSTDOC_LIBDIR",
961 builder.sysroot_target_libdir(self.test_compiler, self.test_compiler.host),
962 )
963 .env("CFG_RELEASE_CHANNEL", &builder.config.channel)
964 .env("RUSTDOC_REAL", builder.rustdoc_for_compiler(self.test_compiler))
965 .env("RUSTC_BOOTSTRAP", "1");
966 cmd.args(linker_args(builder, self.test_compiler.host, LldThreads::No));
967
968 cmd.delay_failure().run(builder);
969 }
970
971 fn metadata(&self) -> Option<StepMetadata> {
972 Some(
973 StepMetadata::test("rustdoc-theme", self.test_compiler.host)
974 .stage(self.test_compiler.stage),
975 )
976 }
977}
978
979#[derive(Debug, Clone, Hash, PartialEq, Eq)]
981pub struct RustdocJSStd {
982 build_compiler: Compiler,
984 target: TargetSelection,
985}
986
987impl Step for RustdocJSStd {
988 type Output = ();
989 const DEFAULT: bool = true;
990 const IS_HOST: bool = true;
991
992 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
993 let default = run.builder.config.nodejs.is_some();
994 run.suite_path("tests/rustdoc-js-std").default_condition(default)
995 }
996
997 fn make_run(run: RunConfig<'_>) {
998 run.builder.ensure(RustdocJSStd {
999 build_compiler: run.builder.compiler(run.builder.top_stage, run.builder.host_target),
1000 target: run.target,
1001 });
1002 }
1003
1004 fn run(self, builder: &Builder<'_>) {
1005 let nodejs =
1006 builder.config.nodejs.as_ref().expect("need nodejs to run rustdoc-js-std tests");
1007 let mut command = command(nodejs);
1008 command
1009 .arg(builder.src.join("src/tools/rustdoc-js/tester.js"))
1010 .arg("--crate-name")
1011 .arg("std")
1012 .arg("--resource-suffix")
1013 .arg(&builder.version)
1014 .arg("--doc-folder")
1015 .arg(builder.doc_out(self.target))
1016 .arg("--test-folder")
1017 .arg(builder.src.join("tests/rustdoc-js-std"));
1018 for path in &builder.paths {
1019 if let Some(p) = helpers::is_valid_test_suite_arg(path, "tests/rustdoc-js-std", builder)
1020 {
1021 if !p.ends_with(".js") {
1022 eprintln!("A non-js file was given: `{}`", path.display());
1023 panic!("Cannot run rustdoc-js-std tests");
1024 }
1025 command.arg("--test-file").arg(path);
1026 }
1027 }
1028 builder.ensure(crate::core::build_steps::doc::Std::from_build_compiler(
1029 self.build_compiler,
1030 self.target,
1031 DocumentationFormat::Html,
1032 ));
1033 let _guard = builder.msg_test("rustdoc-js-std", self.target, self.build_compiler.stage);
1034 command.run(builder);
1035 }
1036
1037 fn metadata(&self) -> Option<StepMetadata> {
1038 Some(StepMetadata::test("rustdoc-js-std", self.target).stage(self.build_compiler.stage))
1039 }
1040}
1041
1042#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1043pub struct RustdocJSNotStd {
1044 pub target: TargetSelection,
1045 pub compiler: Compiler,
1046}
1047
1048impl Step for RustdocJSNotStd {
1049 type Output = ();
1050 const DEFAULT: bool = true;
1051 const IS_HOST: bool = true;
1052
1053 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1054 let default = run.builder.config.nodejs.is_some();
1055 run.suite_path("tests/rustdoc-js").default_condition(default)
1056 }
1057
1058 fn make_run(run: RunConfig<'_>) {
1059 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1060 run.builder.ensure(RustdocJSNotStd { target: run.target, compiler });
1061 }
1062
1063 fn run(self, builder: &Builder<'_>) {
1064 builder.ensure(Compiletest {
1065 test_compiler: self.compiler,
1066 target: self.target,
1067 mode: "rustdoc-js",
1068 suite: "rustdoc-js",
1069 path: "tests/rustdoc-js",
1070 compare_mode: None,
1071 });
1072 }
1073}
1074
1075fn get_browser_ui_test_version_inner(
1076 builder: &Builder<'_>,
1077 yarn: &Path,
1078 global: bool,
1079) -> Option<String> {
1080 let mut command = command(yarn);
1081 command
1082 .arg("--cwd")
1083 .arg(&builder.build.out)
1084 .arg("list")
1085 .arg("--parseable")
1086 .arg("--long")
1087 .arg("--depth=0");
1088 if global {
1089 command.arg("--global");
1090 }
1091 let lines = command.allow_failure().run_capture(builder).stdout();
1092 lines
1093 .lines()
1094 .find_map(|l| l.split(':').nth(1)?.strip_prefix("browser-ui-test@"))
1095 .map(|v| v.to_owned())
1096}
1097
1098fn get_browser_ui_test_version(builder: &Builder<'_>, yarn: &Path) -> Option<String> {
1099 get_browser_ui_test_version_inner(builder, yarn, false)
1100 .or_else(|| get_browser_ui_test_version_inner(builder, yarn, true))
1101}
1102
1103#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1105pub struct RustdocGUI {
1106 test_compiler: Compiler,
1108 target: TargetSelection,
1109}
1110
1111impl Step for RustdocGUI {
1112 type Output = ();
1113 const DEFAULT: bool = true;
1114 const IS_HOST: bool = true;
1115
1116 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1117 let builder = run.builder;
1118 let run = run.suite_path("tests/rustdoc-gui");
1119 run.lazy_default_condition(Box::new(move || {
1120 builder.config.nodejs.is_some()
1121 && builder.doc_tests != DocTests::Only
1122 && builder
1123 .config
1124 .yarn
1125 .as_ref()
1126 .map(|p| get_browser_ui_test_version(builder, p).is_some())
1127 .unwrap_or(false)
1128 }))
1129 }
1130
1131 fn make_run(run: RunConfig<'_>) {
1132 let test_compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1133 run.builder.ensure(RustdocGUI { test_compiler, target: run.target });
1134 }
1135
1136 fn run(self, builder: &Builder<'_>) {
1137 builder.std(self.test_compiler, self.target);
1138
1139 let mut cmd = builder.tool_cmd(Tool::RustdocGUITest);
1140
1141 let out_dir = builder.test_out(self.target).join("rustdoc-gui");
1142 build_stamp::clear_if_dirty(
1143 builder,
1144 &out_dir,
1145 &builder.rustdoc_for_compiler(self.test_compiler),
1146 );
1147
1148 if let Some(src) = builder.config.src.to_str() {
1149 cmd.arg("--rust-src").arg(src);
1150 }
1151
1152 if let Some(out_dir) = out_dir.to_str() {
1153 cmd.arg("--out-dir").arg(out_dir);
1154 }
1155
1156 if let Some(initial_cargo) = builder.config.initial_cargo.to_str() {
1157 cmd.arg("--initial-cargo").arg(initial_cargo);
1158 }
1159
1160 cmd.arg("--jobs").arg(builder.jobs().to_string());
1161
1162 cmd.env("RUSTDOC", builder.rustdoc_for_compiler(self.test_compiler))
1163 .env("RUSTC", builder.rustc(self.test_compiler));
1164
1165 add_rustdoc_cargo_linker_args(&mut cmd, builder, self.test_compiler.host, LldThreads::No);
1166
1167 for path in &builder.paths {
1168 if let Some(p) = helpers::is_valid_test_suite_arg(path, "tests/rustdoc-gui", builder) {
1169 if !p.ends_with(".goml") {
1170 eprintln!("A non-goml file was given: `{}`", path.display());
1171 panic!("Cannot run rustdoc-gui tests");
1172 }
1173 if let Some(name) = path.file_name().and_then(|f| f.to_str()) {
1174 cmd.arg("--goml-file").arg(name);
1175 }
1176 }
1177 }
1178
1179 for test_arg in builder.config.test_args() {
1180 cmd.arg("--test-arg").arg(test_arg);
1181 }
1182
1183 if let Some(ref nodejs) = builder.config.nodejs {
1184 cmd.arg("--nodejs").arg(nodejs);
1185 }
1186
1187 if let Some(ref yarn) = builder.config.yarn {
1188 cmd.arg("--yarn").arg(yarn);
1189 }
1190
1191 let _time = helpers::timeit(builder);
1192 let _guard = builder.msg_test("rustdoc-gui", self.target, self.test_compiler.stage);
1193 try_run_tests(builder, &mut cmd, true);
1194 }
1195
1196 fn metadata(&self) -> Option<StepMetadata> {
1197 Some(StepMetadata::test("rustdoc-gui", self.target).stage(self.test_compiler.stage))
1198 }
1199}
1200
1201#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1206pub struct Tidy;
1207
1208impl Step for Tidy {
1209 type Output = ();
1210 const DEFAULT: bool = true;
1211 const IS_HOST: bool = true;
1212
1213 fn run(self, builder: &Builder<'_>) {
1222 let mut cmd = builder.tool_cmd(Tool::Tidy);
1223 cmd.arg(&builder.src);
1224 cmd.arg(&builder.initial_cargo);
1225 cmd.arg(&builder.out);
1226 let jobs = builder.config.jobs.unwrap_or_else(|| {
1228 8 * std::thread::available_parallelism().map_or(1, std::num::NonZeroUsize::get) as u32
1229 });
1230 cmd.arg(jobs.to_string());
1231 if let Some(yarn) = &builder.config.yarn {
1233 cmd.arg(yarn);
1234 } else {
1235 cmd.arg("yarn");
1236 }
1237 if builder.is_verbose() {
1238 cmd.arg("--verbose");
1239 }
1240 if builder.config.cmd.bless() {
1241 cmd.arg("--bless");
1242 }
1243 if let Some(s) =
1244 builder.config.cmd.extra_checks().or(builder.config.tidy_extra_checks.as_deref())
1245 {
1246 cmd.arg(format!("--extra-checks={s}"));
1247 }
1248 let mut args = std::env::args_os();
1249 if args.any(|arg| arg == OsStr::new("--")) {
1250 cmd.arg("--");
1251 cmd.args(args);
1252 }
1253
1254 if builder.config.channel == "dev" || builder.config.channel == "nightly" {
1255 if !builder.config.json_output {
1256 builder.info("fmt check");
1257 if builder.config.initial_rustfmt.is_none() {
1258 let inferred_rustfmt_dir = builder.initial_sysroot.join("bin");
1259 eprintln!(
1260 "\
1261ERROR: no `rustfmt` binary found in {PATH}
1262INFO: `rust.channel` is currently set to \"{CHAN}\"
1263HELP: if you are testing a beta branch, set `rust.channel` to \"beta\" in the `bootstrap.toml` file
1264HELP: to skip test's attempt to check tidiness, pass `--skip src/tools/tidy` to `x.py test`",
1265 PATH = inferred_rustfmt_dir.display(),
1266 CHAN = builder.config.channel,
1267 );
1268 crate::exit!(1);
1269 }
1270 let all = false;
1271 crate::core::build_steps::format::format(
1272 builder,
1273 !builder.config.cmd.bless(),
1274 all,
1275 &[],
1276 );
1277 } else {
1278 eprintln!(
1279 "WARNING: `--json-output` is not supported on rustfmt, formatting will be skipped"
1280 );
1281 }
1282 }
1283
1284 builder.info("tidy check");
1285 cmd.delay_failure().run(builder);
1286
1287 builder.info("x.py completions check");
1288 let completion_paths = get_completion_paths(builder);
1289 if builder.config.cmd.bless() {
1290 builder.ensure(crate::core::build_steps::run::GenerateCompletions);
1291 } else if completion_paths
1292 .into_iter()
1293 .any(|(shell, path)| get_completion(shell, &path).is_some())
1294 {
1295 eprintln!(
1296 "x.py completions were changed; run `x.py run generate-completions` to update them"
1297 );
1298 crate::exit!(1);
1299 }
1300
1301 builder.info("x.py help check");
1302 if builder.config.cmd.bless() {
1303 builder.ensure(crate::core::build_steps::run::GenerateHelp);
1304 } else {
1305 let help_path = get_help_path(builder);
1306 let cur_help = std::fs::read_to_string(&help_path).unwrap_or_else(|err| {
1307 eprintln!("couldn't read {}: {}", help_path.display(), err);
1308 crate::exit!(1);
1309 });
1310 let new_help = top_level_help();
1311
1312 if new_help != cur_help {
1313 eprintln!("x.py help was changed; run `x.py run generate-help` to update it");
1314 crate::exit!(1);
1315 }
1316 }
1317 }
1318
1319 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1320 let default = run.builder.doc_tests != DocTests::Only;
1321 run.path("src/tools/tidy").default_condition(default)
1322 }
1323
1324 fn make_run(run: RunConfig<'_>) {
1325 run.builder.ensure(Tidy);
1326 }
1327
1328 fn metadata(&self) -> Option<StepMetadata> {
1329 Some(StepMetadata::test("tidy", TargetSelection::default()))
1330 }
1331}
1332
1333#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1336pub struct CrateRunMakeSupport {
1337 host: TargetSelection,
1338}
1339
1340impl Step for CrateRunMakeSupport {
1341 type Output = ();
1342 const IS_HOST: bool = true;
1343
1344 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1345 run.path("src/tools/run-make-support")
1346 }
1347
1348 fn make_run(run: RunConfig<'_>) {
1349 run.builder.ensure(CrateRunMakeSupport { host: run.target });
1350 }
1351
1352 fn run(self, builder: &Builder<'_>) {
1354 let host = self.host;
1355 let compiler = builder.compiler(0, host);
1356
1357 let mut cargo = tool::prepare_tool_cargo(
1358 builder,
1359 compiler,
1360 Mode::ToolBootstrap,
1361 host,
1362 Kind::Test,
1363 "src/tools/run-make-support",
1364 SourceType::InTree,
1365 &[],
1366 );
1367 cargo.allow_features("test");
1368 run_cargo_test(cargo, &[], &[], "run-make-support self test", host, builder);
1369 }
1370}
1371
1372#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1373pub struct CrateBuildHelper {
1374 host: TargetSelection,
1375}
1376
1377impl Step for CrateBuildHelper {
1378 type Output = ();
1379 const IS_HOST: bool = true;
1380
1381 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1382 run.path("src/build_helper")
1383 }
1384
1385 fn make_run(run: RunConfig<'_>) {
1386 run.builder.ensure(CrateBuildHelper { host: run.target });
1387 }
1388
1389 fn run(self, builder: &Builder<'_>) {
1391 let host = self.host;
1392 let compiler = builder.compiler(0, host);
1393
1394 let mut cargo = tool::prepare_tool_cargo(
1395 builder,
1396 compiler,
1397 Mode::ToolBootstrap,
1398 host,
1399 Kind::Test,
1400 "src/build_helper",
1401 SourceType::InTree,
1402 &[],
1403 );
1404 cargo.allow_features("test");
1405 run_cargo_test(cargo, &[], &[], "build_helper self test", host, builder);
1406 }
1407}
1408
1409fn testdir(builder: &Builder<'_>, host: TargetSelection) -> PathBuf {
1410 builder.out.join(host).join("test")
1411}
1412
1413macro_rules! test {
1415 (
1416 $( #[$attr:meta] )* $name:ident {
1418 path: $path:expr,
1419 mode: $mode:expr,
1420 suite: $suite:expr,
1421 default: $default:expr
1422 $( , IS_HOST: $IS_HOST:expr )? $( , compare_mode: $compare_mode:expr )? $( , )? }
1426 ) => {
1427 $( #[$attr] )*
1428 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
1429 pub struct $name {
1430 test_compiler: Compiler,
1431 target: TargetSelection,
1432 }
1433
1434 impl Step for $name {
1435 type Output = ();
1436 const DEFAULT: bool = $default;
1437 const IS_HOST: bool = (const {
1438 #[allow(unused_assignments, unused_mut)]
1439 let mut value = false;
1440 $( value = $IS_HOST; )?
1441 value
1442 });
1443
1444 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1445 run.suite_path($path)
1446 }
1447
1448 fn make_run(run: RunConfig<'_>) {
1449 let test_compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1450
1451 run.builder.ensure($name { test_compiler, target: run.target });
1452 }
1453
1454 fn run(self, builder: &Builder<'_>) {
1455 builder.ensure(Compiletest {
1456 test_compiler: self.test_compiler,
1457 target: self.target,
1458 mode: $mode,
1459 suite: $suite,
1460 path: $path,
1461 compare_mode: (const {
1462 #[allow(unused_assignments, unused_mut)]
1463 let mut value = None;
1464 $( value = $compare_mode; )?
1465 value
1466 }),
1467 })
1468 }
1469 }
1470 };
1471}
1472
1473test!(Ui { path: "tests/ui", mode: "ui", suite: "ui", default: true });
1474
1475test!(Crashes { path: "tests/crashes", mode: "crashes", suite: "crashes", default: true });
1476
1477test!(CodegenLlvm {
1478 path: "tests/codegen-llvm",
1479 mode: "codegen",
1480 suite: "codegen-llvm",
1481 default: true
1482});
1483
1484test!(CodegenUnits {
1485 path: "tests/codegen-units",
1486 mode: "codegen-units",
1487 suite: "codegen-units",
1488 default: true,
1489});
1490
1491test!(Incremental {
1492 path: "tests/incremental",
1493 mode: "incremental",
1494 suite: "incremental",
1495 default: true,
1496});
1497
1498test!(Debuginfo {
1499 path: "tests/debuginfo",
1500 mode: "debuginfo",
1501 suite: "debuginfo",
1502 default: true,
1503 compare_mode: Some("split-dwarf"),
1504});
1505
1506test!(UiFullDeps {
1507 path: "tests/ui-fulldeps",
1508 mode: "ui",
1509 suite: "ui-fulldeps",
1510 default: true,
1511 IS_HOST: true,
1512});
1513
1514test!(Rustdoc {
1515 path: "tests/rustdoc",
1516 mode: "rustdoc",
1517 suite: "rustdoc",
1518 default: true,
1519 IS_HOST: true,
1520});
1521test!(RustdocUi {
1522 path: "tests/rustdoc-ui",
1523 mode: "ui",
1524 suite: "rustdoc-ui",
1525 default: true,
1526 IS_HOST: true,
1527});
1528
1529test!(RustdocJson {
1530 path: "tests/rustdoc-json",
1531 mode: "rustdoc-json",
1532 suite: "rustdoc-json",
1533 default: true,
1534 IS_HOST: true,
1535});
1536
1537test!(Pretty {
1538 path: "tests/pretty",
1539 mode: "pretty",
1540 suite: "pretty",
1541 default: true,
1542 IS_HOST: true,
1543});
1544
1545test!(RunMake { path: "tests/run-make", mode: "run-make", suite: "run-make", default: true });
1546test!(RunMakeCargo {
1547 path: "tests/run-make-cargo",
1548 mode: "run-make",
1549 suite: "run-make-cargo",
1550 default: true
1551});
1552
1553test!(AssemblyLlvm {
1554 path: "tests/assembly-llvm",
1555 mode: "assembly",
1556 suite: "assembly-llvm",
1557 default: true
1558});
1559
1560#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
1563pub struct Coverage {
1564 pub compiler: Compiler,
1565 pub target: TargetSelection,
1566 pub mode: &'static str,
1567}
1568
1569impl Coverage {
1570 const PATH: &'static str = "tests/coverage";
1571 const SUITE: &'static str = "coverage";
1572 const ALL_MODES: &[&str] = &["coverage-map", "coverage-run"];
1573}
1574
1575impl Step for Coverage {
1576 type Output = ();
1577 const DEFAULT: bool = true;
1578 const IS_HOST: bool = false;
1580
1581 fn should_run(mut run: ShouldRun<'_>) -> ShouldRun<'_> {
1582 run = run.suite_path(Self::PATH);
1588 for mode in Self::ALL_MODES {
1589 run = run.alias(mode);
1590 }
1591 run
1592 }
1593
1594 fn make_run(run: RunConfig<'_>) {
1595 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1596 let target = run.target;
1597
1598 let mut modes = vec![];
1602
1603 for path in &run.paths {
1606 match path {
1607 PathSet::Set(_) => {
1608 for mode in Self::ALL_MODES {
1609 if path.assert_single_path().path == Path::new(mode) {
1610 modes.push(mode);
1611 break;
1612 }
1613 }
1614 }
1615 PathSet::Suite(_) => {
1616 modes.extend(Self::ALL_MODES);
1617 break;
1618 }
1619 }
1620 }
1621
1622 modes.retain(|mode| !run.builder.config.skip.iter().any(|skip| skip == Path::new(mode)));
1625
1626 for mode in modes {
1634 run.builder.ensure(Coverage { compiler, target, mode });
1635 }
1636 }
1637
1638 fn run(self, builder: &Builder<'_>) {
1639 let Self { compiler, target, mode } = self;
1640 builder.ensure(Compiletest {
1643 test_compiler: compiler,
1644 target,
1645 mode,
1646 suite: Self::SUITE,
1647 path: Self::PATH,
1648 compare_mode: None,
1649 });
1650 }
1651}
1652
1653test!(CoverageRunRustdoc {
1654 path: "tests/coverage-run-rustdoc",
1655 mode: "coverage-run",
1656 suite: "coverage-run-rustdoc",
1657 default: true,
1658 IS_HOST: true,
1659});
1660
1661#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1663pub struct MirOpt {
1664 pub compiler: Compiler,
1665 pub target: TargetSelection,
1666}
1667
1668impl Step for MirOpt {
1669 type Output = ();
1670 const DEFAULT: bool = true;
1671
1672 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1673 run.suite_path("tests/mir-opt")
1674 }
1675
1676 fn make_run(run: RunConfig<'_>) {
1677 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1678 run.builder.ensure(MirOpt { compiler, target: run.target });
1679 }
1680
1681 fn run(self, builder: &Builder<'_>) {
1682 let run = |target| {
1683 builder.ensure(Compiletest {
1684 test_compiler: self.compiler,
1685 target,
1686 mode: "mir-opt",
1687 suite: "mir-opt",
1688 path: "tests/mir-opt",
1689 compare_mode: None,
1690 })
1691 };
1692
1693 run(self.target);
1694
1695 if builder.config.cmd.bless() {
1698 for target in ["aarch64-unknown-linux-gnu", "i686-pc-windows-msvc"] {
1704 run(TargetSelection::from_user(target));
1705 }
1706
1707 for target in ["x86_64-apple-darwin", "i686-unknown-linux-musl"] {
1708 let target = TargetSelection::from_user(target);
1709 let panic_abort_target = builder.ensure(MirOptPanicAbortSyntheticTarget {
1710 compiler: self.compiler,
1711 base: target,
1712 });
1713 run(panic_abort_target);
1714 }
1715 }
1716 }
1717}
1718
1719#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1725struct Compiletest {
1726 test_compiler: Compiler,
1728 target: TargetSelection,
1729 mode: &'static str,
1730 suite: &'static str,
1731 path: &'static str,
1732 compare_mode: Option<&'static str>,
1733}
1734
1735impl Step for Compiletest {
1736 type Output = ();
1737
1738 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1739 run.never()
1740 }
1741
1742 fn run(self, builder: &Builder<'_>) {
1743 if builder.doc_tests == DocTests::Only {
1744 return;
1745 }
1746
1747 if builder.top_stage == 0 && !builder.config.compiletest_allow_stage0 {
1748 eprintln!("\
1749ERROR: `--stage 0` runs compiletest on the stage0 (precompiled) compiler, not your local changes, and will almost always cause tests to fail
1750HELP: to test the compiler or standard library, omit the stage or explicitly use `--stage 1` instead
1751NOTE: if you're sure you want to do this, please open an issue as to why. In the meantime, you can override this with `--set build.compiletest-allow-stage0=true`."
1752 );
1753 crate::exit!(1);
1754 }
1755
1756 let mut test_compiler = self.test_compiler;
1757 let target = self.target;
1758 let mode = self.mode;
1759 let suite = self.suite;
1760
1761 let suite_path = self.path;
1763
1764 if !builder.config.codegen_tests && mode == "codegen" {
1766 return;
1767 }
1768
1769 let query_compiler;
1776 let (stage, stage_id) = if suite == "ui-fulldeps" && test_compiler.stage == 1 {
1777 query_compiler = Some(test_compiler);
1780 let build = builder.build.host_target;
1784 test_compiler = builder.compiler(test_compiler.stage - 1, build);
1785 let test_stage = test_compiler.stage + 1;
1786 (test_stage, format!("stage{test_stage}-{build}"))
1787 } else {
1788 query_compiler = None;
1789 let stage = test_compiler.stage;
1790 (stage, format!("stage{stage}-{target}"))
1791 };
1792
1793 if suite.ends_with("fulldeps") {
1794 builder.ensure(compile::Rustc::new(test_compiler, target));
1795 }
1796
1797 if suite == "debuginfo" {
1798 builder.ensure(dist::DebuggerScripts {
1799 sysroot: builder.sysroot(test_compiler).to_path_buf(),
1800 target,
1801 });
1802 }
1803 if mode == "run-make" {
1804 builder.tool_exe(Tool::RunMakeSupport);
1805 }
1806
1807 if suite == "mir-opt" {
1809 builder.ensure(
1810 compile::Std::new(test_compiler, test_compiler.host).is_for_mir_opt_tests(true),
1811 );
1812 } else {
1813 builder.std(test_compiler, test_compiler.host);
1814 }
1815
1816 let mut cmd = builder.tool_cmd(Tool::Compiletest);
1817
1818 if suite == "mir-opt" {
1819 builder.ensure(compile::Std::new(test_compiler, target).is_for_mir_opt_tests(true));
1820 } else {
1821 builder.std(test_compiler, target);
1822 }
1823
1824 builder.ensure(RemoteCopyLibs { build_compiler: test_compiler, target });
1825
1826 cmd.arg("--stage").arg(stage.to_string());
1830 cmd.arg("--stage-id").arg(stage_id);
1831
1832 cmd.arg("--compile-lib-path").arg(builder.rustc_libdir(test_compiler));
1833 cmd.arg("--run-lib-path").arg(builder.sysroot_target_libdir(test_compiler, target));
1834 cmd.arg("--rustc-path").arg(builder.rustc(test_compiler));
1835 if let Some(query_compiler) = query_compiler {
1836 cmd.arg("--query-rustc-path").arg(builder.rustc(query_compiler));
1837 }
1838
1839 cmd.arg("--minicore-path")
1842 .arg(builder.src.join("tests").join("auxiliary").join("minicore.rs"));
1843
1844 let is_rustdoc = suite == "rustdoc-ui" || suite == "rustdoc-js";
1845
1846 if mode == "run-make" {
1861 let stage0_rustc_path = builder.compiler(0, test_compiler.host);
1864 cmd.arg("--stage0-rustc-path").arg(builder.rustc(stage0_rustc_path));
1865
1866 if suite == "run-make-cargo" {
1867 let cargo_path = if test_compiler.stage == 0 {
1868 builder.initial_cargo.clone()
1870 } else {
1871 builder
1872 .ensure(tool::Cargo::from_build_compiler(
1873 builder.compiler(test_compiler.stage - 1, test_compiler.host),
1874 test_compiler.host,
1875 ))
1876 .tool_path
1877 };
1878
1879 cmd.arg("--cargo-path").arg(cargo_path);
1880 }
1881 }
1882
1883 if mode == "rustdoc"
1885 || mode == "run-make"
1886 || (mode == "ui" && is_rustdoc)
1887 || mode == "rustdoc-js"
1888 || mode == "rustdoc-json"
1889 || suite == "coverage-run-rustdoc"
1890 {
1891 cmd.arg("--rustdoc-path").arg(builder.rustdoc_for_compiler(test_compiler));
1892 }
1893
1894 if mode == "rustdoc-json" {
1895 let json_compiler = builder.compiler(0, builder.host_target);
1897 cmd.arg("--jsondocck-path")
1898 .arg(builder.ensure(tool::JsonDocCk { compiler: json_compiler, target }).tool_path);
1899 cmd.arg("--jsondoclint-path").arg(
1900 builder.ensure(tool::JsonDocLint { compiler: json_compiler, target }).tool_path,
1901 );
1902 }
1903
1904 if matches!(mode, "coverage-map" | "coverage-run") {
1905 let coverage_dump = builder.tool_exe(Tool::CoverageDump);
1906 cmd.arg("--coverage-dump-path").arg(coverage_dump);
1907 }
1908
1909 cmd.arg("--src-root").arg(&builder.src);
1910 cmd.arg("--src-test-suite-root").arg(builder.src.join("tests").join(suite));
1911
1912 cmd.arg("--build-root").arg(&builder.out);
1916 cmd.arg("--build-test-suite-root").arg(testdir(builder, test_compiler.host).join(suite));
1917
1918 let sysroot = if builder.top_stage == 0 {
1923 builder.initial_sysroot.clone()
1924 } else {
1925 builder.sysroot(test_compiler)
1926 };
1927
1928 cmd.arg("--sysroot-base").arg(sysroot);
1929
1930 cmd.arg("--suite").arg(suite);
1931 cmd.arg("--mode").arg(mode);
1932 cmd.arg("--target").arg(target.rustc_target_arg());
1933 cmd.arg("--host").arg(&*test_compiler.host.triple);
1934 cmd.arg("--llvm-filecheck").arg(builder.llvm_filecheck(builder.config.host_target));
1935
1936 if let Some(codegen_backend) = builder.config.cmd.test_codegen_backend() {
1937 if !builder
1938 .config
1939 .enabled_codegen_backends(test_compiler.host)
1940 .contains(codegen_backend)
1941 {
1942 eprintln!(
1943 "\
1944ERROR: No configured backend named `{name}`
1945HELP: You can add it into `bootstrap.toml` in `rust.codegen-backends = [{name:?}]`",
1946 name = codegen_backend.name(),
1947 );
1948 crate::exit!(1);
1949 }
1950
1951 if let CodegenBackendKind::Gcc = codegen_backend
1952 && builder.config.rustc_debug_assertions
1953 {
1954 eprintln!(
1955 r#"WARNING: Running tests with the GCC codegen backend while rustc debug assertions are enabled. This might lead to test failures.
1956Please disable assertions with `rust.debug-assertions = false`.
1957 "#
1958 );
1959 }
1960
1961 cmd.arg("--override-codegen-backend").arg(codegen_backend.name());
1964 cmd.arg("--default-codegen-backend").arg(codegen_backend.name());
1967 } else {
1968 cmd.arg("--default-codegen-backend")
1971 .arg(builder.config.default_codegen_backend(test_compiler.host).name());
1972 }
1973 if builder.config.cmd.bypass_ignore_backends() {
1974 cmd.arg("--bypass-ignore-backends");
1975 }
1976
1977 if builder.build.config.llvm_enzyme {
1978 cmd.arg("--has-enzyme");
1979 }
1980
1981 if builder.config.cmd.bless() {
1982 cmd.arg("--bless");
1983 }
1984
1985 if builder.config.cmd.force_rerun() {
1986 cmd.arg("--force-rerun");
1987 }
1988
1989 if builder.config.cmd.no_capture() {
1990 cmd.arg("--no-capture");
1991 }
1992
1993 let compare_mode =
1994 builder.config.cmd.compare_mode().or_else(|| {
1995 if builder.config.test_compare_mode { self.compare_mode } else { None }
1996 });
1997
1998 if let Some(ref pass) = builder.config.cmd.pass() {
1999 cmd.arg("--pass");
2000 cmd.arg(pass);
2001 }
2002
2003 if let Some(ref run) = builder.config.cmd.run() {
2004 cmd.arg("--run");
2005 cmd.arg(run);
2006 }
2007
2008 if let Some(ref nodejs) = builder.config.nodejs {
2009 cmd.arg("--nodejs").arg(nodejs);
2010 } else if mode == "rustdoc-js" {
2011 panic!("need nodejs to run rustdoc-js suite");
2012 }
2013 if builder.config.rust_optimize_tests {
2014 cmd.arg("--optimize-tests");
2015 }
2016 if builder.config.rust_randomize_layout {
2017 cmd.arg("--rust-randomized-layout");
2018 }
2019 if builder.config.cmd.only_modified() {
2020 cmd.arg("--only-modified");
2021 }
2022 if let Some(compiletest_diff_tool) = &builder.config.compiletest_diff_tool {
2023 cmd.arg("--compiletest-diff-tool").arg(compiletest_diff_tool);
2024 }
2025
2026 let mut flags = if is_rustdoc { Vec::new() } else { vec!["-Crpath".to_string()] };
2027 flags.push(format!(
2028 "-Cdebuginfo={}",
2029 if mode == "codegen" {
2030 if builder.config.rust_debuginfo_level_tests
2033 != crate::core::config::DebuginfoLevel::None
2034 {
2035 println!(
2036 "NOTE: ignoring `rust.debuginfo-level-tests={}` for codegen tests",
2037 builder.config.rust_debuginfo_level_tests
2038 );
2039 }
2040 crate::core::config::DebuginfoLevel::None
2041 } else {
2042 builder.config.rust_debuginfo_level_tests
2043 }
2044 ));
2045 flags.extend(builder.config.cmd.compiletest_rustc_args().iter().map(|s| s.to_string()));
2046
2047 if suite != "mir-opt" {
2048 if let Some(linker) = builder.linker(target) {
2049 cmd.arg("--target-linker").arg(linker);
2050 }
2051 if let Some(linker) = builder.linker(test_compiler.host) {
2052 cmd.arg("--host-linker").arg(linker);
2053 }
2054 }
2055
2056 if suite == "ui-fulldeps" && target.ends_with("darwin") {
2058 flags.push("-Alinker_messages".into());
2059 }
2060
2061 let mut hostflags = flags.clone();
2062 hostflags.extend(linker_flags(builder, test_compiler.host, LldThreads::No));
2063
2064 let mut targetflags = flags;
2065
2066 if suite == "ui" || suite == "incremental" {
2068 builder.ensure(TestHelpers { target: test_compiler.host });
2069 builder.ensure(TestHelpers { target });
2070 hostflags.push(format!(
2071 "-Lnative={}",
2072 builder.test_helpers_out(test_compiler.host).display()
2073 ));
2074 targetflags.push(format!("-Lnative={}", builder.test_helpers_out(target).display()));
2075 }
2076
2077 for flag in hostflags {
2078 cmd.arg("--host-rustcflags").arg(flag);
2079 }
2080 for flag in targetflags {
2081 cmd.arg("--target-rustcflags").arg(flag);
2082 }
2083
2084 cmd.arg("--python").arg(
2085 builder.config.python.as_ref().expect("python is required for running rustdoc tests"),
2086 );
2087
2088 if let Some(debuggers::Android { adb_path, adb_test_dir, android_cross_path }) =
2093 debuggers::discover_android(builder, target)
2094 {
2095 cmd.arg("--adb-path").arg(adb_path);
2096 cmd.arg("--adb-test-dir").arg(adb_test_dir);
2097 cmd.arg("--android-cross-path").arg(android_cross_path);
2098 }
2099
2100 if mode == "debuginfo" {
2101 if let Some(debuggers::Gdb { gdb }) = debuggers::discover_gdb(builder) {
2102 cmd.arg("--gdb").arg(gdb);
2103 }
2104
2105 if let Some(debuggers::Lldb { lldb_exe, lldb_version }) =
2106 debuggers::discover_lldb(builder)
2107 {
2108 cmd.arg("--lldb").arg(lldb_exe);
2109 cmd.arg("--lldb-version").arg(lldb_version);
2110 }
2111 }
2112
2113 if helpers::forcing_clang_based_tests() {
2114 let clang_exe = builder.llvm_out(target).join("bin").join("clang");
2115 cmd.arg("--run-clang-based-tests-with").arg(clang_exe);
2116 }
2117
2118 for exclude in &builder.config.skip {
2119 cmd.arg("--skip");
2120 cmd.arg(exclude);
2121 }
2122
2123 let mut paths = match &builder.config.cmd {
2125 Subcommand::Test { .. } => &builder.config.paths[..],
2126 _ => &[],
2127 };
2128
2129 let mut paths_v;
2132 if mode == "rustdoc-js" {
2133 paths_v = paths.to_vec();
2134 for p in &mut paths_v {
2135 if let Some(ext) = p.extension()
2136 && ext == "js"
2137 {
2138 p.set_extension("rs");
2139 }
2140 }
2141 paths = &paths_v;
2142 }
2143 let mut test_args: Vec<&str> = paths
2145 .iter()
2146 .filter_map(|p| helpers::is_valid_test_suite_arg(p, suite_path, builder))
2147 .collect();
2148
2149 test_args.append(&mut builder.config.test_args());
2150
2151 if cfg!(windows) {
2154 let test_args_win: Vec<String> =
2155 test_args.iter().map(|s| s.replace('/', "\\")).collect();
2156 cmd.args(&test_args_win);
2157 } else {
2158 cmd.args(&test_args);
2159 }
2160
2161 if builder.is_verbose() {
2162 cmd.arg("--verbose");
2163 }
2164
2165 if builder.config.rustc_debug_assertions {
2166 cmd.arg("--with-rustc-debug-assertions");
2167 }
2168
2169 if builder.config.std_debug_assertions {
2170 cmd.arg("--with-std-debug-assertions");
2171 }
2172
2173 let mut llvm_components_passed = false;
2174 let mut copts_passed = false;
2175 if builder.config.llvm_enabled(test_compiler.host) {
2176 let llvm::LlvmResult { host_llvm_config, .. } =
2177 builder.ensure(llvm::Llvm { target: builder.config.host_target });
2178 if !builder.config.dry_run() {
2179 let llvm_version = get_llvm_version(builder, &host_llvm_config);
2180 let llvm_components = command(&host_llvm_config)
2181 .cached()
2182 .arg("--components")
2183 .run_capture_stdout(builder)
2184 .stdout();
2185 cmd.arg("--llvm-version")
2187 .arg(llvm_version.trim())
2188 .arg("--llvm-components")
2189 .arg(llvm_components.trim());
2190 llvm_components_passed = true;
2191 }
2192 if !builder.config.is_rust_llvm(target) {
2193 cmd.arg("--system-llvm");
2194 }
2195
2196 if !builder.config.dry_run() && suite.ends_with("fulldeps") {
2201 let llvm_libdir = command(&host_llvm_config)
2202 .cached()
2203 .arg("--libdir")
2204 .run_capture_stdout(builder)
2205 .stdout();
2206 let link_llvm = if target.is_msvc() {
2207 format!("-Clink-arg=-LIBPATH:{llvm_libdir}")
2208 } else {
2209 format!("-Clink-arg=-L{llvm_libdir}")
2210 };
2211 cmd.arg("--host-rustcflags").arg(link_llvm);
2212 }
2213
2214 if !builder.config.dry_run() && matches!(mode, "run-make" | "coverage-run") {
2215 let llvm_bin_path = host_llvm_config
2220 .parent()
2221 .expect("Expected llvm-config to be contained in directory");
2222 assert!(llvm_bin_path.is_dir());
2223 cmd.arg("--llvm-bin-dir").arg(llvm_bin_path);
2224 }
2225
2226 if !builder.config.dry_run() && mode == "run-make" {
2227 if builder.config.lld_enabled {
2229 let lld_install_root =
2230 builder.ensure(llvm::Lld { target: builder.config.host_target });
2231
2232 let lld_bin_path = lld_install_root.join("bin");
2233
2234 let old_path = env::var_os("PATH").unwrap_or_default();
2235 let new_path = env::join_paths(
2236 std::iter::once(lld_bin_path).chain(env::split_paths(&old_path)),
2237 )
2238 .expect("Could not add LLD bin path to PATH");
2239 cmd.env("PATH", new_path);
2240 }
2241 }
2242 }
2243
2244 if !builder.config.dry_run() && mode == "run-make" {
2247 let mut cflags = builder.cc_handled_clags(target, CLang::C);
2248 cflags.extend(builder.cc_unhandled_cflags(target, GitRepo::Rustc, CLang::C));
2249 let mut cxxflags = builder.cc_handled_clags(target, CLang::Cxx);
2250 cxxflags.extend(builder.cc_unhandled_cflags(target, GitRepo::Rustc, CLang::Cxx));
2251 cmd.arg("--cc")
2252 .arg(builder.cc(target))
2253 .arg("--cxx")
2254 .arg(builder.cxx(target).unwrap())
2255 .arg("--cflags")
2256 .arg(cflags.join(" "))
2257 .arg("--cxxflags")
2258 .arg(cxxflags.join(" "));
2259 copts_passed = true;
2260 if let Some(ar) = builder.ar(target) {
2261 cmd.arg("--ar").arg(ar);
2262 }
2263 }
2264
2265 if !llvm_components_passed {
2266 cmd.arg("--llvm-components").arg("");
2267 }
2268 if !copts_passed {
2269 cmd.arg("--cc")
2270 .arg("")
2271 .arg("--cxx")
2272 .arg("")
2273 .arg("--cflags")
2274 .arg("")
2275 .arg("--cxxflags")
2276 .arg("");
2277 }
2278
2279 if builder.remote_tested(target) {
2280 cmd.arg("--remote-test-client").arg(builder.tool_exe(Tool::RemoteTestClient));
2281 } else if let Some(tool) = builder.runner(target) {
2282 cmd.arg("--runner").arg(tool);
2283 }
2284
2285 if suite != "mir-opt" {
2286 if !builder.config.dry_run() && target.is_msvc() {
2292 for (k, v) in builder.cc[&target].env() {
2293 if k != "PATH" {
2294 cmd.env(k, v);
2295 }
2296 }
2297 }
2298 }
2299
2300 if !builder.config.dry_run()
2302 && target.contains("msvc")
2303 && builder.config.sanitizers_enabled(target)
2304 {
2305 cmd.env("ASAN_WIN_CONTINUE_ON_INTERCEPTION_FAILURE", "1");
2308 let asan_runtime_path = builder.cc[&target].path().parent().unwrap().to_path_buf();
2310 let old_path = cmd
2311 .get_envs()
2312 .find_map(|(k, v)| (k == "PATH").then_some(v))
2313 .flatten()
2314 .map_or_else(|| env::var_os("PATH").unwrap_or_default(), |v| v.to_owned());
2315 let new_path = env::join_paths(
2316 env::split_paths(&old_path).chain(std::iter::once(asan_runtime_path)),
2317 )
2318 .expect("Could not add ASAN runtime path to PATH");
2319 cmd.env("PATH", new_path);
2320 }
2321
2322 cmd.env_remove("CARGO");
2325
2326 cmd.env("RUSTC_BOOTSTRAP", "1");
2327 cmd.env("RUSTC_FORCE_RUSTC_VERSION", "compiletest");
2330 cmd.env("DOC_RUST_LANG_ORG_CHANNEL", builder.doc_rust_lang_org_channel());
2331 builder.add_rust_test_threads(&mut cmd);
2332
2333 if builder.config.sanitizers_enabled(target) {
2334 cmd.env("RUSTC_SANITIZER_SUPPORT", "1");
2335 }
2336
2337 if builder.config.profiler_enabled(target) {
2338 cmd.arg("--profiler-runtime");
2339 }
2340
2341 cmd.env("RUST_TEST_TMPDIR", builder.tempdir());
2342
2343 if builder.config.cmd.rustfix_coverage() {
2344 cmd.arg("--rustfix-coverage");
2345 }
2346
2347 cmd.arg("--channel").arg(&builder.config.channel);
2348
2349 if !builder.config.omit_git_hash {
2350 cmd.arg("--git-hash");
2351 }
2352
2353 let git_config = builder.config.git_config();
2354 cmd.arg("--nightly-branch").arg(git_config.nightly_branch);
2355 cmd.arg("--git-merge-commit-email").arg(git_config.git_merge_commit_email);
2356 cmd.force_coloring_in_ci();
2357
2358 #[cfg(feature = "build-metrics")]
2359 builder.metrics.begin_test_suite(
2360 build_helper::metrics::TestSuiteMetadata::Compiletest {
2361 suite: suite.into(),
2362 mode: mode.into(),
2363 compare_mode: None,
2364 target: self.target.triple.to_string(),
2365 host: self.test_compiler.host.triple.to_string(),
2366 stage: self.test_compiler.stage,
2367 },
2368 builder,
2369 );
2370
2371 let _group = builder.msg_test(
2372 format!("with compiletest suite={suite} mode={mode}"),
2373 target,
2374 test_compiler.stage,
2375 );
2376 try_run_tests(builder, &mut cmd, false);
2377
2378 if let Some(compare_mode) = compare_mode {
2379 cmd.arg("--compare-mode").arg(compare_mode);
2380
2381 #[cfg(feature = "build-metrics")]
2382 builder.metrics.begin_test_suite(
2383 build_helper::metrics::TestSuiteMetadata::Compiletest {
2384 suite: suite.into(),
2385 mode: mode.into(),
2386 compare_mode: Some(compare_mode.into()),
2387 target: self.target.triple.to_string(),
2388 host: self.test_compiler.host.triple.to_string(),
2389 stage: self.test_compiler.stage,
2390 },
2391 builder,
2392 );
2393
2394 builder.info(&format!(
2395 "Check compiletest suite={} mode={} compare_mode={} ({} -> {})",
2396 suite, mode, compare_mode, &test_compiler.host, target
2397 ));
2398 let _time = helpers::timeit(builder);
2399 try_run_tests(builder, &mut cmd, false);
2400 }
2401 }
2402
2403 fn metadata(&self) -> Option<StepMetadata> {
2404 Some(
2405 StepMetadata::test(&format!("compiletest-{}", self.suite), self.target)
2406 .stage(self.test_compiler.stage),
2407 )
2408 }
2409}
2410
2411#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2413struct BookTest {
2414 test_compiler: Compiler,
2415 path: PathBuf,
2416 name: &'static str,
2417 is_ext_doc: bool,
2418 dependencies: Vec<&'static str>,
2419}
2420
2421impl Step for BookTest {
2422 type Output = ();
2423 const IS_HOST: bool = true;
2424
2425 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2426 run.never()
2427 }
2428
2429 fn run(self, builder: &Builder<'_>) {
2430 if self.is_ext_doc {
2440 self.run_ext_doc(builder);
2441 } else {
2442 self.run_local_doc(builder);
2443 }
2444 }
2445}
2446
2447impl BookTest {
2448 fn run_ext_doc(self, builder: &Builder<'_>) {
2451 let test_compiler = self.test_compiler;
2452
2453 builder.std(test_compiler, test_compiler.host);
2454
2455 let mut rustdoc_path = builder.rustdoc_for_compiler(test_compiler);
2458 rustdoc_path.pop();
2459 let old_path = env::var_os("PATH").unwrap_or_default();
2460 let new_path = env::join_paths(iter::once(rustdoc_path).chain(env::split_paths(&old_path)))
2461 .expect("could not add rustdoc to PATH");
2462
2463 let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook);
2464 let path = builder.src.join(&self.path);
2465 rustbook_cmd.env("RUSTC_BOOTSTRAP", "1");
2467 rustbook_cmd.env("PATH", new_path).arg("test").arg(path);
2468
2469 let libs = if !self.dependencies.is_empty() {
2474 let mut lib_paths = vec![];
2475 for dep in self.dependencies {
2476 let mode = Mode::ToolRustcPrivate;
2477 let target = builder.config.host_target;
2478 let cargo = tool::prepare_tool_cargo(
2479 builder,
2480 test_compiler,
2481 mode,
2482 target,
2483 Kind::Build,
2484 dep,
2485 SourceType::Submodule,
2486 &[],
2487 );
2488
2489 let stamp = BuildStamp::new(&builder.cargo_out(test_compiler, mode, target))
2490 .with_prefix(PathBuf::from(dep).file_name().and_then(|v| v.to_str()).unwrap());
2491
2492 let output_paths = run_cargo(builder, cargo, vec![], &stamp, vec![], false, false);
2493 let directories = output_paths
2494 .into_iter()
2495 .filter_map(|p| p.parent().map(ToOwned::to_owned))
2496 .fold(HashSet::new(), |mut set, dir| {
2497 set.insert(dir);
2498 set
2499 });
2500
2501 lib_paths.extend(directories);
2502 }
2503 lib_paths
2504 } else {
2505 vec![]
2506 };
2507
2508 if !libs.is_empty() {
2509 let paths = libs
2510 .into_iter()
2511 .map(|path| path.into_os_string())
2512 .collect::<Vec<OsString>>()
2513 .join(OsStr::new(","));
2514 rustbook_cmd.args([OsString::from("--library-path"), paths]);
2515 }
2516
2517 builder.add_rust_test_threads(&mut rustbook_cmd);
2518 let _guard = builder.msg_test(
2519 format_args!("mdbook {}", self.path.display()),
2520 test_compiler.host,
2521 test_compiler.stage,
2522 );
2523 let _time = helpers::timeit(builder);
2524 let toolstate = if rustbook_cmd.delay_failure().run(builder) {
2525 ToolState::TestPass
2526 } else {
2527 ToolState::TestFail
2528 };
2529 builder.save_toolstate(self.name, toolstate);
2530 }
2531
2532 fn run_local_doc(self, builder: &Builder<'_>) {
2534 let test_compiler = self.test_compiler;
2535 let host = self.test_compiler.host;
2536
2537 builder.std(test_compiler, host);
2538
2539 let _guard = builder.msg_test(
2540 format!("book {}", self.name),
2541 test_compiler.host,
2542 test_compiler.stage,
2543 );
2544
2545 let mut stack = vec![builder.src.join(self.path)];
2548 let _time = helpers::timeit(builder);
2549 let mut files = Vec::new();
2550 while let Some(p) = stack.pop() {
2551 if p.is_dir() {
2552 stack.extend(t!(p.read_dir()).map(|p| t!(p).path()));
2553 continue;
2554 }
2555
2556 if p.extension().and_then(|s| s.to_str()) != Some("md") {
2557 continue;
2558 }
2559
2560 files.push(p);
2561 }
2562
2563 files.sort();
2564
2565 for file in files {
2566 markdown_test(builder, test_compiler, &file);
2567 }
2568 }
2569}
2570
2571macro_rules! test_book {
2572 ($(
2573 $name:ident, $path:expr, $book_name:expr,
2574 default=$default:expr
2575 $(,submodules = $submodules:expr)?
2576 $(,dependencies=$dependencies:expr)?
2577 ;
2578 )+) => {
2579 $(
2580 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
2581 pub struct $name {
2582 test_compiler: Compiler,
2583 }
2584
2585 impl Step for $name {
2586 type Output = ();
2587 const DEFAULT: bool = $default;
2588 const IS_HOST: bool = true;
2589
2590 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2591 run.path($path)
2592 }
2593
2594 fn make_run(run: RunConfig<'_>) {
2595 run.builder.ensure($name {
2596 test_compiler: run.builder.compiler(run.builder.top_stage, run.target),
2597 });
2598 }
2599
2600 fn run(self, builder: &Builder<'_>) {
2601 $(
2602 for submodule in $submodules {
2603 builder.require_submodule(submodule, None);
2604 }
2605 )*
2606
2607 let dependencies = vec![];
2608 $(
2609 let mut dependencies = dependencies;
2610 for dep in $dependencies {
2611 dependencies.push(dep);
2612 }
2613 )?
2614
2615 builder.ensure(BookTest {
2616 test_compiler: self.test_compiler,
2617 path: PathBuf::from($path),
2618 name: $book_name,
2619 is_ext_doc: !$default,
2620 dependencies,
2621 });
2622 }
2623 }
2624 )+
2625 }
2626}
2627
2628test_book!(
2629 Nomicon, "src/doc/nomicon", "nomicon", default=false, submodules=["src/doc/nomicon"];
2630 Reference, "src/doc/reference", "reference", default=false, submodules=["src/doc/reference"];
2631 RustdocBook, "src/doc/rustdoc", "rustdoc", default=true;
2632 RustcBook, "src/doc/rustc", "rustc", default=true;
2633 RustByExample, "src/doc/rust-by-example", "rust-by-example", default=false, submodules=["src/doc/rust-by-example"];
2634 EmbeddedBook, "src/doc/embedded-book", "embedded-book", default=false, submodules=["src/doc/embedded-book"];
2635 TheBook, "src/doc/book", "book", default=false, submodules=["src/doc/book"], dependencies=["src/doc/book/packages/trpl"];
2636 UnstableBook, "src/doc/unstable-book", "unstable-book", default=true;
2637 EditionGuide, "src/doc/edition-guide", "edition-guide", default=false, submodules=["src/doc/edition-guide"];
2638);
2639
2640#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2641pub struct ErrorIndex {
2642 compilers: RustcPrivateCompilers,
2643}
2644
2645impl Step for ErrorIndex {
2646 type Output = ();
2647 const DEFAULT: bool = true;
2648 const IS_HOST: bool = true;
2649
2650 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2651 run.path("src/tools/error_index_generator").alias("error-index")
2654 }
2655
2656 fn make_run(run: RunConfig<'_>) {
2657 let compilers = RustcPrivateCompilers::new(
2661 run.builder,
2662 run.builder.top_stage,
2663 run.builder.config.host_target,
2664 );
2665 run.builder.ensure(ErrorIndex { compilers });
2666 }
2667
2668 fn run(self, builder: &Builder<'_>) {
2675 let target_compiler = self.compilers.target_compiler();
2677
2678 let dir = testdir(builder, target_compiler.host);
2679 t!(fs::create_dir_all(&dir));
2680 let output = dir.join("error-index.md");
2681
2682 let mut tool = tool::ErrorIndex::command(builder, self.compilers);
2683 tool.arg("markdown").arg(&output);
2684
2685 let guard = builder.msg_test("error-index", target_compiler.host, target_compiler.stage);
2686 let _time = helpers::timeit(builder);
2687 tool.run_capture(builder);
2688 drop(guard);
2689 builder.std(target_compiler, target_compiler.host);
2692 markdown_test(builder, target_compiler, &output);
2693 }
2694}
2695
2696fn markdown_test(builder: &Builder<'_>, compiler: Compiler, markdown: &Path) -> bool {
2697 if let Ok(contents) = fs::read_to_string(markdown)
2698 && !contents.contains("```")
2699 {
2700 return true;
2701 }
2702
2703 builder.do_if_verbose(|| println!("doc tests for: {}", markdown.display()));
2704 let mut cmd = builder.rustdoc_cmd(compiler);
2705 builder.add_rust_test_threads(&mut cmd);
2706 cmd.arg("-Z");
2708 cmd.arg("unstable-options");
2709 cmd.arg("--test");
2710 cmd.arg(markdown);
2711 cmd.env("RUSTC_BOOTSTRAP", "1");
2712
2713 let test_args = builder.config.test_args().join(" ");
2714 cmd.arg("--test-args").arg(test_args);
2715
2716 cmd = cmd.delay_failure();
2717 if !builder.config.verbose_tests {
2718 cmd.run_capture(builder).is_success()
2719 } else {
2720 cmd.run(builder)
2721 }
2722}
2723
2724#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2729pub struct CrateLibrustc {
2730 build_compiler: Compiler,
2732 target: TargetSelection,
2733 crates: Vec<String>,
2734}
2735
2736impl Step for CrateLibrustc {
2737 type Output = ();
2738 const DEFAULT: bool = true;
2739 const IS_HOST: bool = true;
2740
2741 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2742 run.crate_or_deps("rustc-main").path("compiler")
2743 }
2744
2745 fn make_run(run: RunConfig<'_>) {
2746 let builder = run.builder;
2747 let host = run.build_triple();
2748 let build_compiler = builder.compiler(builder.top_stage - 1, host);
2749 let crates = run.make_run_crates(Alias::Compiler);
2750
2751 builder.ensure(CrateLibrustc { build_compiler, target: run.target, crates });
2752 }
2753
2754 fn run(self, builder: &Builder<'_>) {
2755 builder.std(self.build_compiler, self.target);
2756
2757 builder.ensure(Crate {
2759 build_compiler: self.build_compiler,
2760 target: self.target,
2761 mode: Mode::Rustc,
2762 crates: self.crates,
2763 });
2764 }
2765
2766 fn metadata(&self) -> Option<StepMetadata> {
2767 Some(StepMetadata::test("CrateLibrustc", self.target).built_by(self.build_compiler))
2768 }
2769}
2770
2771fn run_cargo_test<'a>(
2775 cargo: builder::Cargo,
2776 libtest_args: &[&str],
2777 crates: &[String],
2778 description: impl Into<Option<&'a str>>,
2779 target: TargetSelection,
2780 builder: &Builder<'_>,
2781) -> bool {
2782 let compiler = cargo.compiler();
2783 let mut cargo = prepare_cargo_test(cargo, libtest_args, crates, target, builder);
2784 let _time = helpers::timeit(builder);
2785 let _group =
2786 description.into().and_then(|what| builder.msg_test(what, target, compiler.stage + 1));
2787
2788 #[cfg(feature = "build-metrics")]
2789 builder.metrics.begin_test_suite(
2790 build_helper::metrics::TestSuiteMetadata::CargoPackage {
2791 crates: crates.iter().map(|c| c.to_string()).collect(),
2792 target: target.triple.to_string(),
2793 host: compiler.host.triple.to_string(),
2794 stage: compiler.stage,
2795 },
2796 builder,
2797 );
2798 add_flags_and_try_run_tests(builder, &mut cargo)
2799}
2800
2801fn prepare_cargo_test(
2803 cargo: builder::Cargo,
2804 libtest_args: &[&str],
2805 crates: &[String],
2806 target: TargetSelection,
2807 builder: &Builder<'_>,
2808) -> BootstrapCommand {
2809 let compiler = cargo.compiler();
2810 let mut cargo: BootstrapCommand = cargo.into();
2811
2812 if builder.config.cmd.bless() && !cargo.get_envs().any(|v| v.0 == "RUSTC_BLESS") {
2816 cargo.env("RUSTC_BLESS", "Gesundheit");
2817 }
2818
2819 if builder.kind == Kind::Test && !builder.fail_fast {
2823 cargo.arg("--no-fail-fast");
2824 }
2825
2826 if builder.config.json_output {
2827 cargo.arg("--message-format=json");
2828 }
2829
2830 match builder.doc_tests {
2831 DocTests::Only => {
2832 cargo.arg("--doc");
2833 }
2834 DocTests::No => {
2835 cargo.args(["--bins", "--examples", "--tests", "--benches"]);
2836 }
2837 DocTests::Yes => {}
2838 }
2839
2840 for krate in crates {
2841 cargo.arg("-p").arg(krate);
2842 }
2843
2844 cargo.arg("--").args(builder.config.test_args()).args(libtest_args);
2845 if !builder.config.verbose_tests {
2846 cargo.arg("--quiet");
2847 }
2848
2849 if builder.kind != Kind::Miri {
2858 let mut dylib_paths = builder.rustc_lib_paths(compiler);
2859 dylib_paths.push(builder.sysroot_target_libdir(compiler, target));
2860 helpers::add_dylib_path(dylib_paths, &mut cargo);
2861 }
2862
2863 if builder.remote_tested(target) {
2864 cargo.env(
2865 format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)),
2866 format!("{} run 0", builder.tool_exe(Tool::RemoteTestClient).display()),
2867 );
2868 } else if let Some(tool) = builder.runner(target) {
2869 cargo.env(format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)), tool);
2870 }
2871
2872 cargo
2873}
2874
2875#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2883pub struct Crate {
2884 build_compiler: Compiler,
2886 target: TargetSelection,
2887 mode: Mode,
2888 crates: Vec<String>,
2889}
2890
2891impl Step for Crate {
2892 type Output = ();
2893 const DEFAULT: bool = true;
2894
2895 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2896 run.crate_or_deps("sysroot").crate_or_deps("coretests").crate_or_deps("alloctests")
2897 }
2898
2899 fn make_run(run: RunConfig<'_>) {
2900 let builder = run.builder;
2901 let host = run.build_triple();
2902 let build_compiler = builder.compiler(builder.top_stage, host);
2903 let crates = run
2904 .paths
2905 .iter()
2906 .map(|p| builder.crate_paths[&p.assert_single_path().path].clone())
2907 .collect();
2908
2909 builder.ensure(Crate { build_compiler, target: run.target, mode: Mode::Std, crates });
2910 }
2911
2912 fn run(self, builder: &Builder<'_>) {
2921 let build_compiler = self.build_compiler;
2922 let target = self.target;
2923 let mode = self.mode;
2924
2925 builder.ensure(Std::new(build_compiler, build_compiler.host).force_recompile(true));
2928
2929 let mut cargo = if builder.kind == Kind::Miri {
2930 if builder.top_stage == 0 {
2931 eprintln!("ERROR: `x.py miri` requires stage 1 or higher");
2932 std::process::exit(1);
2933 }
2934
2935 let mut cargo = builder::Cargo::new(
2938 builder,
2939 build_compiler,
2940 mode,
2941 SourceType::InTree,
2942 target,
2943 Kind::MiriTest,
2944 );
2945 cargo.env("MIRI_REPLACE_LIBRS_IF_NOT_TEST", "1");
2957 cargo.rustflag("-Zforce-unstable-if-unmarked");
2961 cargo
2962 } else {
2963 if !builder.config.is_host_target(target) {
2965 builder.ensure(compile::Std::new(build_compiler, target).force_recompile(true));
2966 builder.ensure(RemoteCopyLibs { build_compiler, target });
2967 }
2968
2969 builder::Cargo::new(
2971 builder,
2972 build_compiler,
2973 mode,
2974 SourceType::InTree,
2975 target,
2976 builder.kind,
2977 )
2978 };
2979
2980 match mode {
2981 Mode::Std => {
2982 if builder.kind == Kind::Miri {
2983 cargo
2989 .arg("--manifest-path")
2990 .arg(builder.src.join("library/sysroot/Cargo.toml"));
2991 } else {
2992 compile::std_cargo(builder, target, &mut cargo, &[]);
2993 }
2994 }
2995 Mode::Rustc => {
2996 compile::rustc_cargo(builder, &mut cargo, target, &build_compiler, &self.crates);
2997 }
2998 _ => panic!("can only test libraries"),
2999 };
3000
3001 let mut crates = self.crates.clone();
3002 if crates.iter().any(|crate_| crate_ == "core") {
3007 crates.push("coretests".to_owned());
3008 }
3009 if crates.iter().any(|crate_| crate_ == "alloc") {
3010 crates.push("alloctests".to_owned());
3011 }
3012
3013 run_cargo_test(cargo, &[], &crates, &*crate_description(&self.crates), target, builder);
3014 }
3015}
3016
3017#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3020pub struct CrateRustdoc {
3021 host: TargetSelection,
3022}
3023
3024impl Step for CrateRustdoc {
3025 type Output = ();
3026 const DEFAULT: bool = true;
3027 const IS_HOST: bool = true;
3028
3029 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3030 run.paths(&["src/librustdoc", "src/tools/rustdoc"])
3031 }
3032
3033 fn make_run(run: RunConfig<'_>) {
3034 let builder = run.builder;
3035
3036 builder.ensure(CrateRustdoc { host: run.target });
3037 }
3038
3039 fn run(self, builder: &Builder<'_>) {
3040 let target = self.host;
3041
3042 let compiler = if builder.download_rustc() {
3043 builder.compiler(builder.top_stage, target)
3044 } else {
3045 builder.compiler_for(builder.top_stage, target, target)
3050 };
3051 builder.std(compiler, target);
3056 builder.ensure(compile::Rustc::new(compiler, target));
3057
3058 let mut cargo = tool::prepare_tool_cargo(
3059 builder,
3060 compiler,
3061 Mode::ToolRustcPrivate,
3062 target,
3063 builder.kind,
3064 "src/tools/rustdoc",
3065 SourceType::InTree,
3066 &[],
3067 );
3068 if self.host.contains("musl") {
3069 cargo.arg("'-Ctarget-feature=-crt-static'");
3070 }
3071
3072 let libdir = if builder.download_rustc() {
3099 builder.rustc_libdir(compiler)
3100 } else {
3101 builder.sysroot_target_libdir(compiler, target).to_path_buf()
3102 };
3103 let mut dylib_path = dylib_path();
3104 dylib_path.insert(0, PathBuf::from(&*libdir));
3105 cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());
3106
3107 run_cargo_test(cargo, &[], &["rustdoc:0.0.0".to_string()], "rustdoc", target, builder);
3108 }
3109}
3110
3111#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3112pub struct CrateRustdocJsonTypes {
3113 build_compiler: Compiler,
3114 target: TargetSelection,
3115}
3116
3117impl Step for CrateRustdocJsonTypes {
3118 type Output = ();
3119 const DEFAULT: bool = true;
3120 const IS_HOST: bool = true;
3121
3122 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3123 run.path("src/rustdoc-json-types")
3124 }
3125
3126 fn make_run(run: RunConfig<'_>) {
3127 let builder = run.builder;
3128
3129 builder.ensure(CrateRustdocJsonTypes {
3130 build_compiler: get_tool_target_compiler(
3131 builder,
3132 ToolTargetBuildMode::Build(run.target),
3133 ),
3134 target: run.target,
3135 });
3136 }
3137
3138 fn run(self, builder: &Builder<'_>) {
3139 let target = self.target;
3140
3141 let cargo = tool::prepare_tool_cargo(
3142 builder,
3143 self.build_compiler,
3144 Mode::ToolTarget,
3145 target,
3146 builder.kind,
3147 "src/rustdoc-json-types",
3148 SourceType::InTree,
3149 &[],
3150 );
3151
3152 let libtest_args = if target.contains("musl") {
3154 ["'-Ctarget-feature=-crt-static'"].as_slice()
3155 } else {
3156 &[]
3157 };
3158
3159 run_cargo_test(
3160 cargo,
3161 libtest_args,
3162 &["rustdoc-json-types".to_string()],
3163 "rustdoc-json-types",
3164 target,
3165 builder,
3166 );
3167 }
3168}
3169
3170#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3180pub struct RemoteCopyLibs {
3181 build_compiler: Compiler,
3182 target: TargetSelection,
3183}
3184
3185impl Step for RemoteCopyLibs {
3186 type Output = ();
3187
3188 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3189 run.never()
3190 }
3191
3192 fn run(self, builder: &Builder<'_>) {
3193 let build_compiler = self.build_compiler;
3194 let target = self.target;
3195 if !builder.remote_tested(target) {
3196 return;
3197 }
3198
3199 builder.std(build_compiler, target);
3200
3201 builder.info(&format!("REMOTE copy libs to emulator ({target})"));
3202
3203 let remote_test_server = builder.ensure(tool::RemoteTestServer { build_compiler, target });
3204
3205 let tool = builder.tool_exe(Tool::RemoteTestClient);
3207 let mut cmd = command(&tool);
3208 cmd.arg("spawn-emulator")
3209 .arg(target.triple)
3210 .arg(&remote_test_server.tool_path)
3211 .arg(builder.tempdir());
3212 if let Some(rootfs) = builder.qemu_rootfs(target) {
3213 cmd.arg(rootfs);
3214 }
3215 cmd.run(builder);
3216
3217 for f in t!(builder.sysroot_target_libdir(build_compiler, target).read_dir()) {
3219 let f = t!(f);
3220 if helpers::is_dylib(&f.path()) {
3221 command(&tool).arg("push").arg(f.path()).run(builder);
3222 }
3223 }
3224 }
3225}
3226
3227#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3228pub struct Distcheck;
3229
3230impl Step for Distcheck {
3231 type Output = ();
3232
3233 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3234 run.alias("distcheck")
3235 }
3236
3237 fn make_run(run: RunConfig<'_>) {
3238 run.builder.ensure(Distcheck);
3239 }
3240
3241 fn run(self, builder: &Builder<'_>) {
3251 let root_dir = std::env::temp_dir().join("distcheck");
3254
3255 distcheck_plain_source_tarball(builder, &root_dir.join("distcheck-rustc-src"));
3256 distcheck_rust_src(builder, &root_dir.join("distcheck-rust-src"));
3257 distcheck_rustc_dev(builder, &root_dir.join("distcheck-rustc-dev"));
3258 }
3259}
3260
3261fn distcheck_plain_source_tarball(builder: &Builder<'_>, plain_src_dir: &Path) {
3263 builder.info("Distcheck plain source tarball");
3264 let plain_src_tarball = builder.ensure(dist::PlainSourceTarball);
3265 builder.clear_dir(plain_src_dir);
3266
3267 let configure_args: Vec<String> = std::env::var("DISTCHECK_CONFIGURE_ARGS")
3268 .map(|args| args.split(" ").map(|s| s.to_string()).collect::<Vec<String>>())
3269 .unwrap_or_default();
3270
3271 command("tar")
3272 .arg("-xf")
3273 .arg(plain_src_tarball.tarball())
3274 .arg("--strip-components=1")
3275 .current_dir(plain_src_dir)
3276 .run(builder);
3277 command("./configure")
3278 .arg("--set")
3279 .arg("rust.omit-git-hash=false")
3280 .args(&configure_args)
3281 .arg("--enable-vendor")
3282 .current_dir(plain_src_dir)
3283 .run(builder);
3284 command(helpers::make(&builder.config.host_target.triple))
3285 .arg("check")
3286 .env("GITHUB_ACTIONS", "0")
3289 .current_dir(plain_src_dir)
3290 .run(builder);
3291 builder.remove_dir(plain_src_dir);
3293}
3294
3295fn distcheck_rust_src(builder: &Builder<'_>, src_dir: &Path) {
3297 builder.info("Distcheck rust-src");
3298 let src_tarball = builder.ensure(dist::Src);
3299 builder.clear_dir(src_dir);
3300
3301 command("tar")
3302 .arg("-xf")
3303 .arg(src_tarball.tarball())
3304 .arg("--strip-components=1")
3305 .current_dir(src_dir)
3306 .run(builder);
3307
3308 let toml = src_dir.join("rust-src/lib/rustlib/src/rust/library/std/Cargo.toml");
3309 command(&builder.initial_cargo)
3310 .env("RUSTC_BOOTSTRAP", "1")
3313 .arg("generate-lockfile")
3314 .arg("--manifest-path")
3315 .arg(&toml)
3316 .current_dir(src_dir)
3317 .run(builder);
3318 builder.remove_dir(src_dir);
3320}
3321
3322fn distcheck_rustc_dev(builder: &Builder<'_>, dir: &Path) {
3324 builder.info("Distcheck rustc-dev");
3325 let tarball = builder.ensure(dist::RustcDev::new(builder, builder.host_target)).unwrap();
3326 builder.clear_dir(dir);
3327
3328 command("tar")
3329 .arg("-xf")
3330 .arg(tarball.tarball())
3331 .arg("--strip-components=1")
3332 .current_dir(dir)
3333 .run(builder);
3334
3335 command(&builder.initial_cargo)
3336 .arg("metadata")
3337 .arg("--manifest-path")
3338 .arg("rustc-dev/lib/rustlib/rustc-src/rust/compiler/rustc/Cargo.toml")
3339 .env("RUSTC_BOOTSTRAP", "1")
3340 .env("RUSTC", &builder.initial_rustc)
3342 .current_dir(dir)
3343 .run(builder);
3344 builder.remove_dir(dir);
3346}
3347
3348#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3350pub(crate) struct BootstrapPy;
3351
3352impl Step for BootstrapPy {
3353 type Output = ();
3354 const DEFAULT: bool = true;
3355 const IS_HOST: bool = true;
3356
3357 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3358 let is_ci = run.builder.config.is_running_on_ci;
3362 run.alias("bootstrap-py").default_condition(is_ci)
3363 }
3364
3365 fn make_run(run: RunConfig<'_>) {
3366 run.builder.ensure(BootstrapPy)
3367 }
3368
3369 fn run(self, builder: &Builder<'_>) -> Self::Output {
3370 let mut check_bootstrap = command(
3371 builder.config.python.as_ref().expect("python is required for running bootstrap tests"),
3372 );
3373 check_bootstrap
3374 .args(["-m", "unittest", "bootstrap_test.py"])
3375 .args(builder.config.test_args())
3377 .env("BUILD_DIR", &builder.out)
3378 .env("BUILD_PLATFORM", builder.build.host_target.triple)
3379 .env("BOOTSTRAP_TEST_RUSTC_BIN", &builder.initial_rustc)
3380 .env("BOOTSTRAP_TEST_CARGO_BIN", &builder.initial_cargo)
3381 .current_dir(builder.src.join("src/bootstrap/"));
3382 check_bootstrap.delay_failure().run(builder);
3383 }
3384}
3385
3386#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3387pub struct Bootstrap;
3388
3389impl Step for Bootstrap {
3390 type Output = ();
3391 const DEFAULT: bool = true;
3392 const IS_HOST: bool = true;
3393
3394 fn run(self, builder: &Builder<'_>) {
3396 let host = builder.config.host_target;
3397 let build_compiler = builder.compiler(0, host);
3398
3399 builder.build.require_submodule("src/tools/cargo", None);
3401
3402 let mut cargo = tool::prepare_tool_cargo(
3403 builder,
3404 build_compiler,
3405 Mode::ToolBootstrap,
3406 host,
3407 Kind::Test,
3408 "src/bootstrap",
3409 SourceType::InTree,
3410 &[],
3411 );
3412
3413 cargo.release_build(false);
3414
3415 cargo
3416 .rustflag("-Cdebuginfo=2")
3417 .env("CARGO_TARGET_DIR", builder.out.join("bootstrap"))
3418 .env("INSTA_WORKSPACE_ROOT", &builder.src)
3420 .env("RUSTC_BOOTSTRAP", "1");
3421
3422 if builder.config.cmd.bless() {
3423 cargo.env("INSTA_UPDATE", "always");
3427 }
3428
3429 run_cargo_test(cargo, &[], &[], None, host, builder);
3430 }
3431
3432 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3433 let runs_on_ci = run.builder.config.is_running_on_ci;
3437 run.path("src/bootstrap").default_condition(runs_on_ci)
3438 }
3439
3440 fn make_run(run: RunConfig<'_>) {
3441 run.builder.ensure(Bootstrap);
3442 }
3443}
3444
3445fn get_compiler_to_test(builder: &Builder<'_>, target: TargetSelection) -> Compiler {
3446 builder.compiler(builder.top_stage, target)
3447}
3448
3449#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3452pub struct TierCheck {
3453 test_compiler: Compiler,
3454}
3455
3456impl Step for TierCheck {
3457 type Output = ();
3458 const DEFAULT: bool = true;
3459 const IS_HOST: bool = true;
3460
3461 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3462 run.path("src/tools/tier-check")
3463 }
3464
3465 fn make_run(run: RunConfig<'_>) {
3466 run.builder
3467 .ensure(TierCheck { test_compiler: get_compiler_to_test(run.builder, run.target) });
3468 }
3469
3470 fn run(self, builder: &Builder<'_>) {
3471 let tool_build_compiler = builder.compiler(0, builder.host_target);
3472
3473 let mut cargo = tool::prepare_tool_cargo(
3474 builder,
3475 tool_build_compiler,
3476 Mode::ToolBootstrap,
3477 tool_build_compiler.host,
3478 Kind::Run,
3479 "src/tools/tier-check",
3480 SourceType::InTree,
3481 &[],
3482 );
3483 cargo.arg(builder.src.join("src/doc/rustc/src/platform-support.md"));
3484 cargo.arg(builder.rustc(self.test_compiler));
3485
3486 let _guard = builder.msg_test(
3487 "platform support check",
3488 self.test_compiler.host,
3489 self.test_compiler.stage,
3490 );
3491 BootstrapCommand::from(cargo).delay_failure().run(builder);
3492 }
3493
3494 fn metadata(&self) -> Option<StepMetadata> {
3495 Some(StepMetadata::test("tier-check", self.test_compiler.host))
3496 }
3497}
3498
3499#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3500pub struct LintDocs {
3501 build_compiler: Compiler,
3502 target: TargetSelection,
3503}
3504
3505impl Step for LintDocs {
3506 type Output = ();
3507 const DEFAULT: bool = true;
3508 const IS_HOST: bool = true;
3509
3510 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3511 let stage = run.builder.top_stage;
3512 run.path("src/tools/lint-docs").default_condition(stage > 1)
3515 }
3516
3517 fn make_run(run: RunConfig<'_>) {
3518 if run.builder.top_stage < 2 {
3519 eprintln!("WARNING: lint-docs tests might not work below stage 2");
3520 }
3521
3522 run.builder.ensure(LintDocs {
3523 build_compiler: prepare_doc_compiler(
3524 run.builder,
3525 run.builder.config.host_target,
3526 run.builder.top_stage,
3527 ),
3528 target: run.target,
3529 });
3530 }
3531
3532 fn run(self, builder: &Builder<'_>) {
3535 builder.ensure(crate::core::build_steps::doc::RustcBook::validate(
3536 self.build_compiler,
3537 self.target,
3538 ));
3539 }
3540
3541 fn metadata(&self) -> Option<StepMetadata> {
3542 Some(StepMetadata::test("lint-docs", self.target).built_by(self.build_compiler))
3543 }
3544}
3545
3546#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3547pub struct RustInstaller;
3548
3549impl Step for RustInstaller {
3550 type Output = ();
3551 const IS_HOST: bool = true;
3552 const DEFAULT: bool = true;
3553
3554 fn run(self, builder: &Builder<'_>) {
3556 let bootstrap_host = builder.config.host_target;
3557 let build_compiler = builder.compiler(0, bootstrap_host);
3558 let cargo = tool::prepare_tool_cargo(
3559 builder,
3560 build_compiler,
3561 Mode::ToolBootstrap,
3562 bootstrap_host,
3563 Kind::Test,
3564 "src/tools/rust-installer",
3565 SourceType::InTree,
3566 &[],
3567 );
3568
3569 let _guard = builder.msg_test("rust-installer", bootstrap_host, 1);
3570 run_cargo_test(cargo, &[], &[], None, bootstrap_host, builder);
3571
3572 if bootstrap_host != "x86_64-unknown-linux-gnu" {
3576 return;
3577 }
3578
3579 let mut cmd = command(builder.src.join("src/tools/rust-installer/test.sh"));
3580 let tmpdir = testdir(builder, build_compiler.host).join("rust-installer");
3581 let _ = std::fs::remove_dir_all(&tmpdir);
3582 let _ = std::fs::create_dir_all(&tmpdir);
3583 cmd.current_dir(&tmpdir);
3584 cmd.env("CARGO_TARGET_DIR", tmpdir.join("cargo-target"));
3585 cmd.env("CARGO", &builder.initial_cargo);
3586 cmd.env("RUSTC", &builder.initial_rustc);
3587 cmd.env("TMP_DIR", &tmpdir);
3588 cmd.delay_failure().run(builder);
3589 }
3590
3591 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3592 run.path("src/tools/rust-installer")
3593 }
3594
3595 fn make_run(run: RunConfig<'_>) {
3596 run.builder.ensure(Self);
3597 }
3598}
3599
3600#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3601pub struct TestHelpers {
3602 pub target: TargetSelection,
3603}
3604
3605impl Step for TestHelpers {
3606 type Output = ();
3607
3608 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3609 run.path("tests/auxiliary/rust_test_helpers.c")
3610 }
3611
3612 fn make_run(run: RunConfig<'_>) {
3613 run.builder.ensure(TestHelpers { target: run.target })
3614 }
3615
3616 fn run(self, builder: &Builder<'_>) {
3619 if builder.config.dry_run() {
3620 return;
3621 }
3622 let target = if self.target == "x86_64-fortanix-unknown-sgx" {
3626 TargetSelection::from_user("x86_64-unknown-linux-gnu")
3627 } else {
3628 self.target
3629 };
3630 let dst = builder.test_helpers_out(target);
3631 let src = builder.src.join("tests/auxiliary/rust_test_helpers.c");
3632 if up_to_date(&src, &dst.join("librust_test_helpers.a")) {
3633 return;
3634 }
3635
3636 let _guard = builder.msg_unstaged(Kind::Build, "test helpers", target);
3637 t!(fs::create_dir_all(&dst));
3638 let mut cfg = cc::Build::new();
3639
3640 if !target.is_msvc() {
3644 if let Some(ar) = builder.ar(target) {
3645 cfg.archiver(ar);
3646 }
3647 cfg.compiler(builder.cc(target));
3648 }
3649 cfg.cargo_metadata(false)
3650 .out_dir(&dst)
3651 .target(&target.triple)
3652 .host(&builder.config.host_target.triple)
3653 .opt_level(0)
3654 .warnings(false)
3655 .debug(false)
3656 .file(builder.src.join("tests/auxiliary/rust_test_helpers.c"))
3657 .compile("rust_test_helpers");
3658 }
3659}
3660
3661#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3662pub struct CodegenCranelift {
3663 compilers: RustcPrivateCompilers,
3664 target: TargetSelection,
3665}
3666
3667impl Step for CodegenCranelift {
3668 type Output = ();
3669 const DEFAULT: bool = true;
3670 const IS_HOST: bool = true;
3671
3672 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3673 run.paths(&["compiler/rustc_codegen_cranelift"])
3674 }
3675
3676 fn make_run(run: RunConfig<'_>) {
3677 let builder = run.builder;
3678 let host = run.build_triple();
3679 let compilers = RustcPrivateCompilers::new(run.builder, run.builder.top_stage, host);
3680
3681 if builder.doc_tests == DocTests::Only {
3682 return;
3683 }
3684
3685 if builder.download_rustc() {
3686 builder.info("CI rustc uses the default codegen backend. skipping");
3687 return;
3688 }
3689
3690 if !target_supports_cranelift_backend(run.target) {
3691 builder.info("target not supported by rustc_codegen_cranelift. skipping");
3692 return;
3693 }
3694
3695 if builder.remote_tested(run.target) {
3696 builder.info("remote testing is not supported by rustc_codegen_cranelift. skipping");
3697 return;
3698 }
3699
3700 if !builder
3701 .config
3702 .enabled_codegen_backends(run.target)
3703 .contains(&CodegenBackendKind::Cranelift)
3704 {
3705 builder.info("cranelift not in rust.codegen-backends. skipping");
3706 return;
3707 }
3708
3709 builder.ensure(CodegenCranelift { compilers, target: run.target });
3710 }
3711
3712 fn run(self, builder: &Builder<'_>) {
3713 let compilers = self.compilers;
3714 let build_compiler = compilers.build_compiler();
3715
3716 let target_compiler = compilers.target_compiler();
3719 let target = self.target;
3720
3721 builder.std(target_compiler, target);
3722
3723 let mut cargo = builder::Cargo::new(
3724 builder,
3725 target_compiler,
3726 Mode::Codegen, SourceType::InTree,
3728 target,
3729 Kind::Run,
3730 );
3731
3732 cargo.current_dir(&builder.src.join("compiler/rustc_codegen_cranelift"));
3733 cargo
3734 .arg("--manifest-path")
3735 .arg(builder.src.join("compiler/rustc_codegen_cranelift/build_system/Cargo.toml"));
3736 compile::rustc_cargo_env(builder, &mut cargo, target);
3737
3738 cargo.env("CARGO_BUILD_INCREMENTAL", "false");
3740
3741 let _guard = builder.msg_test(
3742 "rustc_codegen_cranelift",
3743 target_compiler.host,
3744 target_compiler.stage,
3745 );
3746
3747 let download_dir = builder.out.join("cg_clif_download");
3749
3750 cargo
3751 .arg("--")
3752 .arg("test")
3753 .arg("--download-dir")
3754 .arg(&download_dir)
3755 .arg("--out-dir")
3756 .arg(builder.stage_out(build_compiler, Mode::Codegen).join("cg_clif"))
3757 .arg("--no-unstable-features")
3758 .arg("--use-backend")
3759 .arg("cranelift")
3760 .arg("--sysroot")
3762 .arg("llvm")
3763 .arg("--skip-test")
3766 .arg("testsuite.extended_sysroot");
3767
3768 cargo.into_cmd().run(builder);
3769 }
3770
3771 fn metadata(&self) -> Option<StepMetadata> {
3772 Some(
3773 StepMetadata::test("rustc_codegen_cranelift", self.target)
3774 .built_by(self.compilers.build_compiler()),
3775 )
3776 }
3777}
3778
3779#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3780pub struct CodegenGCC {
3781 compilers: RustcPrivateCompilers,
3782 target: TargetSelection,
3783}
3784
3785impl Step for CodegenGCC {
3786 type Output = ();
3787 const DEFAULT: bool = true;
3788 const IS_HOST: bool = true;
3789
3790 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3791 run.paths(&["compiler/rustc_codegen_gcc"])
3792 }
3793
3794 fn make_run(run: RunConfig<'_>) {
3795 let builder = run.builder;
3796 let host = run.build_triple();
3797 let compilers = RustcPrivateCompilers::new(run.builder, run.builder.top_stage, host);
3798
3799 if builder.doc_tests == DocTests::Only {
3800 return;
3801 }
3802
3803 if builder.download_rustc() {
3804 builder.info("CI rustc uses the default codegen backend. skipping");
3805 return;
3806 }
3807
3808 let triple = run.target.triple;
3809 let target_supported =
3810 if triple.contains("linux") { triple.contains("x86_64") } else { false };
3811 if !target_supported {
3812 builder.info("target not supported by rustc_codegen_gcc. skipping");
3813 return;
3814 }
3815
3816 if builder.remote_tested(run.target) {
3817 builder.info("remote testing is not supported by rustc_codegen_gcc. skipping");
3818 return;
3819 }
3820
3821 if !builder.config.enabled_codegen_backends(run.target).contains(&CodegenBackendKind::Gcc) {
3822 builder.info("gcc not in rust.codegen-backends. skipping");
3823 return;
3824 }
3825
3826 builder.ensure(CodegenGCC { compilers, target: run.target });
3827 }
3828
3829 fn run(self, builder: &Builder<'_>) {
3830 let compilers = self.compilers;
3831 let target = self.target;
3832
3833 let gcc = builder.ensure(Gcc { target });
3834
3835 builder.ensure(
3836 compile::Std::new(compilers.build_compiler(), target)
3837 .extra_rust_args(&["-Csymbol-mangling-version=v0", "-Cpanic=abort"]),
3838 );
3839
3840 let _guard = builder.msg_test(
3841 "rustc_codegen_gcc",
3842 compilers.target(),
3843 compilers.target_compiler().stage,
3844 );
3845
3846 let mut cargo = builder::Cargo::new(
3847 builder,
3848 compilers.build_compiler(),
3849 Mode::Codegen, SourceType::InTree,
3851 target,
3852 Kind::Run,
3853 );
3854
3855 cargo.current_dir(&builder.src.join("compiler/rustc_codegen_gcc"));
3856 cargo
3857 .arg("--manifest-path")
3858 .arg(builder.src.join("compiler/rustc_codegen_gcc/build_system/Cargo.toml"));
3859 compile::rustc_cargo_env(builder, &mut cargo, target);
3860 add_cg_gcc_cargo_flags(&mut cargo, &gcc);
3861
3862 cargo.env("CARGO_BUILD_INCREMENTAL", "false");
3864 cargo.rustflag("-Cpanic=abort");
3865
3866 cargo
3867 .env("CG_RUSTFLAGS", "-Alinker-messages")
3869 .arg("--")
3870 .arg("test")
3871 .arg("--use-backend")
3872 .arg("gcc")
3873 .arg("--gcc-path")
3874 .arg(gcc.libgccjit.parent().unwrap())
3875 .arg("--out-dir")
3876 .arg(builder.stage_out(compilers.build_compiler(), Mode::Codegen).join("cg_gcc"))
3877 .arg("--release")
3878 .arg("--mini-tests")
3879 .arg("--std-tests");
3880 cargo.args(builder.config.test_args());
3881
3882 cargo.into_cmd().run(builder);
3883 }
3884
3885 fn metadata(&self) -> Option<StepMetadata> {
3886 Some(
3887 StepMetadata::test("rustc_codegen_gcc", self.target)
3888 .built_by(self.compilers.build_compiler()),
3889 )
3890 }
3891}
3892
3893#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3898pub struct TestFloatParse {
3899 build_compiler: Compiler,
3908 target: TargetSelection,
3910}
3911
3912impl Step for TestFloatParse {
3913 type Output = ();
3914 const IS_HOST: bool = true;
3915 const DEFAULT: bool = true;
3916
3917 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3918 run.path("src/tools/test-float-parse")
3919 }
3920
3921 fn make_run(run: RunConfig<'_>) {
3922 run.builder.ensure(Self {
3923 build_compiler: get_compiler_to_test(run.builder, run.target),
3924 target: run.target,
3925 });
3926 }
3927
3928 fn run(self, builder: &Builder<'_>) {
3929 let build_compiler = self.build_compiler;
3930 let target = self.target;
3931
3932 builder.std(build_compiler, target);
3934 builder.std(build_compiler, builder.host_target);
3935
3936 let mut cargo_test = tool::prepare_tool_cargo(
3938 builder,
3939 build_compiler,
3940 Mode::ToolStd,
3941 target,
3942 Kind::Test,
3943 "src/tools/test-float-parse",
3944 SourceType::InTree,
3945 &[],
3946 );
3947 cargo_test.allow_features(TEST_FLOAT_PARSE_ALLOW_FEATURES);
3948
3949 run_cargo_test(cargo_test, &[], &[], "test-float-parse", target, builder);
3950
3951 let mut cargo_run = tool::prepare_tool_cargo(
3953 builder,
3954 build_compiler,
3955 Mode::ToolStd,
3956 target,
3957 Kind::Run,
3958 "src/tools/test-float-parse",
3959 SourceType::InTree,
3960 &[],
3961 );
3962 cargo_run.allow_features(TEST_FLOAT_PARSE_ALLOW_FEATURES);
3963
3964 if !matches!(env::var("FLOAT_PARSE_TESTS_NO_SKIP_HUGE").as_deref(), Ok("1") | Ok("true")) {
3965 cargo_run.args(["--", "--skip-huge"]);
3966 }
3967
3968 cargo_run.into_cmd().run(builder);
3969 }
3970}
3971
3972#[derive(Debug, Clone, Hash, PartialEq, Eq)]
3976pub struct CollectLicenseMetadata;
3977
3978impl Step for CollectLicenseMetadata {
3979 type Output = PathBuf;
3980 const IS_HOST: bool = true;
3981
3982 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3983 run.path("src/tools/collect-license-metadata")
3984 }
3985
3986 fn make_run(run: RunConfig<'_>) {
3987 run.builder.ensure(CollectLicenseMetadata);
3988 }
3989
3990 fn run(self, builder: &Builder<'_>) -> Self::Output {
3991 let Some(reuse) = &builder.config.reuse else {
3992 panic!("REUSE is required to collect the license metadata");
3993 };
3994
3995 let dest = builder.src.join("license-metadata.json");
3996
3997 let mut cmd = builder.tool_cmd(Tool::CollectLicenseMetadata);
3998 cmd.env("REUSE_EXE", reuse);
3999 cmd.env("DEST", &dest);
4000 cmd.env("ONLY_CHECK", "1");
4001 cmd.run(builder);
4002
4003 dest
4004 }
4005}
4006
4007#[derive(Debug, Clone, PartialEq, Eq, Hash)]
4008pub struct RemoteTestClientTests {
4009 host: TargetSelection,
4010}
4011
4012impl Step for RemoteTestClientTests {
4013 type Output = ();
4014 const IS_HOST: bool = true;
4015 const DEFAULT: bool = true;
4016
4017 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
4018 run.path("src/tools/remote-test-client")
4019 }
4020
4021 fn make_run(run: RunConfig<'_>) {
4022 run.builder.ensure(Self { host: run.target });
4023 }
4024
4025 fn run(self, builder: &Builder<'_>) {
4026 let bootstrap_host = builder.config.host_target;
4027 let compiler = builder.compiler(0, bootstrap_host);
4028
4029 let cargo = tool::prepare_tool_cargo(
4030 builder,
4031 compiler,
4032 Mode::ToolBootstrap,
4033 bootstrap_host,
4034 Kind::Test,
4035 "src/tools/remote-test-client",
4036 SourceType::InTree,
4037 &[],
4038 );
4039
4040 run_cargo_test(cargo, &[], &[], "remote-test-client", bootstrap_host, builder);
4041 }
4042}