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
53 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
54 run.path("src/tools/jsondoclint")
59 .path("src/tools/replace-version-placeholder")
60 .path("src/tools/coverage-dump")
61 .alias("tidyselftest")
64 }
65
66 fn is_default_step(_builder: &Builder<'_>) -> bool {
67 true
68 }
69
70 fn make_run(run: RunConfig<'_>) {
71 for path in run.paths {
74 let path = path.assert_single_path().path.clone();
75 run.builder.ensure(CrateBootstrap { host: run.target, path });
76 }
77 }
78
79 fn run(self, builder: &Builder<'_>) {
80 let bootstrap_host = builder.config.host_target;
81 let compiler = builder.compiler(0, bootstrap_host);
82 let mut path = self.path.to_str().unwrap();
83
84 if path == "tidyselftest" {
86 path = "src/tools/tidy";
87 }
88
89 let cargo = tool::prepare_tool_cargo(
90 builder,
91 compiler,
92 Mode::ToolBootstrap,
93 bootstrap_host,
94 Kind::Test,
95 path,
96 SourceType::InTree,
97 &[],
98 );
99
100 let crate_name = path.rsplit_once('/').unwrap().1;
101 run_cargo_test(cargo, &[], &[], crate_name, bootstrap_host, builder);
102 }
103
104 fn metadata(&self) -> Option<StepMetadata> {
105 Some(
106 StepMetadata::test("crate-bootstrap", self.host)
107 .with_metadata(self.path.as_path().to_string_lossy().to_string()),
108 )
109 }
110}
111
112#[derive(Debug, Clone, PartialEq, Eq, Hash)]
113pub struct Linkcheck {
114 host: TargetSelection,
115}
116
117impl Step for Linkcheck {
118 type Output = ();
119 const IS_HOST: bool = true;
120
121 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
122 run.path("src/tools/linkchecker")
123 }
124
125 fn is_default_step(builder: &Builder<'_>) -> bool {
126 builder.config.docs
127 }
128
129 fn make_run(run: RunConfig<'_>) {
130 run.builder.ensure(Linkcheck { host: run.target });
131 }
132
133 fn run(self, builder: &Builder<'_>) {
138 let host = self.host;
139 let hosts = &builder.hosts;
140 let targets = &builder.targets;
141
142 if (hosts != targets) && !hosts.is_empty() && !targets.is_empty() {
147 panic!(
148 "Linkcheck currently does not support builds with different hosts and targets.
149You can skip linkcheck with --skip src/tools/linkchecker"
150 );
151 }
152
153 builder.info(&format!("Linkcheck ({host})"));
154
155 let bootstrap_host = builder.config.host_target;
157 let compiler = builder.compiler(0, bootstrap_host);
158
159 let cargo = tool::prepare_tool_cargo(
160 builder,
161 compiler,
162 Mode::ToolBootstrap,
163 bootstrap_host,
164 Kind::Test,
165 "src/tools/linkchecker",
166 SourceType::InTree,
167 &[],
168 );
169 run_cargo_test(cargo, &[], &[], "linkchecker self tests", bootstrap_host, builder);
170
171 if builder.doc_tests == DocTests::No {
172 return;
173 }
174
175 builder.run_default_doc_steps();
177
178 let linkchecker = builder.tool_cmd(Tool::Linkchecker);
180
181 let _guard = builder.msg_test("Linkcheck", bootstrap_host, 1);
183 let _time = helpers::timeit(builder);
184 linkchecker.delay_failure().arg(builder.out.join(host).join("doc")).run(builder);
185 }
186
187 fn metadata(&self) -> Option<StepMetadata> {
188 Some(StepMetadata::test("link-check", self.host))
189 }
190}
191
192fn check_if_tidy_is_installed(builder: &Builder<'_>) -> bool {
193 command("tidy")
194 .allow_failure()
195 .arg("--version")
196 .cached()
198 .run_capture_stdout(builder)
199 .is_success()
200}
201
202#[derive(Debug, Clone, PartialEq, Eq, Hash)]
203pub struct HtmlCheck {
204 target: TargetSelection,
205}
206
207impl Step for HtmlCheck {
208 type Output = ();
209 const IS_HOST: bool = true;
210
211 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
212 run.path("src/tools/html-checker")
213 }
214
215 fn is_default_step(builder: &Builder<'_>) -> bool {
216 check_if_tidy_is_installed(builder)
217 }
218
219 fn make_run(run: RunConfig<'_>) {
220 run.builder.ensure(HtmlCheck { target: run.target });
221 }
222
223 fn run(self, builder: &Builder<'_>) {
224 if !check_if_tidy_is_installed(builder) {
225 eprintln!("not running HTML-check tool because `tidy` is missing");
226 eprintln!(
227 "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."
228 );
229 panic!("Cannot run html-check tests");
230 }
231 builder.run_default_doc_steps();
233 builder.ensure(crate::core::build_steps::doc::Rustc::for_stage(
234 builder,
235 builder.top_stage,
236 self.target,
237 ));
238
239 builder
240 .tool_cmd(Tool::HtmlChecker)
241 .delay_failure()
242 .arg(builder.doc_out(self.target))
243 .run(builder);
244 }
245
246 fn metadata(&self) -> Option<StepMetadata> {
247 Some(StepMetadata::test("html-check", self.target))
248 }
249}
250
251#[derive(Debug, Clone, PartialEq, Eq, Hash)]
255pub struct Cargotest {
256 build_compiler: Compiler,
257 host: TargetSelection,
258}
259
260impl Step for Cargotest {
261 type Output = ();
262 const IS_HOST: bool = true;
263
264 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
265 run.path("src/tools/cargotest")
266 }
267
268 fn make_run(run: RunConfig<'_>) {
269 if run.builder.top_stage == 0 {
270 eprintln!(
271 "ERROR: running cargotest with stage 0 is currently unsupported. Use at least stage 1."
272 );
273 exit!(1);
274 }
275 run.builder.ensure(Cargotest {
279 build_compiler: run.builder.compiler(run.builder.top_stage - 1, run.target),
280 host: run.target,
281 });
282 }
283
284 fn run(self, builder: &Builder<'_>) {
289 let cargo =
299 builder.ensure(tool::Cargo::from_build_compiler(self.build_compiler, self.host));
300 let tested_compiler = builder.compiler(self.build_compiler.stage + 1, self.host);
301 builder.std(tested_compiler, self.host);
302
303 let out_dir = builder.out.join("ct");
307 t!(fs::create_dir_all(&out_dir));
308
309 let _time = helpers::timeit(builder);
310 let mut cmd = builder.tool_cmd(Tool::CargoTest);
311 cmd.arg(&cargo.tool_path)
312 .arg(&out_dir)
313 .args(builder.config.test_args())
314 .env("RUSTC", builder.rustc(tested_compiler))
315 .env("RUSTDOC", builder.rustdoc_for_compiler(tested_compiler));
316 add_rustdoc_cargo_linker_args(&mut cmd, builder, tested_compiler.host, LldThreads::No);
317 cmd.delay_failure().run(builder);
318 }
319
320 fn metadata(&self) -> Option<StepMetadata> {
321 Some(StepMetadata::test("cargotest", self.host).stage(self.build_compiler.stage + 1))
322 }
323}
324
325#[derive(Debug, Clone, PartialEq, Eq, Hash)]
328pub struct Cargo {
329 build_compiler: Compiler,
330 host: TargetSelection,
331}
332
333impl Cargo {
334 const CRATE_PATH: &str = "src/tools/cargo";
335}
336
337impl Step for Cargo {
338 type Output = ();
339 const IS_HOST: bool = true;
340
341 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
342 run.path(Self::CRATE_PATH)
343 }
344
345 fn make_run(run: RunConfig<'_>) {
346 run.builder.ensure(Cargo {
347 build_compiler: get_tool_target_compiler(
348 run.builder,
349 ToolTargetBuildMode::Build(run.target),
350 ),
351 host: run.target,
352 });
353 }
354
355 fn run(self, builder: &Builder<'_>) {
357 builder.ensure(tool::Cargo::from_build_compiler(self.build_compiler, self.host));
361
362 let tested_compiler = builder.compiler(self.build_compiler.stage + 1, self.host);
363 builder.std(tested_compiler, self.host);
364 builder.rustdoc_for_compiler(tested_compiler);
368
369 let cargo = tool::prepare_tool_cargo(
370 builder,
371 self.build_compiler,
372 Mode::ToolTarget,
373 self.host,
374 Kind::Test,
375 Self::CRATE_PATH,
376 SourceType::Submodule,
377 &[],
378 );
379
380 let mut cargo = prepare_cargo_test(cargo, &[], &[], self.host, builder);
382
383 cargo.env("CFG_DISABLE_CROSS_TESTS", "1");
386 cargo.env("CARGO_TEST_DISABLE_NIGHTLY", "1");
389
390 cargo.env("PATH", bin_path_for_cargo(builder, tested_compiler));
394
395 let mut existing_dylib_paths = cargo
400 .get_envs()
401 .find(|(k, _)| *k == OsStr::new(dylib_path_var()))
402 .and_then(|(_, v)| v)
403 .map(|value| split_paths(value).collect::<Vec<PathBuf>>())
404 .unwrap_or_default();
405 existing_dylib_paths.insert(0, builder.rustc_libdir(tested_compiler));
406 add_dylib_path(existing_dylib_paths, &mut cargo);
407
408 cargo.env("CARGO_RUSTC_CURRENT_DIR", builder.src.display().to_string());
412
413 #[cfg(feature = "build-metrics")]
414 builder.metrics.begin_test_suite(
415 build_helper::metrics::TestSuiteMetadata::CargoPackage {
416 crates: vec!["cargo".into()],
417 target: self.host.triple.to_string(),
418 host: self.host.triple.to_string(),
419 stage: self.build_compiler.stage + 1,
420 },
421 builder,
422 );
423
424 let _time = helpers::timeit(builder);
425 add_flags_and_try_run_tests(builder, &mut cargo);
426 }
427
428 fn metadata(&self) -> Option<StepMetadata> {
429 Some(StepMetadata::test("cargo", self.host).built_by(self.build_compiler))
430 }
431}
432
433#[derive(Debug, Clone, PartialEq, Eq, Hash)]
434pub struct RustAnalyzer {
435 compilers: RustcPrivateCompilers,
436}
437
438impl Step for RustAnalyzer {
439 type Output = ();
440 const IS_HOST: bool = true;
441
442 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
443 run.path("src/tools/rust-analyzer")
444 }
445
446 fn is_default_step(_builder: &Builder<'_>) -> bool {
447 true
448 }
449
450 fn make_run(run: RunConfig<'_>) {
451 run.builder.ensure(Self {
452 compilers: RustcPrivateCompilers::new(
453 run.builder,
454 run.builder.top_stage,
455 run.builder.host_target,
456 ),
457 });
458 }
459
460 fn run(self, builder: &Builder<'_>) {
462 let host = self.compilers.target();
463
464 let workspace_path = "src/tools/rust-analyzer";
465 let crate_path = "src/tools/rust-analyzer/crates/proc-macro-srv";
468 let mut cargo = tool::prepare_tool_cargo(
469 builder,
470 self.compilers.build_compiler(),
471 Mode::ToolRustcPrivate,
472 host,
473 Kind::Test,
474 crate_path,
475 SourceType::InTree,
476 &["in-rust-tree".to_owned()],
477 );
478 cargo.allow_features(tool::RustAnalyzer::ALLOW_FEATURES);
479
480 let dir = builder.src.join(workspace_path);
481 cargo.env("CARGO_WORKSPACE_DIR", &dir);
484
485 cargo.env("SKIP_SLOW_TESTS", "1");
488
489 cargo.add_rustc_lib_path(builder);
490 run_cargo_test(cargo, &[], &[], "rust-analyzer", host, builder);
491 }
492
493 fn metadata(&self) -> Option<StepMetadata> {
494 Some(
495 StepMetadata::test("rust-analyzer", self.compilers.target())
496 .built_by(self.compilers.build_compiler()),
497 )
498 }
499}
500
501#[derive(Debug, Clone, PartialEq, Eq, Hash)]
503pub struct Rustfmt {
504 compilers: RustcPrivateCompilers,
505}
506
507impl Step for Rustfmt {
508 type Output = ();
509 const IS_HOST: bool = true;
510
511 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
512 run.path("src/tools/rustfmt")
513 }
514
515 fn make_run(run: RunConfig<'_>) {
516 run.builder.ensure(Rustfmt {
517 compilers: RustcPrivateCompilers::new(
518 run.builder,
519 run.builder.top_stage,
520 run.builder.host_target,
521 ),
522 });
523 }
524
525 fn run(self, builder: &Builder<'_>) {
527 let build_compiler = self.compilers.build_compiler();
528 let target = self.compilers.target();
529
530 let mut cargo = tool::prepare_tool_cargo(
531 builder,
532 build_compiler,
533 Mode::ToolRustcPrivate,
534 target,
535 Kind::Test,
536 "src/tools/rustfmt",
537 SourceType::InTree,
538 &[],
539 );
540
541 let dir = testdir(builder, target);
542 t!(fs::create_dir_all(&dir));
543 cargo.env("RUSTFMT_TEST_DIR", dir);
544
545 cargo.add_rustc_lib_path(builder);
546
547 run_cargo_test(cargo, &[], &[], "rustfmt", target, builder);
548 }
549
550 fn metadata(&self) -> Option<StepMetadata> {
551 Some(
552 StepMetadata::test("rustfmt", self.compilers.target())
553 .built_by(self.compilers.build_compiler()),
554 )
555 }
556}
557
558#[derive(Debug, Clone, PartialEq, Eq, Hash)]
559pub struct Miri {
560 target: TargetSelection,
561}
562
563impl Miri {
564 pub fn build_miri_sysroot(
566 builder: &Builder<'_>,
567 compiler: Compiler,
568 target: TargetSelection,
569 ) -> PathBuf {
570 let miri_sysroot = builder.out.join(compiler.host).join("miri-sysroot");
571 let mut cargo = builder::Cargo::new(
572 builder,
573 compiler,
574 Mode::Std,
575 SourceType::Submodule,
576 target,
577 Kind::MiriSetup,
578 );
579
580 cargo.env("MIRI_LIB_SRC", builder.src.join("library"));
582 cargo.env("MIRI_SYSROOT", &miri_sysroot);
584
585 let mut cargo = BootstrapCommand::from(cargo);
586 let _guard =
587 builder.msg(Kind::Build, "miri sysroot", Mode::ToolRustcPrivate, compiler, target);
588 cargo.run(builder);
589
590 cargo.arg("--print-sysroot");
596
597 builder.do_if_verbose(|| println!("running: {cargo:?}"));
598 let stdout = cargo.run_capture_stdout(builder).stdout();
599 let sysroot = stdout.trim_end();
601 builder.do_if_verbose(|| println!("`cargo miri setup --print-sysroot` said: {sysroot:?}"));
602 PathBuf::from(sysroot)
603 }
604}
605
606impl Step for Miri {
607 type Output = ();
608
609 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
610 run.path("src/tools/miri")
611 }
612
613 fn make_run(run: RunConfig<'_>) {
614 run.builder.ensure(Miri { target: run.target });
615 }
616
617 fn run(self, builder: &Builder<'_>) {
619 let host = builder.build.host_target;
620 let target = self.target;
621 let stage = builder.top_stage;
622 if stage == 0 {
623 eprintln!("miri cannot be tested at stage 0");
624 std::process::exit(1);
625 }
626
627 let compilers = RustcPrivateCompilers::new(builder, stage, host);
629
630 let miri = builder.ensure(tool::Miri::from_compilers(compilers));
632 builder.ensure(tool::CargoMiri::from_compilers(compilers));
634
635 let target_compiler = compilers.target_compiler();
636
637 let miri_sysroot = Miri::build_miri_sysroot(builder, target_compiler, target);
640 builder.std(target_compiler, host);
641 let host_sysroot = builder.sysroot(target_compiler);
642
643 if !builder.config.dry_run() {
646 let ui_test_dep_dir = builder
649 .stage_out(miri.build_compiler, Mode::ToolStd)
650 .join(host)
651 .join("tmp")
652 .join("miri_ui");
653 build_stamp::clear_if_dirty(builder, &ui_test_dep_dir, &miri_sysroot);
657 }
658
659 let mut cargo = tool::prepare_tool_cargo(
662 builder,
663 miri.build_compiler,
664 Mode::ToolRustcPrivate,
665 host,
666 Kind::Test,
667 "src/tools/miri",
668 SourceType::InTree,
669 &[],
670 );
671
672 cargo.add_rustc_lib_path(builder);
673
674 let mut cargo = prepare_cargo_test(cargo, &[], &[], host, builder);
677
678 cargo.env("MIRI_SYSROOT", &miri_sysroot);
680 cargo.env("MIRI_HOST_SYSROOT", &host_sysroot);
681 cargo.env("MIRI", &miri.tool_path);
682
683 cargo.env("MIRI_TEST_TARGET", target.rustc_target_arg());
685
686 {
687 let _guard = builder.msg_test("miri", target, target_compiler.stage);
688 let _time = helpers::timeit(builder);
689 cargo.run(builder);
690 }
691
692 if builder.config.test_args().is_empty() {
694 cargo.env("MIRIFLAGS", "-O -Zmir-opt-level=4 -Cdebug-assertions=yes");
695 cargo.env("MIRI_SKIP_UI_CHECKS", "1");
697 cargo.env_remove("RUSTC_BLESS");
699 cargo.args(["tests/pass", "tests/panic"]);
701
702 {
703 let _guard =
704 builder.msg_test("miri (mir-opt-level 4)", target, target_compiler.stage);
705 let _time = helpers::timeit(builder);
706 cargo.run(builder);
707 }
708 }
709 }
710}
711
712#[derive(Debug, Clone, PartialEq, Eq, Hash)]
715pub struct CargoMiri {
716 target: TargetSelection,
717}
718
719impl Step for CargoMiri {
720 type Output = ();
721
722 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
723 run.path("src/tools/miri/cargo-miri")
724 }
725
726 fn make_run(run: RunConfig<'_>) {
727 run.builder.ensure(CargoMiri { target: run.target });
728 }
729
730 fn run(self, builder: &Builder<'_>) {
732 let host = builder.build.host_target;
733 let target = self.target;
734 let stage = builder.top_stage;
735 if stage == 0 {
736 eprintln!("cargo-miri cannot be tested at stage 0");
737 std::process::exit(1);
738 }
739
740 let build_compiler = builder.compiler(stage, host);
742
743 let mut cargo = tool::prepare_tool_cargo(
748 builder,
749 build_compiler,
750 Mode::ToolStd, target,
752 Kind::MiriTest,
753 "src/tools/miri/test-cargo-miri",
754 SourceType::Submodule,
755 &[],
756 );
757
758 match builder.doc_tests {
761 DocTests::Yes => {}
762 DocTests::No => {
763 cargo.args(["--lib", "--bins", "--examples", "--tests", "--benches"]);
764 }
765 DocTests::Only => {
766 cargo.arg("--doc");
767 }
768 }
769 cargo.arg("--").args(builder.config.test_args());
770
771 let mut cargo = BootstrapCommand::from(cargo);
773 {
774 let _guard = builder.msg_test("cargo-miri", target, stage);
775 let _time = helpers::timeit(builder);
776 cargo.run(builder);
777 }
778 }
779}
780
781#[derive(Debug, Clone, PartialEq, Eq, Hash)]
782pub struct CompiletestTest {
783 host: TargetSelection,
784}
785
786impl Step for CompiletestTest {
787 type Output = ();
788
789 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
790 run.path("src/tools/compiletest")
791 }
792
793 fn make_run(run: RunConfig<'_>) {
794 run.builder.ensure(CompiletestTest { host: run.target });
795 }
796
797 fn run(self, builder: &Builder<'_>) {
799 let host = self.host;
800
801 if builder.top_stage == 0 && !builder.config.compiletest_allow_stage0 {
807 eprintln!("\
808ERROR: `--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
809NOTE: 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`."
810 );
811 crate::exit!(1);
812 }
813
814 let bootstrap_compiler = builder.compiler(0, host);
815 let staged_compiler = builder.compiler(builder.top_stage, host);
816
817 let mut cargo = tool::prepare_tool_cargo(
818 builder,
819 bootstrap_compiler,
820 Mode::ToolBootstrap,
821 host,
822 Kind::Test,
823 "src/tools/compiletest",
824 SourceType::InTree,
825 &[],
826 );
827
828 cargo.env("TEST_RUSTC", builder.rustc(staged_compiler));
832
833 run_cargo_test(cargo, &[], &[], "compiletest self test", host, builder);
834 }
835}
836
837#[derive(Debug, Clone, PartialEq, Eq, Hash)]
838pub struct Clippy {
839 compilers: RustcPrivateCompilers,
840}
841
842impl Step for Clippy {
843 type Output = ();
844 const IS_HOST: bool = true;
845
846 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
847 run.suite_path("src/tools/clippy/tests").path("src/tools/clippy")
848 }
849
850 fn is_default_step(_builder: &Builder<'_>) -> bool {
851 false
852 }
853
854 fn make_run(run: RunConfig<'_>) {
855 run.builder.ensure(Clippy {
856 compilers: RustcPrivateCompilers::new(
857 run.builder,
858 run.builder.top_stage,
859 run.builder.host_target,
860 ),
861 });
862 }
863
864 fn run(self, builder: &Builder<'_>) {
866 let target = self.compilers.target();
867
868 let target_compiler = self.compilers.target_compiler();
872 let build_compiler = self.compilers.build_compiler();
873
874 let mut cargo = tool::prepare_tool_cargo(
875 builder,
876 build_compiler,
877 Mode::ToolRustcPrivate,
878 target,
879 Kind::Test,
880 "src/tools/clippy",
881 SourceType::InTree,
882 &[],
883 );
884
885 cargo.env("RUSTC_TEST_SUITE", builder.rustc(build_compiler));
886 cargo.env("RUSTC_LIB_PATH", builder.rustc_libdir(build_compiler));
887 let host_libs =
888 builder.stage_out(build_compiler, Mode::ToolRustcPrivate).join(builder.cargo_dir());
889 cargo.env("HOST_LIBS", host_libs);
890
891 builder.std(target_compiler, target);
893 cargo.env("TEST_SYSROOT", builder.sysroot(target_compiler));
894 cargo.env("TEST_RUSTC", builder.rustc(target_compiler));
895 cargo.env("TEST_RUSTC_LIB", builder.rustc_libdir(target_compiler));
896
897 'partially_test: {
899 let paths = &builder.config.paths[..];
900 let mut test_names = Vec::new();
901 for path in paths {
902 if let Some(path) =
903 helpers::is_valid_test_suite_arg(path, "src/tools/clippy/tests", builder)
904 {
905 test_names.push(path);
906 } else if path.ends_with("src/tools/clippy") {
907 break 'partially_test;
909 }
910 }
911 cargo.env("TESTNAME", test_names.join(","));
912 }
913
914 cargo.add_rustc_lib_path(builder);
915 let cargo = prepare_cargo_test(cargo, &[], &[], target, builder);
916
917 let _guard = builder.msg_test("clippy", target, target_compiler.stage);
918
919 if cargo.allow_failure().run(builder) {
921 return;
923 }
924
925 if !builder.config.cmd.bless() {
926 crate::exit!(1);
927 }
928 }
929
930 fn metadata(&self) -> Option<StepMetadata> {
931 Some(
932 StepMetadata::test("clippy", self.compilers.target())
933 .built_by(self.compilers.build_compiler()),
934 )
935 }
936}
937
938fn bin_path_for_cargo(builder: &Builder<'_>, compiler: Compiler) -> OsString {
939 let path = builder.sysroot(compiler).join("bin");
940 let old_path = env::var_os("PATH").unwrap_or_default();
941 env::join_paths(iter::once(path).chain(env::split_paths(&old_path))).expect("")
942}
943
944#[derive(Debug, Clone, Hash, PartialEq, Eq)]
946pub struct RustdocTheme {
947 test_compiler: Compiler,
949}
950
951impl Step for RustdocTheme {
952 type Output = ();
953 const IS_HOST: bool = true;
954
955 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
956 run.path("src/tools/rustdoc-themes")
957 }
958
959 fn is_default_step(_builder: &Builder<'_>) -> bool {
960 true
961 }
962
963 fn make_run(run: RunConfig<'_>) {
964 let test_compiler = run.builder.compiler(run.builder.top_stage, run.target);
965
966 run.builder.ensure(RustdocTheme { test_compiler });
967 }
968
969 fn run(self, builder: &Builder<'_>) {
970 let rustdoc = builder.bootstrap_out.join("rustdoc");
971 let mut cmd = builder.tool_cmd(Tool::RustdocTheme);
972 cmd.arg(rustdoc.to_str().unwrap())
973 .arg(builder.src.join("src/librustdoc/html/static/css/rustdoc.css").to_str().unwrap())
974 .env("RUSTC_STAGE", self.test_compiler.stage.to_string())
975 .env("RUSTC_SYSROOT", builder.sysroot(self.test_compiler))
976 .env(
977 "RUSTDOC_LIBDIR",
978 builder.sysroot_target_libdir(self.test_compiler, self.test_compiler.host),
979 )
980 .env("CFG_RELEASE_CHANNEL", &builder.config.channel)
981 .env("RUSTDOC_REAL", builder.rustdoc_for_compiler(self.test_compiler))
982 .env("RUSTC_BOOTSTRAP", "1");
983 cmd.args(linker_args(builder, self.test_compiler.host, LldThreads::No));
984
985 cmd.delay_failure().run(builder);
986 }
987
988 fn metadata(&self) -> Option<StepMetadata> {
989 Some(
990 StepMetadata::test("rustdoc-theme", self.test_compiler.host)
991 .stage(self.test_compiler.stage),
992 )
993 }
994}
995
996#[derive(Debug, Clone, Hash, PartialEq, Eq)]
998pub struct RustdocJSStd {
999 build_compiler: Compiler,
1001 target: TargetSelection,
1002}
1003
1004impl Step for RustdocJSStd {
1005 type Output = ();
1006 const IS_HOST: bool = true;
1007
1008 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1009 run.suite_path("tests/rustdoc-js-std")
1010 }
1011
1012 fn is_default_step(builder: &Builder<'_>) -> bool {
1013 builder.config.nodejs.is_some()
1014 }
1015
1016 fn make_run(run: RunConfig<'_>) {
1017 run.builder.ensure(RustdocJSStd {
1018 build_compiler: run.builder.compiler(run.builder.top_stage, run.builder.host_target),
1019 target: run.target,
1020 });
1021 }
1022
1023 fn run(self, builder: &Builder<'_>) {
1024 let nodejs =
1025 builder.config.nodejs.as_ref().expect("need nodejs to run rustdoc-js-std tests");
1026 let mut command = command(nodejs);
1027 command
1028 .arg(builder.src.join("src/tools/rustdoc-js/tester.js"))
1029 .arg("--crate-name")
1030 .arg("std")
1031 .arg("--resource-suffix")
1032 .arg(&builder.version)
1033 .arg("--doc-folder")
1034 .arg(builder.doc_out(self.target))
1035 .arg("--test-folder")
1036 .arg(builder.src.join("tests/rustdoc-js-std"));
1037 for path in &builder.paths {
1038 if let Some(p) = helpers::is_valid_test_suite_arg(path, "tests/rustdoc-js-std", builder)
1039 {
1040 if !p.ends_with(".js") {
1041 eprintln!("A non-js file was given: `{}`", path.display());
1042 panic!("Cannot run rustdoc-js-std tests");
1043 }
1044 command.arg("--test-file").arg(path);
1045 }
1046 }
1047 builder.ensure(crate::core::build_steps::doc::Std::from_build_compiler(
1048 self.build_compiler,
1049 self.target,
1050 DocumentationFormat::Html,
1051 ));
1052 let _guard = builder.msg_test("rustdoc-js-std", self.target, self.build_compiler.stage);
1053 command.run(builder);
1054 }
1055
1056 fn metadata(&self) -> Option<StepMetadata> {
1057 Some(StepMetadata::test("rustdoc-js-std", self.target).stage(self.build_compiler.stage))
1058 }
1059}
1060
1061#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1062pub struct RustdocJSNotStd {
1063 pub target: TargetSelection,
1064 pub compiler: Compiler,
1065}
1066
1067impl Step for RustdocJSNotStd {
1068 type Output = ();
1069 const IS_HOST: bool = true;
1070
1071 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1072 run.suite_path("tests/rustdoc-js")
1073 }
1074
1075 fn is_default_step(builder: &Builder<'_>) -> bool {
1076 builder.config.nodejs.is_some()
1077 }
1078
1079 fn make_run(run: RunConfig<'_>) {
1080 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1081 run.builder.ensure(RustdocJSNotStd { target: run.target, compiler });
1082 }
1083
1084 fn run(self, builder: &Builder<'_>) {
1085 builder.ensure(Compiletest {
1086 test_compiler: self.compiler,
1087 target: self.target,
1088 mode: "rustdoc-js",
1089 suite: "rustdoc-js",
1090 path: "tests/rustdoc-js",
1091 compare_mode: None,
1092 });
1093 }
1094}
1095
1096fn get_browser_ui_test_version_inner(
1097 builder: &Builder<'_>,
1098 yarn: &Path,
1099 global: bool,
1100) -> Option<String> {
1101 let mut command = command(yarn);
1102 command
1103 .arg("--cwd")
1104 .arg(&builder.build.out)
1105 .arg("list")
1106 .arg("--parseable")
1107 .arg("--long")
1108 .arg("--depth=0");
1109 if global {
1110 command.arg("--global");
1111 }
1112 let lines = command.allow_failure().cached().run_capture(builder).stdout();
1115 lines
1116 .lines()
1117 .find_map(|l| l.split(':').nth(1)?.strip_prefix("browser-ui-test@"))
1118 .map(|v| v.to_owned())
1119}
1120
1121fn get_browser_ui_test_version(builder: &Builder<'_>) -> Option<String> {
1122 let yarn = builder.config.yarn.as_deref()?;
1123 get_browser_ui_test_version_inner(builder, yarn, false)
1124 .or_else(|| get_browser_ui_test_version_inner(builder, yarn, true))
1125}
1126
1127#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1129pub struct RustdocGUI {
1130 test_compiler: Compiler,
1132 target: TargetSelection,
1133}
1134
1135impl Step for RustdocGUI {
1136 type Output = ();
1137 const IS_HOST: bool = true;
1138
1139 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1140 run.suite_path("tests/rustdoc-gui")
1141 }
1142
1143 fn is_default_step(builder: &Builder<'_>) -> bool {
1144 builder.config.nodejs.is_some()
1145 && builder.doc_tests != DocTests::Only
1146 && get_browser_ui_test_version(builder).is_some()
1147 }
1148
1149 fn make_run(run: RunConfig<'_>) {
1150 let test_compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1151 run.builder.ensure(RustdocGUI { test_compiler, target: run.target });
1152 }
1153
1154 fn run(self, builder: &Builder<'_>) {
1155 builder.std(self.test_compiler, self.target);
1156
1157 let mut cmd = builder.tool_cmd(Tool::RustdocGUITest);
1158
1159 let out_dir = builder.test_out(self.target).join("rustdoc-gui");
1160 build_stamp::clear_if_dirty(
1161 builder,
1162 &out_dir,
1163 &builder.rustdoc_for_compiler(self.test_compiler),
1164 );
1165
1166 if let Some(src) = builder.config.src.to_str() {
1167 cmd.arg("--rust-src").arg(src);
1168 }
1169
1170 if let Some(out_dir) = out_dir.to_str() {
1171 cmd.arg("--out-dir").arg(out_dir);
1172 }
1173
1174 if let Some(initial_cargo) = builder.config.initial_cargo.to_str() {
1175 cmd.arg("--initial-cargo").arg(initial_cargo);
1176 }
1177
1178 cmd.arg("--jobs").arg(builder.jobs().to_string());
1179
1180 cmd.env("RUSTDOC", builder.rustdoc_for_compiler(self.test_compiler))
1181 .env("RUSTC", builder.rustc(self.test_compiler));
1182
1183 add_rustdoc_cargo_linker_args(&mut cmd, builder, self.test_compiler.host, LldThreads::No);
1184
1185 for path in &builder.paths {
1186 if let Some(p) = helpers::is_valid_test_suite_arg(path, "tests/rustdoc-gui", builder) {
1187 if !p.ends_with(".goml") {
1188 eprintln!("A non-goml file was given: `{}`", path.display());
1189 panic!("Cannot run rustdoc-gui tests");
1190 }
1191 if let Some(name) = path.file_name().and_then(|f| f.to_str()) {
1192 cmd.arg("--goml-file").arg(name);
1193 }
1194 }
1195 }
1196
1197 for test_arg in builder.config.test_args() {
1198 cmd.arg("--test-arg").arg(test_arg);
1199 }
1200
1201 if let Some(ref nodejs) = builder.config.nodejs {
1202 cmd.arg("--nodejs").arg(nodejs);
1203 }
1204
1205 if let Some(ref yarn) = builder.config.yarn {
1206 cmd.arg("--yarn").arg(yarn);
1207 }
1208
1209 let _time = helpers::timeit(builder);
1210 let _guard = builder.msg_test("rustdoc-gui", self.target, self.test_compiler.stage);
1211 try_run_tests(builder, &mut cmd, true);
1212 }
1213
1214 fn metadata(&self) -> Option<StepMetadata> {
1215 Some(StepMetadata::test("rustdoc-gui", self.target).stage(self.test_compiler.stage))
1216 }
1217}
1218
1219#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1224pub struct Tidy;
1225
1226impl Step for Tidy {
1227 type Output = ();
1228 const IS_HOST: bool = true;
1229
1230 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1231 run.path("src/tools/tidy")
1232 }
1233
1234 fn is_default_step(builder: &Builder<'_>) -> bool {
1235 builder.doc_tests != DocTests::Only
1236 }
1237
1238 fn make_run(run: RunConfig<'_>) {
1239 run.builder.ensure(Tidy);
1240 }
1241
1242 fn run(self, builder: &Builder<'_>) {
1251 let mut cmd = builder.tool_cmd(Tool::Tidy);
1252 cmd.arg(&builder.src);
1253 cmd.arg(&builder.initial_cargo);
1254 cmd.arg(&builder.out);
1255 let jobs = builder.config.jobs.unwrap_or_else(|| {
1257 8 * std::thread::available_parallelism().map_or(1, std::num::NonZeroUsize::get) as u32
1258 });
1259 cmd.arg(jobs.to_string());
1260 if let Some(yarn) = &builder.config.yarn {
1262 cmd.arg(yarn);
1263 } else {
1264 cmd.arg("yarn");
1265 }
1266 if builder.is_verbose() {
1267 cmd.arg("--verbose");
1268 }
1269 if builder.config.cmd.bless() {
1270 cmd.arg("--bless");
1271 }
1272 if let Some(s) =
1273 builder.config.cmd.extra_checks().or(builder.config.tidy_extra_checks.as_deref())
1274 {
1275 cmd.arg(format!("--extra-checks={s}"));
1276 }
1277 let mut args = std::env::args_os();
1278 if args.any(|arg| arg == OsStr::new("--")) {
1279 cmd.arg("--");
1280 cmd.args(args);
1281 }
1282
1283 if builder.config.channel == "dev" || builder.config.channel == "nightly" {
1284 if !builder.config.json_output {
1285 builder.info("fmt check");
1286 if builder.config.initial_rustfmt.is_none() {
1287 let inferred_rustfmt_dir = builder.initial_sysroot.join("bin");
1288 eprintln!(
1289 "\
1290ERROR: no `rustfmt` binary found in {PATH}
1291INFO: `rust.channel` is currently set to \"{CHAN}\"
1292HELP: if you are testing a beta branch, set `rust.channel` to \"beta\" in the `bootstrap.toml` file
1293HELP: to skip test's attempt to check tidiness, pass `--skip src/tools/tidy` to `x.py test`",
1294 PATH = inferred_rustfmt_dir.display(),
1295 CHAN = builder.config.channel,
1296 );
1297 crate::exit!(1);
1298 }
1299 let all = false;
1300 crate::core::build_steps::format::format(
1301 builder,
1302 !builder.config.cmd.bless(),
1303 all,
1304 &[],
1305 );
1306 } else {
1307 eprintln!(
1308 "WARNING: `--json-output` is not supported on rustfmt, formatting will be skipped"
1309 );
1310 }
1311 }
1312
1313 builder.info("tidy check");
1314 cmd.delay_failure().run(builder);
1315
1316 builder.info("x.py completions check");
1317 let completion_paths = get_completion_paths(builder);
1318 if builder.config.cmd.bless() {
1319 builder.ensure(crate::core::build_steps::run::GenerateCompletions);
1320 } else if completion_paths
1321 .into_iter()
1322 .any(|(shell, path)| get_completion(shell, &path).is_some())
1323 {
1324 eprintln!(
1325 "x.py completions were changed; run `x.py run generate-completions` to update them"
1326 );
1327 crate::exit!(1);
1328 }
1329
1330 builder.info("x.py help check");
1331 if builder.config.cmd.bless() {
1332 builder.ensure(crate::core::build_steps::run::GenerateHelp);
1333 } else {
1334 let help_path = get_help_path(builder);
1335 let cur_help = std::fs::read_to_string(&help_path).unwrap_or_else(|err| {
1336 eprintln!("couldn't read {}: {}", help_path.display(), err);
1337 crate::exit!(1);
1338 });
1339 let new_help = top_level_help();
1340
1341 if new_help != cur_help {
1342 eprintln!("x.py help was changed; run `x.py run generate-help` to update it");
1343 crate::exit!(1);
1344 }
1345 }
1346 }
1347
1348 fn metadata(&self) -> Option<StepMetadata> {
1349 Some(StepMetadata::test("tidy", TargetSelection::default()))
1350 }
1351}
1352
1353#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1356pub struct CrateRunMakeSupport {
1357 host: TargetSelection,
1358}
1359
1360impl Step for CrateRunMakeSupport {
1361 type Output = ();
1362 const IS_HOST: bool = true;
1363
1364 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1365 run.path("src/tools/run-make-support")
1366 }
1367
1368 fn make_run(run: RunConfig<'_>) {
1369 run.builder.ensure(CrateRunMakeSupport { host: run.target });
1370 }
1371
1372 fn run(self, builder: &Builder<'_>) {
1374 let host = self.host;
1375 let compiler = builder.compiler(0, host);
1376
1377 let mut cargo = tool::prepare_tool_cargo(
1378 builder,
1379 compiler,
1380 Mode::ToolBootstrap,
1381 host,
1382 Kind::Test,
1383 "src/tools/run-make-support",
1384 SourceType::InTree,
1385 &[],
1386 );
1387 cargo.allow_features("test");
1388 run_cargo_test(cargo, &[], &[], "run-make-support self test", host, builder);
1389 }
1390}
1391
1392#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1393pub struct CrateBuildHelper {
1394 host: TargetSelection,
1395}
1396
1397impl Step for CrateBuildHelper {
1398 type Output = ();
1399 const IS_HOST: bool = true;
1400
1401 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1402 run.path("src/build_helper")
1403 }
1404
1405 fn make_run(run: RunConfig<'_>) {
1406 run.builder.ensure(CrateBuildHelper { host: run.target });
1407 }
1408
1409 fn run(self, builder: &Builder<'_>) {
1411 let host = self.host;
1412 let compiler = builder.compiler(0, host);
1413
1414 let mut cargo = tool::prepare_tool_cargo(
1415 builder,
1416 compiler,
1417 Mode::ToolBootstrap,
1418 host,
1419 Kind::Test,
1420 "src/build_helper",
1421 SourceType::InTree,
1422 &[],
1423 );
1424 cargo.allow_features("test");
1425 run_cargo_test(cargo, &[], &[], "build_helper self test", host, builder);
1426 }
1427}
1428
1429fn testdir(builder: &Builder<'_>, host: TargetSelection) -> PathBuf {
1430 builder.out.join(host).join("test")
1431}
1432
1433macro_rules! test {
1435 (
1436 $( #[$attr:meta] )* $name:ident {
1438 path: $path:expr,
1439 mode: $mode:expr,
1440 suite: $suite:expr,
1441 default: $default:expr
1442 $( , IS_HOST: $IS_HOST:expr )? $( , compare_mode: $compare_mode:expr )? $( , )? }
1446 ) => {
1447 $( #[$attr] )*
1448 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
1449 pub struct $name {
1450 test_compiler: Compiler,
1451 target: TargetSelection,
1452 }
1453
1454 impl Step for $name {
1455 type Output = ();
1456 const IS_HOST: bool = (const {
1457 #[allow(unused_assignments, unused_mut)]
1458 let mut value = false;
1459 $( value = $IS_HOST; )?
1460 value
1461 });
1462
1463 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1464 run.suite_path($path)
1465 }
1466
1467 fn is_default_step(_builder: &Builder<'_>) -> bool {
1468 const { $default }
1469 }
1470
1471 fn make_run(run: RunConfig<'_>) {
1472 let test_compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1473
1474 run.builder.ensure($name { test_compiler, target: run.target });
1475 }
1476
1477 fn run(self, builder: &Builder<'_>) {
1478 builder.ensure(Compiletest {
1479 test_compiler: self.test_compiler,
1480 target: self.target,
1481 mode: $mode,
1482 suite: $suite,
1483 path: $path,
1484 compare_mode: (const {
1485 #[allow(unused_assignments, unused_mut)]
1486 let mut value = None;
1487 $( value = $compare_mode; )?
1488 value
1489 }),
1490 })
1491 }
1492 }
1493 };
1494}
1495
1496test!(Ui { path: "tests/ui", mode: "ui", suite: "ui", default: true });
1497
1498test!(Crashes { path: "tests/crashes", mode: "crashes", suite: "crashes", default: true });
1499
1500test!(CodegenLlvm {
1501 path: "tests/codegen-llvm",
1502 mode: "codegen",
1503 suite: "codegen-llvm",
1504 default: true
1505});
1506
1507test!(CodegenUnits {
1508 path: "tests/codegen-units",
1509 mode: "codegen-units",
1510 suite: "codegen-units",
1511 default: true,
1512});
1513
1514test!(Incremental {
1515 path: "tests/incremental",
1516 mode: "incremental",
1517 suite: "incremental",
1518 default: true,
1519});
1520
1521test!(Debuginfo {
1522 path: "tests/debuginfo",
1523 mode: "debuginfo",
1524 suite: "debuginfo",
1525 default: true,
1526 compare_mode: Some("split-dwarf"),
1527});
1528
1529test!(UiFullDeps {
1530 path: "tests/ui-fulldeps",
1531 mode: "ui",
1532 suite: "ui-fulldeps",
1533 default: true,
1534 IS_HOST: true,
1535});
1536
1537test!(Rustdoc {
1538 path: "tests/rustdoc",
1539 mode: "rustdoc",
1540 suite: "rustdoc",
1541 default: true,
1542 IS_HOST: true,
1543});
1544test!(RustdocUi {
1545 path: "tests/rustdoc-ui",
1546 mode: "ui",
1547 suite: "rustdoc-ui",
1548 default: true,
1549 IS_HOST: true,
1550});
1551
1552test!(RustdocJson {
1553 path: "tests/rustdoc-json",
1554 mode: "rustdoc-json",
1555 suite: "rustdoc-json",
1556 default: true,
1557 IS_HOST: true,
1558});
1559
1560test!(Pretty {
1561 path: "tests/pretty",
1562 mode: "pretty",
1563 suite: "pretty",
1564 default: true,
1565 IS_HOST: true,
1566});
1567
1568test!(RunMake { path: "tests/run-make", mode: "run-make", suite: "run-make", default: true });
1569test!(RunMakeCargo {
1570 path: "tests/run-make-cargo",
1571 mode: "run-make",
1572 suite: "run-make-cargo",
1573 default: true
1574});
1575
1576test!(AssemblyLlvm {
1577 path: "tests/assembly-llvm",
1578 mode: "assembly",
1579 suite: "assembly-llvm",
1580 default: true
1581});
1582
1583#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
1586pub struct Coverage {
1587 pub compiler: Compiler,
1588 pub target: TargetSelection,
1589 pub mode: &'static str,
1590}
1591
1592impl Coverage {
1593 const PATH: &'static str = "tests/coverage";
1594 const SUITE: &'static str = "coverage";
1595 const ALL_MODES: &[&str] = &["coverage-map", "coverage-run"];
1596}
1597
1598impl Step for Coverage {
1599 type Output = ();
1600 const IS_HOST: bool = false;
1602
1603 fn should_run(mut run: ShouldRun<'_>) -> ShouldRun<'_> {
1604 run = run.suite_path(Self::PATH);
1610 for mode in Self::ALL_MODES {
1611 run = run.alias(mode);
1612 }
1613 run
1614 }
1615
1616 fn is_default_step(_builder: &Builder<'_>) -> bool {
1617 true
1618 }
1619
1620 fn make_run(run: RunConfig<'_>) {
1621 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1622 let target = run.target;
1623
1624 let mut modes = vec![];
1628
1629 for path in &run.paths {
1632 match path {
1633 PathSet::Set(_) => {
1634 for mode in Self::ALL_MODES {
1635 if path.assert_single_path().path == Path::new(mode) {
1636 modes.push(mode);
1637 break;
1638 }
1639 }
1640 }
1641 PathSet::Suite(_) => {
1642 modes.extend(Self::ALL_MODES);
1643 break;
1644 }
1645 }
1646 }
1647
1648 modes.retain(|mode| !run.builder.config.skip.iter().any(|skip| skip == Path::new(mode)));
1651
1652 for mode in modes {
1660 run.builder.ensure(Coverage { compiler, target, mode });
1661 }
1662 }
1663
1664 fn run(self, builder: &Builder<'_>) {
1665 let Self { compiler, target, mode } = self;
1666 builder.ensure(Compiletest {
1669 test_compiler: compiler,
1670 target,
1671 mode,
1672 suite: Self::SUITE,
1673 path: Self::PATH,
1674 compare_mode: None,
1675 });
1676 }
1677}
1678
1679test!(CoverageRunRustdoc {
1680 path: "tests/coverage-run-rustdoc",
1681 mode: "coverage-run",
1682 suite: "coverage-run-rustdoc",
1683 default: true,
1684 IS_HOST: true,
1685});
1686
1687#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1689pub struct MirOpt {
1690 pub compiler: Compiler,
1691 pub target: TargetSelection,
1692}
1693
1694impl Step for MirOpt {
1695 type Output = ();
1696
1697 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1698 run.suite_path("tests/mir-opt")
1699 }
1700
1701 fn is_default_step(_builder: &Builder<'_>) -> bool {
1702 true
1703 }
1704
1705 fn make_run(run: RunConfig<'_>) {
1706 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1707 run.builder.ensure(MirOpt { compiler, target: run.target });
1708 }
1709
1710 fn run(self, builder: &Builder<'_>) {
1711 let run = |target| {
1712 builder.ensure(Compiletest {
1713 test_compiler: self.compiler,
1714 target,
1715 mode: "mir-opt",
1716 suite: "mir-opt",
1717 path: "tests/mir-opt",
1718 compare_mode: None,
1719 })
1720 };
1721
1722 run(self.target);
1723
1724 if builder.config.cmd.bless() {
1727 for target in ["aarch64-unknown-linux-gnu", "i686-pc-windows-msvc"] {
1733 run(TargetSelection::from_user(target));
1734 }
1735
1736 for target in ["x86_64-apple-darwin", "i686-unknown-linux-musl"] {
1737 let target = TargetSelection::from_user(target);
1738 let panic_abort_target = builder.ensure(MirOptPanicAbortSyntheticTarget {
1739 compiler: self.compiler,
1740 base: target,
1741 });
1742 run(panic_abort_target);
1743 }
1744 }
1745 }
1746}
1747
1748#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1754struct Compiletest {
1755 test_compiler: Compiler,
1757 target: TargetSelection,
1758 mode: &'static str,
1759 suite: &'static str,
1760 path: &'static str,
1761 compare_mode: Option<&'static str>,
1762}
1763
1764impl Step for Compiletest {
1765 type Output = ();
1766
1767 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1768 run.never()
1769 }
1770
1771 fn run(self, builder: &Builder<'_>) {
1772 if builder.doc_tests == DocTests::Only {
1773 return;
1774 }
1775
1776 if builder.top_stage == 0 && !builder.config.compiletest_allow_stage0 {
1777 eprintln!("\
1778ERROR: `--stage 0` runs compiletest on the stage0 (precompiled) compiler, not your local changes, and will almost always cause tests to fail
1779HELP: to test the compiler or standard library, omit the stage or explicitly use `--stage 1` instead
1780NOTE: 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`."
1781 );
1782 crate::exit!(1);
1783 }
1784
1785 let mut test_compiler = self.test_compiler;
1786 let target = self.target;
1787 let mode = self.mode;
1788 let suite = self.suite;
1789
1790 let suite_path = self.path;
1792
1793 if !builder.config.codegen_tests && mode == "codegen" {
1795 return;
1796 }
1797
1798 let query_compiler;
1805 let (stage, stage_id) = if suite == "ui-fulldeps" && test_compiler.stage == 1 {
1806 query_compiler = Some(test_compiler);
1809 let build = builder.build.host_target;
1813 test_compiler = builder.compiler(test_compiler.stage - 1, build);
1814 let test_stage = test_compiler.stage + 1;
1815 (test_stage, format!("stage{test_stage}-{build}"))
1816 } else {
1817 query_compiler = None;
1818 let stage = test_compiler.stage;
1819 (stage, format!("stage{stage}-{target}"))
1820 };
1821
1822 if suite.ends_with("fulldeps") {
1823 builder.ensure(compile::Rustc::new(test_compiler, target));
1824 }
1825
1826 if suite == "debuginfo" {
1827 builder.ensure(dist::DebuggerScripts {
1828 sysroot: builder.sysroot(test_compiler).to_path_buf(),
1829 target,
1830 });
1831 }
1832 if mode == "run-make" {
1833 builder.tool_exe(Tool::RunMakeSupport);
1834 }
1835
1836 if suite == "mir-opt" {
1838 builder.ensure(
1839 compile::Std::new(test_compiler, test_compiler.host).is_for_mir_opt_tests(true),
1840 );
1841 } else {
1842 builder.std(test_compiler, test_compiler.host);
1843 }
1844
1845 let mut cmd = builder.tool_cmd(Tool::Compiletest);
1846
1847 if suite == "mir-opt" {
1848 builder.ensure(compile::Std::new(test_compiler, target).is_for_mir_opt_tests(true));
1849 } else {
1850 builder.std(test_compiler, target);
1851 }
1852
1853 builder.ensure(RemoteCopyLibs { build_compiler: test_compiler, target });
1854
1855 cmd.arg("--stage").arg(stage.to_string());
1859 cmd.arg("--stage-id").arg(stage_id);
1860
1861 cmd.arg("--compile-lib-path").arg(builder.rustc_libdir(test_compiler));
1862 cmd.arg("--run-lib-path").arg(builder.sysroot_target_libdir(test_compiler, target));
1863 cmd.arg("--rustc-path").arg(builder.rustc(test_compiler));
1864 if let Some(query_compiler) = query_compiler {
1865 cmd.arg("--query-rustc-path").arg(builder.rustc(query_compiler));
1866 }
1867
1868 cmd.arg("--minicore-path")
1871 .arg(builder.src.join("tests").join("auxiliary").join("minicore.rs"));
1872
1873 let is_rustdoc = suite == "rustdoc-ui" || suite == "rustdoc-js";
1874
1875 if mode == "run-make" {
1890 let stage0_rustc_path = builder.compiler(0, test_compiler.host);
1893 cmd.arg("--stage0-rustc-path").arg(builder.rustc(stage0_rustc_path));
1894
1895 if suite == "run-make-cargo" {
1896 let cargo_path = if test_compiler.stage == 0 {
1897 builder.initial_cargo.clone()
1899 } else {
1900 builder
1901 .ensure(tool::Cargo::from_build_compiler(
1902 builder.compiler(test_compiler.stage - 1, test_compiler.host),
1903 test_compiler.host,
1904 ))
1905 .tool_path
1906 };
1907
1908 cmd.arg("--cargo-path").arg(cargo_path);
1909 }
1910 }
1911
1912 if mode == "rustdoc"
1914 || mode == "run-make"
1915 || (mode == "ui" && is_rustdoc)
1916 || mode == "rustdoc-js"
1917 || mode == "rustdoc-json"
1918 || suite == "coverage-run-rustdoc"
1919 {
1920 cmd.arg("--rustdoc-path").arg(builder.rustdoc_for_compiler(test_compiler));
1921 }
1922
1923 if mode == "rustdoc-json" {
1924 let json_compiler = builder.compiler(0, builder.host_target);
1926 cmd.arg("--jsondocck-path")
1927 .arg(builder.ensure(tool::JsonDocCk { compiler: json_compiler, target }).tool_path);
1928 cmd.arg("--jsondoclint-path").arg(
1929 builder.ensure(tool::JsonDocLint { compiler: json_compiler, target }).tool_path,
1930 );
1931 }
1932
1933 if matches!(mode, "coverage-map" | "coverage-run") {
1934 let coverage_dump = builder.tool_exe(Tool::CoverageDump);
1935 cmd.arg("--coverage-dump-path").arg(coverage_dump);
1936 }
1937
1938 cmd.arg("--src-root").arg(&builder.src);
1939 cmd.arg("--src-test-suite-root").arg(builder.src.join("tests").join(suite));
1940
1941 cmd.arg("--build-root").arg(&builder.out);
1945 cmd.arg("--build-test-suite-root").arg(testdir(builder, test_compiler.host).join(suite));
1946
1947 let sysroot = if builder.top_stage == 0 {
1952 builder.initial_sysroot.clone()
1953 } else {
1954 builder.sysroot(test_compiler)
1955 };
1956
1957 cmd.arg("--sysroot-base").arg(sysroot);
1958
1959 cmd.arg("--suite").arg(suite);
1960 cmd.arg("--mode").arg(mode);
1961 cmd.arg("--target").arg(target.rustc_target_arg());
1962 cmd.arg("--host").arg(&*test_compiler.host.triple);
1963 cmd.arg("--llvm-filecheck").arg(builder.llvm_filecheck(builder.config.host_target));
1964
1965 if let Some(codegen_backend) = builder.config.cmd.test_codegen_backend() {
1966 if !builder
1967 .config
1968 .enabled_codegen_backends(test_compiler.host)
1969 .contains(codegen_backend)
1970 {
1971 eprintln!(
1972 "\
1973ERROR: No configured backend named `{name}`
1974HELP: You can add it into `bootstrap.toml` in `rust.codegen-backends = [{name:?}]`",
1975 name = codegen_backend.name(),
1976 );
1977 crate::exit!(1);
1978 }
1979
1980 if let CodegenBackendKind::Gcc = codegen_backend
1981 && builder.config.rustc_debug_assertions
1982 {
1983 eprintln!(
1984 r#"WARNING: Running tests with the GCC codegen backend while rustc debug assertions are enabled. This might lead to test failures.
1985Please disable assertions with `rust.debug-assertions = false`.
1986 "#
1987 );
1988 }
1989
1990 cmd.arg("--override-codegen-backend").arg(codegen_backend.name());
1993 cmd.arg("--default-codegen-backend").arg(codegen_backend.name());
1996 } else {
1997 cmd.arg("--default-codegen-backend")
2000 .arg(builder.config.default_codegen_backend(test_compiler.host).name());
2001 }
2002 if builder.config.cmd.bypass_ignore_backends() {
2003 cmd.arg("--bypass-ignore-backends");
2004 }
2005
2006 if builder.build.config.llvm_enzyme {
2007 cmd.arg("--has-enzyme");
2008 }
2009
2010 if builder.config.cmd.bless() {
2011 cmd.arg("--bless");
2012 }
2013
2014 if builder.config.cmd.force_rerun() {
2015 cmd.arg("--force-rerun");
2016 }
2017
2018 if builder.config.cmd.no_capture() {
2019 cmd.arg("--no-capture");
2020 }
2021
2022 let compare_mode =
2023 builder.config.cmd.compare_mode().or_else(|| {
2024 if builder.config.test_compare_mode { self.compare_mode } else { None }
2025 });
2026
2027 if let Some(ref pass) = builder.config.cmd.pass() {
2028 cmd.arg("--pass");
2029 cmd.arg(pass);
2030 }
2031
2032 if let Some(ref run) = builder.config.cmd.run() {
2033 cmd.arg("--run");
2034 cmd.arg(run);
2035 }
2036
2037 if let Some(ref nodejs) = builder.config.nodejs {
2038 cmd.arg("--nodejs").arg(nodejs);
2039 } else if mode == "rustdoc-js" {
2040 panic!("need nodejs to run rustdoc-js suite");
2041 }
2042 if builder.config.rust_optimize_tests {
2043 cmd.arg("--optimize-tests");
2044 }
2045 if builder.config.rust_randomize_layout {
2046 cmd.arg("--rust-randomized-layout");
2047 }
2048 if builder.config.cmd.only_modified() {
2049 cmd.arg("--only-modified");
2050 }
2051 if let Some(compiletest_diff_tool) = &builder.config.compiletest_diff_tool {
2052 cmd.arg("--compiletest-diff-tool").arg(compiletest_diff_tool);
2053 }
2054
2055 let mut flags = if is_rustdoc { Vec::new() } else { vec!["-Crpath".to_string()] };
2056 flags.push(format!(
2057 "-Cdebuginfo={}",
2058 if mode == "codegen" {
2059 if builder.config.rust_debuginfo_level_tests
2062 != crate::core::config::DebuginfoLevel::None
2063 {
2064 println!(
2065 "NOTE: ignoring `rust.debuginfo-level-tests={}` for codegen tests",
2066 builder.config.rust_debuginfo_level_tests
2067 );
2068 }
2069 crate::core::config::DebuginfoLevel::None
2070 } else {
2071 builder.config.rust_debuginfo_level_tests
2072 }
2073 ));
2074 flags.extend(builder.config.cmd.compiletest_rustc_args().iter().map(|s| s.to_string()));
2075
2076 if suite != "mir-opt" {
2077 if let Some(linker) = builder.linker(target) {
2078 cmd.arg("--target-linker").arg(linker);
2079 }
2080 if let Some(linker) = builder.linker(test_compiler.host) {
2081 cmd.arg("--host-linker").arg(linker);
2082 }
2083 }
2084
2085 if suite == "ui-fulldeps" && target.ends_with("darwin") {
2087 flags.push("-Alinker_messages".into());
2088 }
2089
2090 let mut hostflags = flags.clone();
2091 hostflags.extend(linker_flags(builder, test_compiler.host, LldThreads::No));
2092
2093 let mut targetflags = flags;
2094
2095 if suite == "ui" || suite == "incremental" {
2097 builder.ensure(TestHelpers { target: test_compiler.host });
2098 builder.ensure(TestHelpers { target });
2099 hostflags.push(format!(
2100 "-Lnative={}",
2101 builder.test_helpers_out(test_compiler.host).display()
2102 ));
2103 targetflags.push(format!("-Lnative={}", builder.test_helpers_out(target).display()));
2104 }
2105
2106 for flag in hostflags {
2107 cmd.arg("--host-rustcflags").arg(flag);
2108 }
2109 for flag in targetflags {
2110 cmd.arg("--target-rustcflags").arg(flag);
2111 }
2112
2113 cmd.arg("--python").arg(
2114 builder.config.python.as_ref().expect("python is required for running rustdoc tests"),
2115 );
2116
2117 if let Some(debuggers::Android { adb_path, adb_test_dir, android_cross_path }) =
2122 debuggers::discover_android(builder, target)
2123 {
2124 cmd.arg("--adb-path").arg(adb_path);
2125 cmd.arg("--adb-test-dir").arg(adb_test_dir);
2126 cmd.arg("--android-cross-path").arg(android_cross_path);
2127 }
2128
2129 if mode == "debuginfo" {
2130 if let Some(debuggers::Gdb { gdb }) = debuggers::discover_gdb(builder) {
2131 cmd.arg("--gdb").arg(gdb);
2132 }
2133
2134 if let Some(debuggers::Lldb { lldb_exe, lldb_version }) =
2135 debuggers::discover_lldb(builder)
2136 {
2137 cmd.arg("--lldb").arg(lldb_exe);
2138 cmd.arg("--lldb-version").arg(lldb_version);
2139 }
2140 }
2141
2142 if helpers::forcing_clang_based_tests() {
2143 let clang_exe = builder.llvm_out(target).join("bin").join("clang");
2144 cmd.arg("--run-clang-based-tests-with").arg(clang_exe);
2145 }
2146
2147 for exclude in &builder.config.skip {
2148 cmd.arg("--skip");
2149 cmd.arg(exclude);
2150 }
2151
2152 let mut paths = match &builder.config.cmd {
2154 Subcommand::Test { .. } => &builder.config.paths[..],
2155 _ => &[],
2156 };
2157
2158 let mut paths_v;
2161 if mode == "rustdoc-js" {
2162 paths_v = paths.to_vec();
2163 for p in &mut paths_v {
2164 if let Some(ext) = p.extension()
2165 && ext == "js"
2166 {
2167 p.set_extension("rs");
2168 }
2169 }
2170 paths = &paths_v;
2171 }
2172 let mut test_args: Vec<&str> = paths
2174 .iter()
2175 .filter_map(|p| helpers::is_valid_test_suite_arg(p, suite_path, builder))
2176 .collect();
2177
2178 test_args.append(&mut builder.config.test_args());
2179
2180 if cfg!(windows) {
2183 let test_args_win: Vec<String> =
2184 test_args.iter().map(|s| s.replace('/', "\\")).collect();
2185 cmd.args(&test_args_win);
2186 } else {
2187 cmd.args(&test_args);
2188 }
2189
2190 if builder.is_verbose() {
2191 cmd.arg("--verbose");
2192 }
2193
2194 if builder.config.rustc_debug_assertions {
2195 cmd.arg("--with-rustc-debug-assertions");
2196 }
2197
2198 if builder.config.std_debug_assertions {
2199 cmd.arg("--with-std-debug-assertions");
2200 }
2201
2202 let mut llvm_components_passed = false;
2203 let mut copts_passed = false;
2204 if builder.config.llvm_enabled(test_compiler.host) {
2205 let llvm::LlvmResult { host_llvm_config, .. } =
2206 builder.ensure(llvm::Llvm { target: builder.config.host_target });
2207 if !builder.config.dry_run() {
2208 let llvm_version = get_llvm_version(builder, &host_llvm_config);
2209 let llvm_components = command(&host_llvm_config)
2210 .cached()
2211 .arg("--components")
2212 .run_capture_stdout(builder)
2213 .stdout();
2214 cmd.arg("--llvm-version")
2216 .arg(llvm_version.trim())
2217 .arg("--llvm-components")
2218 .arg(llvm_components.trim());
2219 llvm_components_passed = true;
2220 }
2221 if !builder.config.is_rust_llvm(target) {
2222 cmd.arg("--system-llvm");
2223 }
2224
2225 if !builder.config.dry_run() && suite.ends_with("fulldeps") {
2230 let llvm_libdir = command(&host_llvm_config)
2231 .cached()
2232 .arg("--libdir")
2233 .run_capture_stdout(builder)
2234 .stdout();
2235 let link_llvm = if target.is_msvc() {
2236 format!("-Clink-arg=-LIBPATH:{llvm_libdir}")
2237 } else {
2238 format!("-Clink-arg=-L{llvm_libdir}")
2239 };
2240 cmd.arg("--host-rustcflags").arg(link_llvm);
2241 }
2242
2243 if !builder.config.dry_run() && matches!(mode, "run-make" | "coverage-run") {
2244 let llvm_bin_path = host_llvm_config
2249 .parent()
2250 .expect("Expected llvm-config to be contained in directory");
2251 assert!(llvm_bin_path.is_dir());
2252 cmd.arg("--llvm-bin-dir").arg(llvm_bin_path);
2253 }
2254
2255 if !builder.config.dry_run() && mode == "run-make" {
2256 if builder.config.lld_enabled {
2258 let lld_install_root =
2259 builder.ensure(llvm::Lld { target: builder.config.host_target });
2260
2261 let lld_bin_path = lld_install_root.join("bin");
2262
2263 let old_path = env::var_os("PATH").unwrap_or_default();
2264 let new_path = env::join_paths(
2265 std::iter::once(lld_bin_path).chain(env::split_paths(&old_path)),
2266 )
2267 .expect("Could not add LLD bin path to PATH");
2268 cmd.env("PATH", new_path);
2269 }
2270 }
2271 }
2272
2273 if !builder.config.dry_run() && mode == "run-make" {
2276 let mut cflags = builder.cc_handled_clags(target, CLang::C);
2277 cflags.extend(builder.cc_unhandled_cflags(target, GitRepo::Rustc, CLang::C));
2278 let mut cxxflags = builder.cc_handled_clags(target, CLang::Cxx);
2279 cxxflags.extend(builder.cc_unhandled_cflags(target, GitRepo::Rustc, CLang::Cxx));
2280 cmd.arg("--cc")
2281 .arg(builder.cc(target))
2282 .arg("--cxx")
2283 .arg(builder.cxx(target).unwrap())
2284 .arg("--cflags")
2285 .arg(cflags.join(" "))
2286 .arg("--cxxflags")
2287 .arg(cxxflags.join(" "));
2288 copts_passed = true;
2289 if let Some(ar) = builder.ar(target) {
2290 cmd.arg("--ar").arg(ar);
2291 }
2292 }
2293
2294 if !llvm_components_passed {
2295 cmd.arg("--llvm-components").arg("");
2296 }
2297 if !copts_passed {
2298 cmd.arg("--cc")
2299 .arg("")
2300 .arg("--cxx")
2301 .arg("")
2302 .arg("--cflags")
2303 .arg("")
2304 .arg("--cxxflags")
2305 .arg("");
2306 }
2307
2308 if builder.remote_tested(target) {
2309 cmd.arg("--remote-test-client").arg(builder.tool_exe(Tool::RemoteTestClient));
2310 } else if let Some(tool) = builder.runner(target) {
2311 cmd.arg("--runner").arg(tool);
2312 }
2313
2314 if suite != "mir-opt" {
2315 if !builder.config.dry_run() && target.is_msvc() {
2321 for (k, v) in builder.cc[&target].env() {
2322 if k != "PATH" {
2323 cmd.env(k, v);
2324 }
2325 }
2326 }
2327 }
2328
2329 if !builder.config.dry_run()
2331 && target.contains("msvc")
2332 && builder.config.sanitizers_enabled(target)
2333 {
2334 cmd.env("ASAN_WIN_CONTINUE_ON_INTERCEPTION_FAILURE", "1");
2337 let asan_runtime_path = builder.cc[&target].path().parent().unwrap().to_path_buf();
2339 let old_path = cmd
2340 .get_envs()
2341 .find_map(|(k, v)| (k == "PATH").then_some(v))
2342 .flatten()
2343 .map_or_else(|| env::var_os("PATH").unwrap_or_default(), |v| v.to_owned());
2344 let new_path = env::join_paths(
2345 env::split_paths(&old_path).chain(std::iter::once(asan_runtime_path)),
2346 )
2347 .expect("Could not add ASAN runtime path to PATH");
2348 cmd.env("PATH", new_path);
2349 }
2350
2351 cmd.env_remove("CARGO");
2354
2355 cmd.env("RUSTC_BOOTSTRAP", "1");
2356 cmd.env("RUSTC_FORCE_RUSTC_VERSION", "compiletest");
2359 cmd.env("DOC_RUST_LANG_ORG_CHANNEL", builder.doc_rust_lang_org_channel());
2360 builder.add_rust_test_threads(&mut cmd);
2361
2362 if builder.config.sanitizers_enabled(target) {
2363 cmd.env("RUSTC_SANITIZER_SUPPORT", "1");
2364 }
2365
2366 if builder.config.profiler_enabled(target) {
2367 cmd.arg("--profiler-runtime");
2368 }
2369
2370 cmd.env("RUST_TEST_TMPDIR", builder.tempdir());
2371
2372 if builder.config.cmd.rustfix_coverage() {
2373 cmd.arg("--rustfix-coverage");
2374 }
2375
2376 cmd.arg("--channel").arg(&builder.config.channel);
2377
2378 if !builder.config.omit_git_hash {
2379 cmd.arg("--git-hash");
2380 }
2381
2382 let git_config = builder.config.git_config();
2383 cmd.arg("--nightly-branch").arg(git_config.nightly_branch);
2384 cmd.arg("--git-merge-commit-email").arg(git_config.git_merge_commit_email);
2385 cmd.force_coloring_in_ci();
2386
2387 #[cfg(feature = "build-metrics")]
2388 builder.metrics.begin_test_suite(
2389 build_helper::metrics::TestSuiteMetadata::Compiletest {
2390 suite: suite.into(),
2391 mode: mode.into(),
2392 compare_mode: None,
2393 target: self.target.triple.to_string(),
2394 host: self.test_compiler.host.triple.to_string(),
2395 stage: self.test_compiler.stage,
2396 },
2397 builder,
2398 );
2399
2400 let _group = builder.msg_test(
2401 format!("with compiletest suite={suite} mode={mode}"),
2402 target,
2403 test_compiler.stage,
2404 );
2405 try_run_tests(builder, &mut cmd, false);
2406
2407 if let Some(compare_mode) = compare_mode {
2408 cmd.arg("--compare-mode").arg(compare_mode);
2409
2410 #[cfg(feature = "build-metrics")]
2411 builder.metrics.begin_test_suite(
2412 build_helper::metrics::TestSuiteMetadata::Compiletest {
2413 suite: suite.into(),
2414 mode: mode.into(),
2415 compare_mode: Some(compare_mode.into()),
2416 target: self.target.triple.to_string(),
2417 host: self.test_compiler.host.triple.to_string(),
2418 stage: self.test_compiler.stage,
2419 },
2420 builder,
2421 );
2422
2423 builder.info(&format!(
2424 "Check compiletest suite={} mode={} compare_mode={} ({} -> {})",
2425 suite, mode, compare_mode, &test_compiler.host, target
2426 ));
2427 let _time = helpers::timeit(builder);
2428 try_run_tests(builder, &mut cmd, false);
2429 }
2430 }
2431
2432 fn metadata(&self) -> Option<StepMetadata> {
2433 Some(
2434 StepMetadata::test(&format!("compiletest-{}", self.suite), self.target)
2435 .stage(self.test_compiler.stage),
2436 )
2437 }
2438}
2439
2440#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2442struct BookTest {
2443 test_compiler: Compiler,
2444 path: PathBuf,
2445 name: &'static str,
2446 is_ext_doc: bool,
2447 dependencies: Vec<&'static str>,
2448}
2449
2450impl Step for BookTest {
2451 type Output = ();
2452 const IS_HOST: bool = true;
2453
2454 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2455 run.never()
2456 }
2457
2458 fn run(self, builder: &Builder<'_>) {
2459 if self.is_ext_doc {
2469 self.run_ext_doc(builder);
2470 } else {
2471 self.run_local_doc(builder);
2472 }
2473 }
2474}
2475
2476impl BookTest {
2477 fn run_ext_doc(self, builder: &Builder<'_>) {
2480 let test_compiler = self.test_compiler;
2481
2482 builder.std(test_compiler, test_compiler.host);
2483
2484 let mut rustdoc_path = builder.rustdoc_for_compiler(test_compiler);
2487 rustdoc_path.pop();
2488 let old_path = env::var_os("PATH").unwrap_or_default();
2489 let new_path = env::join_paths(iter::once(rustdoc_path).chain(env::split_paths(&old_path)))
2490 .expect("could not add rustdoc to PATH");
2491
2492 let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook);
2493 let path = builder.src.join(&self.path);
2494 rustbook_cmd.env("RUSTC_BOOTSTRAP", "1");
2496 rustbook_cmd.env("PATH", new_path).arg("test").arg(path);
2497
2498 let libs = if !self.dependencies.is_empty() {
2503 let mut lib_paths = vec![];
2504 for dep in self.dependencies {
2505 let mode = Mode::ToolRustcPrivate;
2506 let target = builder.config.host_target;
2507 let cargo = tool::prepare_tool_cargo(
2508 builder,
2509 test_compiler,
2510 mode,
2511 target,
2512 Kind::Build,
2513 dep,
2514 SourceType::Submodule,
2515 &[],
2516 );
2517
2518 let stamp = BuildStamp::new(&builder.cargo_out(test_compiler, mode, target))
2519 .with_prefix(PathBuf::from(dep).file_name().and_then(|v| v.to_str()).unwrap());
2520
2521 let output_paths = run_cargo(builder, cargo, vec![], &stamp, vec![], false, false);
2522 let directories = output_paths
2523 .into_iter()
2524 .filter_map(|p| p.parent().map(ToOwned::to_owned))
2525 .fold(HashSet::new(), |mut set, dir| {
2526 set.insert(dir);
2527 set
2528 });
2529
2530 lib_paths.extend(directories);
2531 }
2532 lib_paths
2533 } else {
2534 vec![]
2535 };
2536
2537 if !libs.is_empty() {
2538 let paths = libs
2539 .into_iter()
2540 .map(|path| path.into_os_string())
2541 .collect::<Vec<OsString>>()
2542 .join(OsStr::new(","));
2543 rustbook_cmd.args([OsString::from("--library-path"), paths]);
2544 }
2545
2546 builder.add_rust_test_threads(&mut rustbook_cmd);
2547 let _guard = builder.msg_test(
2548 format_args!("mdbook {}", self.path.display()),
2549 test_compiler.host,
2550 test_compiler.stage,
2551 );
2552 let _time = helpers::timeit(builder);
2553 let toolstate = if rustbook_cmd.delay_failure().run(builder) {
2554 ToolState::TestPass
2555 } else {
2556 ToolState::TestFail
2557 };
2558 builder.save_toolstate(self.name, toolstate);
2559 }
2560
2561 fn run_local_doc(self, builder: &Builder<'_>) {
2563 let test_compiler = self.test_compiler;
2564 let host = self.test_compiler.host;
2565
2566 builder.std(test_compiler, host);
2567
2568 let _guard = builder.msg_test(
2569 format!("book {}", self.name),
2570 test_compiler.host,
2571 test_compiler.stage,
2572 );
2573
2574 let mut stack = vec![builder.src.join(self.path)];
2577 let _time = helpers::timeit(builder);
2578 let mut files = Vec::new();
2579 while let Some(p) = stack.pop() {
2580 if p.is_dir() {
2581 stack.extend(t!(p.read_dir()).map(|p| t!(p).path()));
2582 continue;
2583 }
2584
2585 if p.extension().and_then(|s| s.to_str()) != Some("md") {
2586 continue;
2587 }
2588
2589 files.push(p);
2590 }
2591
2592 files.sort();
2593
2594 for file in files {
2595 markdown_test(builder, test_compiler, &file);
2596 }
2597 }
2598}
2599
2600macro_rules! test_book {
2601 ($(
2602 $name:ident, $path:expr, $book_name:expr,
2603 default=$default:expr
2604 $(,submodules = $submodules:expr)?
2605 $(,dependencies=$dependencies:expr)?
2606 ;
2607 )+) => {
2608 $(
2609 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
2610 pub struct $name {
2611 test_compiler: Compiler,
2612 }
2613
2614 impl Step for $name {
2615 type Output = ();
2616 const IS_HOST: bool = true;
2617
2618 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2619 run.path($path)
2620 }
2621
2622 fn is_default_step(_builder: &Builder<'_>) -> bool {
2623 const { $default }
2624 }
2625
2626 fn make_run(run: RunConfig<'_>) {
2627 run.builder.ensure($name {
2628 test_compiler: run.builder.compiler(run.builder.top_stage, run.target),
2629 });
2630 }
2631
2632 fn run(self, builder: &Builder<'_>) {
2633 $(
2634 for submodule in $submodules {
2635 builder.require_submodule(submodule, None);
2636 }
2637 )*
2638
2639 let dependencies = vec![];
2640 $(
2641 let mut dependencies = dependencies;
2642 for dep in $dependencies {
2643 dependencies.push(dep);
2644 }
2645 )?
2646
2647 builder.ensure(BookTest {
2648 test_compiler: self.test_compiler,
2649 path: PathBuf::from($path),
2650 name: $book_name,
2651 is_ext_doc: !$default,
2652 dependencies,
2653 });
2654 }
2655 }
2656 )+
2657 }
2658}
2659
2660test_book!(
2661 Nomicon, "src/doc/nomicon", "nomicon", default=false, submodules=["src/doc/nomicon"];
2662 Reference, "src/doc/reference", "reference", default=false, submodules=["src/doc/reference"];
2663 RustdocBook, "src/doc/rustdoc", "rustdoc", default=true;
2664 RustcBook, "src/doc/rustc", "rustc", default=true;
2665 RustByExample, "src/doc/rust-by-example", "rust-by-example", default=false, submodules=["src/doc/rust-by-example"];
2666 EmbeddedBook, "src/doc/embedded-book", "embedded-book", default=false, submodules=["src/doc/embedded-book"];
2667 TheBook, "src/doc/book", "book", default=false, submodules=["src/doc/book"], dependencies=["src/doc/book/packages/trpl"];
2668 UnstableBook, "src/doc/unstable-book", "unstable-book", default=true;
2669 EditionGuide, "src/doc/edition-guide", "edition-guide", default=false, submodules=["src/doc/edition-guide"];
2670);
2671
2672#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2673pub struct ErrorIndex {
2674 compilers: RustcPrivateCompilers,
2675}
2676
2677impl Step for ErrorIndex {
2678 type Output = ();
2679 const IS_HOST: bool = true;
2680
2681 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2682 run.path("src/tools/error_index_generator").alias("error-index")
2685 }
2686
2687 fn is_default_step(_builder: &Builder<'_>) -> bool {
2688 true
2689 }
2690
2691 fn make_run(run: RunConfig<'_>) {
2692 let compilers = RustcPrivateCompilers::new(
2696 run.builder,
2697 run.builder.top_stage,
2698 run.builder.config.host_target,
2699 );
2700 run.builder.ensure(ErrorIndex { compilers });
2701 }
2702
2703 fn run(self, builder: &Builder<'_>) {
2710 let target_compiler = self.compilers.target_compiler();
2712
2713 let dir = testdir(builder, target_compiler.host);
2714 t!(fs::create_dir_all(&dir));
2715 let output = dir.join("error-index.md");
2716
2717 let mut tool = tool::ErrorIndex::command(builder, self.compilers);
2718 tool.arg("markdown").arg(&output);
2719
2720 let guard = builder.msg_test("error-index", target_compiler.host, target_compiler.stage);
2721 let _time = helpers::timeit(builder);
2722 tool.run_capture(builder);
2723 drop(guard);
2724 builder.std(target_compiler, target_compiler.host);
2727 markdown_test(builder, target_compiler, &output);
2728 }
2729}
2730
2731fn markdown_test(builder: &Builder<'_>, compiler: Compiler, markdown: &Path) -> bool {
2732 if let Ok(contents) = fs::read_to_string(markdown)
2733 && !contents.contains("```")
2734 {
2735 return true;
2736 }
2737
2738 builder.do_if_verbose(|| println!("doc tests for: {}", markdown.display()));
2739 let mut cmd = builder.rustdoc_cmd(compiler);
2740 builder.add_rust_test_threads(&mut cmd);
2741 cmd.arg("-Z");
2743 cmd.arg("unstable-options");
2744 cmd.arg("--test");
2745 cmd.arg(markdown);
2746 cmd.env("RUSTC_BOOTSTRAP", "1");
2747
2748 let test_args = builder.config.test_args().join(" ");
2749 cmd.arg("--test-args").arg(test_args);
2750
2751 cmd = cmd.delay_failure();
2752 if !builder.config.verbose_tests {
2753 cmd.run_capture(builder).is_success()
2754 } else {
2755 cmd.run(builder)
2756 }
2757}
2758
2759#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2764pub struct CrateLibrustc {
2765 build_compiler: Compiler,
2767 target: TargetSelection,
2768 crates: Vec<String>,
2769}
2770
2771impl Step for CrateLibrustc {
2772 type Output = ();
2773 const IS_HOST: bool = true;
2774
2775 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2776 run.crate_or_deps("rustc-main").path("compiler")
2777 }
2778
2779 fn is_default_step(_builder: &Builder<'_>) -> bool {
2780 true
2781 }
2782
2783 fn make_run(run: RunConfig<'_>) {
2784 let builder = run.builder;
2785 let host = run.build_triple();
2786 let build_compiler = builder.compiler(builder.top_stage - 1, host);
2787 let crates = run.make_run_crates(Alias::Compiler);
2788
2789 builder.ensure(CrateLibrustc { build_compiler, target: run.target, crates });
2790 }
2791
2792 fn run(self, builder: &Builder<'_>) {
2793 builder.std(self.build_compiler, self.target);
2794
2795 builder.ensure(Crate {
2797 build_compiler: self.build_compiler,
2798 target: self.target,
2799 mode: Mode::Rustc,
2800 crates: self.crates,
2801 });
2802 }
2803
2804 fn metadata(&self) -> Option<StepMetadata> {
2805 Some(StepMetadata::test("CrateLibrustc", self.target).built_by(self.build_compiler))
2806 }
2807}
2808
2809fn run_cargo_test<'a>(
2813 cargo: builder::Cargo,
2814 libtest_args: &[&str],
2815 crates: &[String],
2816 description: impl Into<Option<&'a str>>,
2817 target: TargetSelection,
2818 builder: &Builder<'_>,
2819) -> bool {
2820 let compiler = cargo.compiler();
2821 let mut cargo = prepare_cargo_test(cargo, libtest_args, crates, target, builder);
2822 let _time = helpers::timeit(builder);
2823 let _group =
2824 description.into().and_then(|what| builder.msg_test(what, target, compiler.stage + 1));
2825
2826 #[cfg(feature = "build-metrics")]
2827 builder.metrics.begin_test_suite(
2828 build_helper::metrics::TestSuiteMetadata::CargoPackage {
2829 crates: crates.iter().map(|c| c.to_string()).collect(),
2830 target: target.triple.to_string(),
2831 host: compiler.host.triple.to_string(),
2832 stage: compiler.stage,
2833 },
2834 builder,
2835 );
2836 add_flags_and_try_run_tests(builder, &mut cargo)
2837}
2838
2839fn prepare_cargo_test(
2841 cargo: builder::Cargo,
2842 libtest_args: &[&str],
2843 crates: &[String],
2844 target: TargetSelection,
2845 builder: &Builder<'_>,
2846) -> BootstrapCommand {
2847 let compiler = cargo.compiler();
2848 let mut cargo: BootstrapCommand = cargo.into();
2849
2850 if builder.config.cmd.bless() && !cargo.get_envs().any(|v| v.0 == "RUSTC_BLESS") {
2854 cargo.env("RUSTC_BLESS", "Gesundheit");
2855 }
2856
2857 if builder.kind == Kind::Test && !builder.fail_fast {
2861 cargo.arg("--no-fail-fast");
2862 }
2863
2864 if builder.config.json_output {
2865 cargo.arg("--message-format=json");
2866 }
2867
2868 match builder.doc_tests {
2869 DocTests::Only => {
2870 cargo.arg("--doc");
2871 }
2872 DocTests::No => {
2873 cargo.args(["--bins", "--examples", "--tests", "--benches"]);
2874 }
2875 DocTests::Yes => {}
2876 }
2877
2878 for krate in crates {
2879 cargo.arg("-p").arg(krate);
2880 }
2881
2882 cargo.arg("--").args(builder.config.test_args()).args(libtest_args);
2883 if !builder.config.verbose_tests {
2884 cargo.arg("--quiet");
2885 }
2886
2887 if builder.kind != Kind::Miri {
2896 let mut dylib_paths = builder.rustc_lib_paths(compiler);
2897 dylib_paths.push(builder.sysroot_target_libdir(compiler, target));
2898 helpers::add_dylib_path(dylib_paths, &mut cargo);
2899 }
2900
2901 if builder.remote_tested(target) {
2902 cargo.env(
2903 format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)),
2904 format!("{} run 0", builder.tool_exe(Tool::RemoteTestClient).display()),
2905 );
2906 } else if let Some(tool) = builder.runner(target) {
2907 cargo.env(format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)), tool);
2908 }
2909
2910 cargo
2911}
2912
2913#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2921pub struct Crate {
2922 build_compiler: Compiler,
2924 target: TargetSelection,
2925 mode: Mode,
2926 crates: Vec<String>,
2927}
2928
2929impl Step for Crate {
2930 type Output = ();
2931
2932 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2933 run.crate_or_deps("sysroot").crate_or_deps("coretests").crate_or_deps("alloctests")
2934 }
2935
2936 fn is_default_step(_builder: &Builder<'_>) -> bool {
2937 true
2938 }
2939
2940 fn make_run(run: RunConfig<'_>) {
2941 let builder = run.builder;
2942 let host = run.build_triple();
2943 let build_compiler = builder.compiler(builder.top_stage, host);
2944 let crates = run
2945 .paths
2946 .iter()
2947 .map(|p| builder.crate_paths[&p.assert_single_path().path].clone())
2948 .collect();
2949
2950 builder.ensure(Crate { build_compiler, target: run.target, mode: Mode::Std, crates });
2951 }
2952
2953 fn run(self, builder: &Builder<'_>) {
2962 let build_compiler = self.build_compiler;
2963 let target = self.target;
2964 let mode = self.mode;
2965
2966 builder.ensure(Std::new(build_compiler, build_compiler.host).force_recompile(true));
2969
2970 let mut cargo = if builder.kind == Kind::Miri {
2971 if builder.top_stage == 0 {
2972 eprintln!("ERROR: `x.py miri` requires stage 1 or higher");
2973 std::process::exit(1);
2974 }
2975
2976 let mut cargo = builder::Cargo::new(
2979 builder,
2980 build_compiler,
2981 mode,
2982 SourceType::InTree,
2983 target,
2984 Kind::MiriTest,
2985 );
2986 cargo.env("MIRI_REPLACE_LIBRS_IF_NOT_TEST", "1");
2998 cargo.rustflag("-Zforce-unstable-if-unmarked");
3002 cargo
3003 } else {
3004 if !builder.config.is_host_target(target) {
3006 builder.ensure(compile::Std::new(build_compiler, target).force_recompile(true));
3007 builder.ensure(RemoteCopyLibs { build_compiler, target });
3008 }
3009
3010 builder::Cargo::new(
3012 builder,
3013 build_compiler,
3014 mode,
3015 SourceType::InTree,
3016 target,
3017 builder.kind,
3018 )
3019 };
3020
3021 match mode {
3022 Mode::Std => {
3023 if builder.kind == Kind::Miri {
3024 cargo
3030 .arg("--manifest-path")
3031 .arg(builder.src.join("library/sysroot/Cargo.toml"));
3032 } else {
3033 compile::std_cargo(builder, target, &mut cargo, &[]);
3034 }
3035 }
3036 Mode::Rustc => {
3037 compile::rustc_cargo(builder, &mut cargo, target, &build_compiler, &self.crates);
3038 }
3039 _ => panic!("can only test libraries"),
3040 };
3041
3042 let mut crates = self.crates.clone();
3043 if crates.iter().any(|crate_| crate_ == "core") {
3048 crates.push("coretests".to_owned());
3049 }
3050 if crates.iter().any(|crate_| crate_ == "alloc") {
3051 crates.push("alloctests".to_owned());
3052 }
3053
3054 run_cargo_test(cargo, &[], &crates, &*crate_description(&self.crates), target, builder);
3055 }
3056}
3057
3058#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3061pub struct CrateRustdoc {
3062 host: TargetSelection,
3063}
3064
3065impl Step for CrateRustdoc {
3066 type Output = ();
3067 const IS_HOST: bool = true;
3068
3069 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3070 run.paths(&["src/librustdoc", "src/tools/rustdoc"])
3071 }
3072
3073 fn is_default_step(_builder: &Builder<'_>) -> bool {
3074 true
3075 }
3076
3077 fn make_run(run: RunConfig<'_>) {
3078 let builder = run.builder;
3079
3080 builder.ensure(CrateRustdoc { host: run.target });
3081 }
3082
3083 fn run(self, builder: &Builder<'_>) {
3084 let target = self.host;
3085
3086 let compiler = if builder.download_rustc() {
3087 builder.compiler(builder.top_stage, target)
3088 } else {
3089 builder.compiler_for(builder.top_stage, target, target)
3094 };
3095 builder.std(compiler, target);
3100 builder.ensure(compile::Rustc::new(compiler, target));
3101
3102 let mut cargo = tool::prepare_tool_cargo(
3103 builder,
3104 compiler,
3105 Mode::ToolRustcPrivate,
3106 target,
3107 builder.kind,
3108 "src/tools/rustdoc",
3109 SourceType::InTree,
3110 &[],
3111 );
3112 if self.host.contains("musl") {
3113 cargo.arg("'-Ctarget-feature=-crt-static'");
3114 }
3115
3116 let libdir = if builder.download_rustc() {
3143 builder.rustc_libdir(compiler)
3144 } else {
3145 builder.sysroot_target_libdir(compiler, target).to_path_buf()
3146 };
3147 let mut dylib_path = dylib_path();
3148 dylib_path.insert(0, PathBuf::from(&*libdir));
3149 cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());
3150
3151 run_cargo_test(cargo, &[], &["rustdoc:0.0.0".to_string()], "rustdoc", target, builder);
3152 }
3153}
3154
3155#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3156pub struct CrateRustdocJsonTypes {
3157 build_compiler: Compiler,
3158 target: TargetSelection,
3159}
3160
3161impl Step for CrateRustdocJsonTypes {
3162 type Output = ();
3163 const IS_HOST: bool = true;
3164
3165 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3166 run.path("src/rustdoc-json-types")
3167 }
3168
3169 fn is_default_step(_builder: &Builder<'_>) -> bool {
3170 true
3171 }
3172
3173 fn make_run(run: RunConfig<'_>) {
3174 let builder = run.builder;
3175
3176 builder.ensure(CrateRustdocJsonTypes {
3177 build_compiler: get_tool_target_compiler(
3178 builder,
3179 ToolTargetBuildMode::Build(run.target),
3180 ),
3181 target: run.target,
3182 });
3183 }
3184
3185 fn run(self, builder: &Builder<'_>) {
3186 let target = self.target;
3187
3188 let cargo = tool::prepare_tool_cargo(
3189 builder,
3190 self.build_compiler,
3191 Mode::ToolTarget,
3192 target,
3193 builder.kind,
3194 "src/rustdoc-json-types",
3195 SourceType::InTree,
3196 &[],
3197 );
3198
3199 let libtest_args = if target.contains("musl") {
3201 ["'-Ctarget-feature=-crt-static'"].as_slice()
3202 } else {
3203 &[]
3204 };
3205
3206 run_cargo_test(
3207 cargo,
3208 libtest_args,
3209 &["rustdoc-json-types".to_string()],
3210 "rustdoc-json-types",
3211 target,
3212 builder,
3213 );
3214 }
3215}
3216
3217#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3227pub struct RemoteCopyLibs {
3228 build_compiler: Compiler,
3229 target: TargetSelection,
3230}
3231
3232impl Step for RemoteCopyLibs {
3233 type Output = ();
3234
3235 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3236 run.never()
3237 }
3238
3239 fn run(self, builder: &Builder<'_>) {
3240 let build_compiler = self.build_compiler;
3241 let target = self.target;
3242 if !builder.remote_tested(target) {
3243 return;
3244 }
3245
3246 builder.std(build_compiler, target);
3247
3248 builder.info(&format!("REMOTE copy libs to emulator ({target})"));
3249
3250 let remote_test_server = builder.ensure(tool::RemoteTestServer { build_compiler, target });
3251
3252 let tool = builder.tool_exe(Tool::RemoteTestClient);
3254 let mut cmd = command(&tool);
3255 cmd.arg("spawn-emulator")
3256 .arg(target.triple)
3257 .arg(&remote_test_server.tool_path)
3258 .arg(builder.tempdir());
3259 if let Some(rootfs) = builder.qemu_rootfs(target) {
3260 cmd.arg(rootfs);
3261 }
3262 cmd.run(builder);
3263
3264 for f in t!(builder.sysroot_target_libdir(build_compiler, target).read_dir()) {
3266 let f = t!(f);
3267 if helpers::is_dylib(&f.path()) {
3268 command(&tool).arg("push").arg(f.path()).run(builder);
3269 }
3270 }
3271 }
3272}
3273
3274#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3275pub struct Distcheck;
3276
3277impl Step for Distcheck {
3278 type Output = ();
3279
3280 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3281 run.alias("distcheck")
3282 }
3283
3284 fn make_run(run: RunConfig<'_>) {
3285 run.builder.ensure(Distcheck);
3286 }
3287
3288 fn run(self, builder: &Builder<'_>) {
3298 let root_dir = std::env::temp_dir().join("distcheck");
3301
3302 distcheck_plain_source_tarball(builder, &root_dir.join("distcheck-rustc-src"));
3303 distcheck_rust_src(builder, &root_dir.join("distcheck-rust-src"));
3304 distcheck_rustc_dev(builder, &root_dir.join("distcheck-rustc-dev"));
3305 }
3306}
3307
3308fn distcheck_plain_source_tarball(builder: &Builder<'_>, plain_src_dir: &Path) {
3310 builder.info("Distcheck plain source tarball");
3311 let plain_src_tarball = builder.ensure(dist::PlainSourceTarball);
3312 builder.clear_dir(plain_src_dir);
3313
3314 let configure_args: Vec<String> = std::env::var("DISTCHECK_CONFIGURE_ARGS")
3315 .map(|args| args.split(" ").map(|s| s.to_string()).collect::<Vec<String>>())
3316 .unwrap_or_default();
3317
3318 command("tar")
3319 .arg("-xf")
3320 .arg(plain_src_tarball.tarball())
3321 .arg("--strip-components=1")
3322 .current_dir(plain_src_dir)
3323 .run(builder);
3324 command("./configure")
3325 .arg("--set")
3326 .arg("rust.omit-git-hash=false")
3327 .args(&configure_args)
3328 .arg("--enable-vendor")
3329 .current_dir(plain_src_dir)
3330 .run(builder);
3331 command(helpers::make(&builder.config.host_target.triple))
3332 .arg("check")
3333 .env("GITHUB_ACTIONS", "0")
3336 .current_dir(plain_src_dir)
3337 .run(builder);
3338 builder.remove_dir(plain_src_dir);
3340}
3341
3342fn distcheck_rust_src(builder: &Builder<'_>, src_dir: &Path) {
3344 builder.info("Distcheck rust-src");
3345 let src_tarball = builder.ensure(dist::Src);
3346 builder.clear_dir(src_dir);
3347
3348 command("tar")
3349 .arg("-xf")
3350 .arg(src_tarball.tarball())
3351 .arg("--strip-components=1")
3352 .current_dir(src_dir)
3353 .run(builder);
3354
3355 let toml = src_dir.join("rust-src/lib/rustlib/src/rust/library/std/Cargo.toml");
3356 command(&builder.initial_cargo)
3357 .env("RUSTC_BOOTSTRAP", "1")
3360 .arg("generate-lockfile")
3361 .arg("--manifest-path")
3362 .arg(&toml)
3363 .current_dir(src_dir)
3364 .run(builder);
3365 builder.remove_dir(src_dir);
3367}
3368
3369fn distcheck_rustc_dev(builder: &Builder<'_>, dir: &Path) {
3371 builder.info("Distcheck rustc-dev");
3372 let tarball = builder.ensure(dist::RustcDev::new(builder, builder.host_target)).unwrap();
3373 builder.clear_dir(dir);
3374
3375 command("tar")
3376 .arg("-xf")
3377 .arg(tarball.tarball())
3378 .arg("--strip-components=1")
3379 .current_dir(dir)
3380 .run(builder);
3381
3382 command(&builder.initial_cargo)
3383 .arg("metadata")
3384 .arg("--manifest-path")
3385 .arg("rustc-dev/lib/rustlib/rustc-src/rust/compiler/rustc/Cargo.toml")
3386 .env("RUSTC_BOOTSTRAP", "1")
3387 .env("RUSTC", &builder.initial_rustc)
3389 .current_dir(dir)
3390 .run(builder);
3391 builder.remove_dir(dir);
3393}
3394
3395#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3397pub(crate) struct BootstrapPy;
3398
3399impl Step for BootstrapPy {
3400 type Output = ();
3401 const IS_HOST: bool = true;
3402
3403 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3404 run.alias("bootstrap-py")
3405 }
3406
3407 fn is_default_step(builder: &Builder<'_>) -> bool {
3408 builder.config.is_running_on_ci
3412 }
3413
3414 fn make_run(run: RunConfig<'_>) {
3415 run.builder.ensure(BootstrapPy)
3416 }
3417
3418 fn run(self, builder: &Builder<'_>) -> Self::Output {
3419 let mut check_bootstrap = command(
3420 builder.config.python.as_ref().expect("python is required for running bootstrap tests"),
3421 );
3422 check_bootstrap
3423 .args(["-m", "unittest", "bootstrap_test.py"])
3424 .args(builder.config.test_args())
3426 .env("BUILD_DIR", &builder.out)
3427 .env("BUILD_PLATFORM", builder.build.host_target.triple)
3428 .env("BOOTSTRAP_TEST_RUSTC_BIN", &builder.initial_rustc)
3429 .env("BOOTSTRAP_TEST_CARGO_BIN", &builder.initial_cargo)
3430 .current_dir(builder.src.join("src/bootstrap/"));
3431 check_bootstrap.delay_failure().run(builder);
3432 }
3433}
3434
3435#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3436pub struct Bootstrap;
3437
3438impl Step for Bootstrap {
3439 type Output = ();
3440 const IS_HOST: bool = true;
3441
3442 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3443 run.path("src/bootstrap")
3444 }
3445
3446 fn is_default_step(builder: &Builder<'_>) -> bool {
3447 builder.config.is_running_on_ci
3451 }
3452
3453 fn run(self, builder: &Builder<'_>) {
3455 let host = builder.config.host_target;
3456 let build_compiler = builder.compiler(0, host);
3457
3458 builder.build.require_submodule("src/tools/cargo", None);
3460
3461 let mut cargo = tool::prepare_tool_cargo(
3462 builder,
3463 build_compiler,
3464 Mode::ToolBootstrap,
3465 host,
3466 Kind::Test,
3467 "src/bootstrap",
3468 SourceType::InTree,
3469 &[],
3470 );
3471
3472 cargo.release_build(false);
3473
3474 cargo
3475 .rustflag("-Cdebuginfo=2")
3476 .env("CARGO_TARGET_DIR", builder.out.join("bootstrap"))
3477 .env("INSTA_WORKSPACE_ROOT", &builder.src)
3479 .env("RUSTC_BOOTSTRAP", "1");
3480
3481 if builder.config.cmd.bless() {
3482 cargo.env("INSTA_UPDATE", "always");
3486 }
3487
3488 run_cargo_test(cargo, &[], &[], None, host, builder);
3489 }
3490
3491 fn make_run(run: RunConfig<'_>) {
3492 run.builder.ensure(Bootstrap);
3493 }
3494}
3495
3496fn get_compiler_to_test(builder: &Builder<'_>, target: TargetSelection) -> Compiler {
3497 builder.compiler(builder.top_stage, target)
3498}
3499
3500#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3503pub struct TierCheck {
3504 test_compiler: Compiler,
3505}
3506
3507impl Step for TierCheck {
3508 type Output = ();
3509 const IS_HOST: bool = true;
3510
3511 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3512 run.path("src/tools/tier-check")
3513 }
3514
3515 fn is_default_step(_builder: &Builder<'_>) -> bool {
3516 true
3517 }
3518
3519 fn make_run(run: RunConfig<'_>) {
3520 run.builder
3521 .ensure(TierCheck { test_compiler: get_compiler_to_test(run.builder, run.target) });
3522 }
3523
3524 fn run(self, builder: &Builder<'_>) {
3525 let tool_build_compiler = builder.compiler(0, builder.host_target);
3526
3527 let mut cargo = tool::prepare_tool_cargo(
3528 builder,
3529 tool_build_compiler,
3530 Mode::ToolBootstrap,
3531 tool_build_compiler.host,
3532 Kind::Run,
3533 "src/tools/tier-check",
3534 SourceType::InTree,
3535 &[],
3536 );
3537 cargo.arg(builder.src.join("src/doc/rustc/src/platform-support.md"));
3538 cargo.arg(builder.rustc(self.test_compiler));
3539
3540 let _guard = builder.msg_test(
3541 "platform support check",
3542 self.test_compiler.host,
3543 self.test_compiler.stage,
3544 );
3545 BootstrapCommand::from(cargo).delay_failure().run(builder);
3546 }
3547
3548 fn metadata(&self) -> Option<StepMetadata> {
3549 Some(StepMetadata::test("tier-check", self.test_compiler.host))
3550 }
3551}
3552
3553#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3554pub struct LintDocs {
3555 build_compiler: Compiler,
3556 target: TargetSelection,
3557}
3558
3559impl Step for LintDocs {
3560 type Output = ();
3561 const IS_HOST: bool = true;
3562
3563 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3564 run.path("src/tools/lint-docs")
3565 }
3566
3567 fn is_default_step(builder: &Builder<'_>) -> bool {
3568 builder.top_stage >= 2
3571 }
3572
3573 fn make_run(run: RunConfig<'_>) {
3574 if run.builder.top_stage < 2 {
3575 eprintln!("WARNING: lint-docs tests might not work below stage 2");
3576 }
3577
3578 run.builder.ensure(LintDocs {
3579 build_compiler: prepare_doc_compiler(
3580 run.builder,
3581 run.builder.config.host_target,
3582 run.builder.top_stage,
3583 ),
3584 target: run.target,
3585 });
3586 }
3587
3588 fn run(self, builder: &Builder<'_>) {
3591 builder.ensure(crate::core::build_steps::doc::RustcBook::validate(
3592 self.build_compiler,
3593 self.target,
3594 ));
3595 }
3596
3597 fn metadata(&self) -> Option<StepMetadata> {
3598 Some(StepMetadata::test("lint-docs", self.target).built_by(self.build_compiler))
3599 }
3600}
3601
3602#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3603pub struct RustInstaller;
3604
3605impl Step for RustInstaller {
3606 type Output = ();
3607 const IS_HOST: bool = true;
3608
3609 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3610 run.path("src/tools/rust-installer")
3611 }
3612
3613 fn is_default_step(_builder: &Builder<'_>) -> bool {
3614 true
3615 }
3616
3617 fn make_run(run: RunConfig<'_>) {
3618 run.builder.ensure(Self);
3619 }
3620
3621 fn run(self, builder: &Builder<'_>) {
3623 let bootstrap_host = builder.config.host_target;
3624 let build_compiler = builder.compiler(0, bootstrap_host);
3625 let cargo = tool::prepare_tool_cargo(
3626 builder,
3627 build_compiler,
3628 Mode::ToolBootstrap,
3629 bootstrap_host,
3630 Kind::Test,
3631 "src/tools/rust-installer",
3632 SourceType::InTree,
3633 &[],
3634 );
3635
3636 let _guard = builder.msg_test("rust-installer", bootstrap_host, 1);
3637 run_cargo_test(cargo, &[], &[], None, bootstrap_host, builder);
3638
3639 if bootstrap_host != "x86_64-unknown-linux-gnu" {
3643 return;
3644 }
3645
3646 let mut cmd = command(builder.src.join("src/tools/rust-installer/test.sh"));
3647 let tmpdir = testdir(builder, build_compiler.host).join("rust-installer");
3648 let _ = std::fs::remove_dir_all(&tmpdir);
3649 let _ = std::fs::create_dir_all(&tmpdir);
3650 cmd.current_dir(&tmpdir);
3651 cmd.env("CARGO_TARGET_DIR", tmpdir.join("cargo-target"));
3652 cmd.env("CARGO", &builder.initial_cargo);
3653 cmd.env("RUSTC", &builder.initial_rustc);
3654 cmd.env("TMP_DIR", &tmpdir);
3655 cmd.delay_failure().run(builder);
3656 }
3657}
3658
3659#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3660pub struct TestHelpers {
3661 pub target: TargetSelection,
3662}
3663
3664impl Step for TestHelpers {
3665 type Output = ();
3666
3667 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3668 run.path("tests/auxiliary/rust_test_helpers.c")
3669 }
3670
3671 fn make_run(run: RunConfig<'_>) {
3672 run.builder.ensure(TestHelpers { target: run.target })
3673 }
3674
3675 fn run(self, builder: &Builder<'_>) {
3678 if builder.config.dry_run() {
3679 return;
3680 }
3681 let target = if self.target == "x86_64-fortanix-unknown-sgx" {
3685 TargetSelection::from_user("x86_64-unknown-linux-gnu")
3686 } else {
3687 self.target
3688 };
3689 let dst = builder.test_helpers_out(target);
3690 let src = builder.src.join("tests/auxiliary/rust_test_helpers.c");
3691 if up_to_date(&src, &dst.join("librust_test_helpers.a")) {
3692 return;
3693 }
3694
3695 let _guard = builder.msg_unstaged(Kind::Build, "test helpers", target);
3696 t!(fs::create_dir_all(&dst));
3697 let mut cfg = cc::Build::new();
3698
3699 if !target.is_msvc() {
3703 if let Some(ar) = builder.ar(target) {
3704 cfg.archiver(ar);
3705 }
3706 cfg.compiler(builder.cc(target));
3707 }
3708 cfg.cargo_metadata(false)
3709 .out_dir(&dst)
3710 .target(&target.triple)
3711 .host(&builder.config.host_target.triple)
3712 .opt_level(0)
3713 .warnings(false)
3714 .debug(false)
3715 .file(builder.src.join("tests/auxiliary/rust_test_helpers.c"))
3716 .compile("rust_test_helpers");
3717 }
3718}
3719
3720#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3721pub struct CodegenCranelift {
3722 compilers: RustcPrivateCompilers,
3723 target: TargetSelection,
3724}
3725
3726impl Step for CodegenCranelift {
3727 type Output = ();
3728 const IS_HOST: bool = true;
3729
3730 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3731 run.paths(&["compiler/rustc_codegen_cranelift"])
3732 }
3733
3734 fn is_default_step(_builder: &Builder<'_>) -> bool {
3735 true
3736 }
3737
3738 fn make_run(run: RunConfig<'_>) {
3739 let builder = run.builder;
3740 let host = run.build_triple();
3741 let compilers = RustcPrivateCompilers::new(run.builder, run.builder.top_stage, host);
3742
3743 if builder.doc_tests == DocTests::Only {
3744 return;
3745 }
3746
3747 if builder.download_rustc() {
3748 builder.info("CI rustc uses the default codegen backend. skipping");
3749 return;
3750 }
3751
3752 if !target_supports_cranelift_backend(run.target) {
3753 builder.info("target not supported by rustc_codegen_cranelift. skipping");
3754 return;
3755 }
3756
3757 if builder.remote_tested(run.target) {
3758 builder.info("remote testing is not supported by rustc_codegen_cranelift. skipping");
3759 return;
3760 }
3761
3762 if !builder
3763 .config
3764 .enabled_codegen_backends(run.target)
3765 .contains(&CodegenBackendKind::Cranelift)
3766 {
3767 builder.info("cranelift not in rust.codegen-backends. skipping");
3768 return;
3769 }
3770
3771 builder.ensure(CodegenCranelift { compilers, target: run.target });
3772 }
3773
3774 fn run(self, builder: &Builder<'_>) {
3775 let compilers = self.compilers;
3776 let build_compiler = compilers.build_compiler();
3777
3778 let target_compiler = compilers.target_compiler();
3781 let target = self.target;
3782
3783 builder.std(target_compiler, target);
3784
3785 let mut cargo = builder::Cargo::new(
3786 builder,
3787 target_compiler,
3788 Mode::Codegen, SourceType::InTree,
3790 target,
3791 Kind::Run,
3792 );
3793
3794 cargo.current_dir(&builder.src.join("compiler/rustc_codegen_cranelift"));
3795 cargo
3796 .arg("--manifest-path")
3797 .arg(builder.src.join("compiler/rustc_codegen_cranelift/build_system/Cargo.toml"));
3798 compile::rustc_cargo_env(builder, &mut cargo, target);
3799
3800 cargo.env("CARGO_BUILD_INCREMENTAL", "false");
3802
3803 let _guard = builder.msg_test(
3804 "rustc_codegen_cranelift",
3805 target_compiler.host,
3806 target_compiler.stage,
3807 );
3808
3809 let download_dir = builder.out.join("cg_clif_download");
3811
3812 cargo
3813 .arg("--")
3814 .arg("test")
3815 .arg("--download-dir")
3816 .arg(&download_dir)
3817 .arg("--out-dir")
3818 .arg(builder.stage_out(build_compiler, Mode::Codegen).join("cg_clif"))
3819 .arg("--no-unstable-features")
3820 .arg("--use-backend")
3821 .arg("cranelift")
3822 .arg("--sysroot")
3824 .arg("llvm")
3825 .arg("--skip-test")
3828 .arg("testsuite.extended_sysroot");
3829
3830 cargo.into_cmd().run(builder);
3831 }
3832
3833 fn metadata(&self) -> Option<StepMetadata> {
3834 Some(
3835 StepMetadata::test("rustc_codegen_cranelift", self.target)
3836 .built_by(self.compilers.build_compiler()),
3837 )
3838 }
3839}
3840
3841#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3842pub struct CodegenGCC {
3843 compilers: RustcPrivateCompilers,
3844 target: TargetSelection,
3845}
3846
3847impl Step for CodegenGCC {
3848 type Output = ();
3849 const IS_HOST: bool = true;
3850
3851 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3852 run.paths(&["compiler/rustc_codegen_gcc"])
3853 }
3854
3855 fn is_default_step(_builder: &Builder<'_>) -> bool {
3856 true
3857 }
3858
3859 fn make_run(run: RunConfig<'_>) {
3860 let builder = run.builder;
3861 let host = run.build_triple();
3862 let compilers = RustcPrivateCompilers::new(run.builder, run.builder.top_stage, host);
3863
3864 if builder.doc_tests == DocTests::Only {
3865 return;
3866 }
3867
3868 if builder.download_rustc() {
3869 builder.info("CI rustc uses the default codegen backend. skipping");
3870 return;
3871 }
3872
3873 let triple = run.target.triple;
3874 let target_supported =
3875 if triple.contains("linux") { triple.contains("x86_64") } else { false };
3876 if !target_supported {
3877 builder.info("target not supported by rustc_codegen_gcc. skipping");
3878 return;
3879 }
3880
3881 if builder.remote_tested(run.target) {
3882 builder.info("remote testing is not supported by rustc_codegen_gcc. skipping");
3883 return;
3884 }
3885
3886 if !builder.config.enabled_codegen_backends(run.target).contains(&CodegenBackendKind::Gcc) {
3887 builder.info("gcc not in rust.codegen-backends. skipping");
3888 return;
3889 }
3890
3891 builder.ensure(CodegenGCC { compilers, target: run.target });
3892 }
3893
3894 fn run(self, builder: &Builder<'_>) {
3895 let compilers = self.compilers;
3896 let target = self.target;
3897
3898 let gcc = builder.ensure(Gcc { target });
3899
3900 builder.ensure(
3901 compile::Std::new(compilers.build_compiler(), target)
3902 .extra_rust_args(&["-Csymbol-mangling-version=v0", "-Cpanic=abort"]),
3903 );
3904
3905 let _guard = builder.msg_test(
3906 "rustc_codegen_gcc",
3907 compilers.target(),
3908 compilers.target_compiler().stage,
3909 );
3910
3911 let mut cargo = builder::Cargo::new(
3912 builder,
3913 compilers.build_compiler(),
3914 Mode::Codegen, SourceType::InTree,
3916 target,
3917 Kind::Run,
3918 );
3919
3920 cargo.current_dir(&builder.src.join("compiler/rustc_codegen_gcc"));
3921 cargo
3922 .arg("--manifest-path")
3923 .arg(builder.src.join("compiler/rustc_codegen_gcc/build_system/Cargo.toml"));
3924 compile::rustc_cargo_env(builder, &mut cargo, target);
3925 add_cg_gcc_cargo_flags(&mut cargo, &gcc);
3926
3927 cargo.env("CARGO_BUILD_INCREMENTAL", "false");
3929 cargo.rustflag("-Cpanic=abort");
3930
3931 cargo
3932 .env("CG_RUSTFLAGS", "-Alinker-messages")
3934 .arg("--")
3935 .arg("test")
3936 .arg("--use-backend")
3937 .arg("gcc")
3938 .arg("--gcc-path")
3939 .arg(gcc.libgccjit.parent().unwrap())
3940 .arg("--out-dir")
3941 .arg(builder.stage_out(compilers.build_compiler(), Mode::Codegen).join("cg_gcc"))
3942 .arg("--release")
3943 .arg("--mini-tests")
3944 .arg("--std-tests");
3945 cargo.args(builder.config.test_args());
3946
3947 cargo.into_cmd().run(builder);
3948 }
3949
3950 fn metadata(&self) -> Option<StepMetadata> {
3951 Some(
3952 StepMetadata::test("rustc_codegen_gcc", self.target)
3953 .built_by(self.compilers.build_compiler()),
3954 )
3955 }
3956}
3957
3958#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3963pub struct TestFloatParse {
3964 build_compiler: Compiler,
3973 target: TargetSelection,
3975}
3976
3977impl Step for TestFloatParse {
3978 type Output = ();
3979 const IS_HOST: bool = true;
3980
3981 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3982 run.path("src/tools/test-float-parse")
3983 }
3984
3985 fn is_default_step(_builder: &Builder<'_>) -> bool {
3986 true
3987 }
3988
3989 fn make_run(run: RunConfig<'_>) {
3990 run.builder.ensure(Self {
3991 build_compiler: get_compiler_to_test(run.builder, run.target),
3992 target: run.target,
3993 });
3994 }
3995
3996 fn run(self, builder: &Builder<'_>) {
3997 let build_compiler = self.build_compiler;
3998 let target = self.target;
3999
4000 builder.std(build_compiler, target);
4002 builder.std(build_compiler, builder.host_target);
4003
4004 let mut cargo_test = tool::prepare_tool_cargo(
4006 builder,
4007 build_compiler,
4008 Mode::ToolStd,
4009 target,
4010 Kind::Test,
4011 "src/tools/test-float-parse",
4012 SourceType::InTree,
4013 &[],
4014 );
4015 cargo_test.allow_features(TEST_FLOAT_PARSE_ALLOW_FEATURES);
4016
4017 run_cargo_test(cargo_test, &[], &[], "test-float-parse", target, builder);
4018
4019 let mut cargo_run = tool::prepare_tool_cargo(
4021 builder,
4022 build_compiler,
4023 Mode::ToolStd,
4024 target,
4025 Kind::Run,
4026 "src/tools/test-float-parse",
4027 SourceType::InTree,
4028 &[],
4029 );
4030 cargo_run.allow_features(TEST_FLOAT_PARSE_ALLOW_FEATURES);
4031
4032 if !matches!(env::var("FLOAT_PARSE_TESTS_NO_SKIP_HUGE").as_deref(), Ok("1") | Ok("true")) {
4033 cargo_run.args(["--", "--skip-huge"]);
4034 }
4035
4036 cargo_run.into_cmd().run(builder);
4037 }
4038}
4039
4040#[derive(Debug, Clone, Hash, PartialEq, Eq)]
4044pub struct CollectLicenseMetadata;
4045
4046impl Step for CollectLicenseMetadata {
4047 type Output = PathBuf;
4048 const IS_HOST: bool = true;
4049
4050 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
4051 run.path("src/tools/collect-license-metadata")
4052 }
4053
4054 fn make_run(run: RunConfig<'_>) {
4055 run.builder.ensure(CollectLicenseMetadata);
4056 }
4057
4058 fn run(self, builder: &Builder<'_>) -> Self::Output {
4059 let Some(reuse) = &builder.config.reuse else {
4060 panic!("REUSE is required to collect the license metadata");
4061 };
4062
4063 let dest = builder.src.join("license-metadata.json");
4064
4065 let mut cmd = builder.tool_cmd(Tool::CollectLicenseMetadata);
4066 cmd.env("REUSE_EXE", reuse);
4067 cmd.env("DEST", &dest);
4068 cmd.env("ONLY_CHECK", "1");
4069 cmd.run(builder);
4070
4071 dest
4072 }
4073}
4074
4075#[derive(Debug, Clone, PartialEq, Eq, Hash)]
4076pub struct RemoteTestClientTests {
4077 host: TargetSelection,
4078}
4079
4080impl Step for RemoteTestClientTests {
4081 type Output = ();
4082 const IS_HOST: bool = true;
4083
4084 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
4085 run.path("src/tools/remote-test-client")
4086 }
4087
4088 fn is_default_step(_builder: &Builder<'_>) -> bool {
4089 true
4090 }
4091
4092 fn make_run(run: RunConfig<'_>) {
4093 run.builder.ensure(Self { host: run.target });
4094 }
4095
4096 fn run(self, builder: &Builder<'_>) {
4097 let bootstrap_host = builder.config.host_target;
4098 let compiler = builder.compiler(0, bootstrap_host);
4099
4100 let cargo = tool::prepare_tool_cargo(
4101 builder,
4102 compiler,
4103 Mode::ToolBootstrap,
4104 bootstrap_host,
4105 Kind::Test,
4106 "src/tools/remote-test-client",
4107 SourceType::InTree,
4108 &[],
4109 );
4110
4111 run_cargo_test(cargo, &[], &[], "remote-test-client", bootstrap_host, builder);
4112 }
4113}