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 tool_result = builder.ensure(tool::Rustfmt::from_compilers(self.compilers));
528 let build_compiler = tool_result.build_compiler;
529 let target = self.compilers.target();
530
531 let mut cargo = tool::prepare_tool_cargo(
532 builder,
533 build_compiler,
534 Mode::ToolRustcPrivate,
535 target,
536 Kind::Test,
537 "src/tools/rustfmt",
538 SourceType::InTree,
539 &[],
540 );
541
542 let dir = testdir(builder, target);
543 t!(fs::create_dir_all(&dir));
544 cargo.env("RUSTFMT_TEST_DIR", dir);
545
546 cargo.add_rustc_lib_path(builder);
547
548 run_cargo_test(cargo, &[], &[], "rustfmt", target, builder);
549 }
550
551 fn metadata(&self) -> Option<StepMetadata> {
552 Some(
553 StepMetadata::test("rustfmt", self.compilers.target())
554 .built_by(self.compilers.build_compiler()),
555 )
556 }
557}
558
559#[derive(Debug, Clone, PartialEq, Eq, Hash)]
560pub struct Miri {
561 target: TargetSelection,
562}
563
564impl Miri {
565 pub fn build_miri_sysroot(
567 builder: &Builder<'_>,
568 compiler: Compiler,
569 target: TargetSelection,
570 ) -> PathBuf {
571 let miri_sysroot = builder.out.join(compiler.host).join("miri-sysroot");
572 let mut cargo = builder::Cargo::new(
573 builder,
574 compiler,
575 Mode::Std,
576 SourceType::Submodule,
577 target,
578 Kind::MiriSetup,
579 );
580
581 cargo.env("MIRI_LIB_SRC", builder.src.join("library"));
583 cargo.env("MIRI_SYSROOT", &miri_sysroot);
585
586 let mut cargo = BootstrapCommand::from(cargo);
587 let _guard =
588 builder.msg(Kind::Build, "miri sysroot", Mode::ToolRustcPrivate, compiler, target);
589 cargo.run(builder);
590
591 cargo.arg("--print-sysroot");
597
598 builder.do_if_verbose(|| println!("running: {cargo:?}"));
599 let stdout = cargo.run_capture_stdout(builder).stdout();
600 let sysroot = stdout.trim_end();
602 builder.do_if_verbose(|| println!("`cargo miri setup --print-sysroot` said: {sysroot:?}"));
603 PathBuf::from(sysroot)
604 }
605}
606
607impl Step for Miri {
608 type Output = ();
609
610 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
611 run.path("src/tools/miri")
612 }
613
614 fn make_run(run: RunConfig<'_>) {
615 run.builder.ensure(Miri { target: run.target });
616 }
617
618 fn run(self, builder: &Builder<'_>) {
620 let host = builder.build.host_target;
621 let target = self.target;
622 let stage = builder.top_stage;
623 if stage == 0 {
624 eprintln!("miri cannot be tested at stage 0");
625 std::process::exit(1);
626 }
627
628 let compilers = RustcPrivateCompilers::new(builder, stage, host);
630
631 let miri = builder.ensure(tool::Miri::from_compilers(compilers));
633 builder.ensure(tool::CargoMiri::from_compilers(compilers));
635
636 let target_compiler = compilers.target_compiler();
637
638 let miri_sysroot = Miri::build_miri_sysroot(builder, target_compiler, target);
641 builder.std(target_compiler, host);
642 let host_sysroot = builder.sysroot(target_compiler);
643
644 if !builder.config.dry_run() {
647 let ui_test_dep_dir = builder
650 .stage_out(miri.build_compiler, Mode::ToolStd)
651 .join(host)
652 .join("tmp")
653 .join("miri_ui");
654 build_stamp::clear_if_dirty(builder, &ui_test_dep_dir, &miri_sysroot);
658 }
659
660 let mut cargo = tool::prepare_tool_cargo(
663 builder,
664 miri.build_compiler,
665 Mode::ToolRustcPrivate,
666 host,
667 Kind::Test,
668 "src/tools/miri",
669 SourceType::InTree,
670 &[],
671 );
672
673 cargo.add_rustc_lib_path(builder);
674
675 let mut cargo = prepare_cargo_test(cargo, &[], &[], host, builder);
678
679 cargo.env("MIRI_SYSROOT", &miri_sysroot);
681 cargo.env("MIRI_HOST_SYSROOT", &host_sysroot);
682 cargo.env("MIRI", &miri.tool_path);
683
684 cargo.env("MIRI_TEST_TARGET", target.rustc_target_arg());
686
687 {
688 let _guard = builder.msg_test("miri", target, target_compiler.stage);
689 let _time = helpers::timeit(builder);
690 cargo.run(builder);
691 }
692
693 if builder.config.test_args().is_empty() {
695 cargo.env("MIRIFLAGS", "-O -Zmir-opt-level=4 -Cdebug-assertions=yes");
696 cargo.env("MIRI_SKIP_UI_CHECKS", "1");
698 cargo.env_remove("RUSTC_BLESS");
700 cargo.args(["tests/pass", "tests/panic"]);
702
703 {
704 let _guard =
705 builder.msg_test("miri (mir-opt-level 4)", target, target_compiler.stage);
706 let _time = helpers::timeit(builder);
707 cargo.run(builder);
708 }
709 }
710 }
711}
712
713#[derive(Debug, Clone, PartialEq, Eq, Hash)]
716pub struct CargoMiri {
717 target: TargetSelection,
718}
719
720impl Step for CargoMiri {
721 type Output = ();
722
723 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
724 run.path("src/tools/miri/cargo-miri")
725 }
726
727 fn make_run(run: RunConfig<'_>) {
728 run.builder.ensure(CargoMiri { target: run.target });
729 }
730
731 fn run(self, builder: &Builder<'_>) {
733 let host = builder.build.host_target;
734 let target = self.target;
735 let stage = builder.top_stage;
736 if stage == 0 {
737 eprintln!("cargo-miri cannot be tested at stage 0");
738 std::process::exit(1);
739 }
740
741 let build_compiler = builder.compiler(stage, host);
743
744 let mut cargo = tool::prepare_tool_cargo(
749 builder,
750 build_compiler,
751 Mode::ToolStd, target,
753 Kind::MiriTest,
754 "src/tools/miri/test-cargo-miri",
755 SourceType::Submodule,
756 &[],
757 );
758
759 match builder.doc_tests {
762 DocTests::Yes => {}
763 DocTests::No => {
764 cargo.args(["--lib", "--bins", "--examples", "--tests", "--benches"]);
765 }
766 DocTests::Only => {
767 cargo.arg("--doc");
768 }
769 }
770 cargo.arg("--").args(builder.config.test_args());
771
772 let mut cargo = BootstrapCommand::from(cargo);
774 {
775 let _guard = builder.msg_test("cargo-miri", target, stage);
776 let _time = helpers::timeit(builder);
777 cargo.run(builder);
778 }
779 }
780}
781
782#[derive(Debug, Clone, PartialEq, Eq, Hash)]
783pub struct CompiletestTest {
784 host: TargetSelection,
785}
786
787impl Step for CompiletestTest {
788 type Output = ();
789
790 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
791 run.path("src/tools/compiletest")
792 }
793
794 fn make_run(run: RunConfig<'_>) {
795 run.builder.ensure(CompiletestTest { host: run.target });
796 }
797
798 fn run(self, builder: &Builder<'_>) {
800 let host = self.host;
801
802 if builder.top_stage == 0 && !builder.config.compiletest_allow_stage0 {
808 eprintln!("\
809ERROR: `--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
810NOTE: 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`."
811 );
812 crate::exit!(1);
813 }
814
815 let bootstrap_compiler = builder.compiler(0, host);
816 let staged_compiler = builder.compiler(builder.top_stage, host);
817
818 let mut cargo = tool::prepare_tool_cargo(
819 builder,
820 bootstrap_compiler,
821 Mode::ToolBootstrap,
822 host,
823 Kind::Test,
824 "src/tools/compiletest",
825 SourceType::InTree,
826 &[],
827 );
828
829 cargo.env("TEST_RUSTC", builder.rustc(staged_compiler));
833
834 run_cargo_test(cargo, &[], &[], "compiletest self test", host, builder);
835 }
836}
837
838#[derive(Debug, Clone, PartialEq, Eq, Hash)]
839pub struct Clippy {
840 compilers: RustcPrivateCompilers,
841}
842
843impl Step for Clippy {
844 type Output = ();
845 const IS_HOST: bool = true;
846
847 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
848 run.suite_path("src/tools/clippy/tests").path("src/tools/clippy")
849 }
850
851 fn is_default_step(_builder: &Builder<'_>) -> bool {
852 false
853 }
854
855 fn make_run(run: RunConfig<'_>) {
856 run.builder.ensure(Clippy {
857 compilers: RustcPrivateCompilers::new(
858 run.builder,
859 run.builder.top_stage,
860 run.builder.host_target,
861 ),
862 });
863 }
864
865 fn run(self, builder: &Builder<'_>) {
867 let target = self.compilers.target();
868
869 let compilers = self.compilers;
873 let target_compiler = compilers.target_compiler();
874
875 let tool_result = builder.ensure(tool::Clippy::from_compilers(compilers));
876 let build_compiler = tool_result.build_compiler;
877 let mut cargo = tool::prepare_tool_cargo(
878 builder,
879 build_compiler,
880 Mode::ToolRustcPrivate,
881 target,
882 Kind::Test,
883 "src/tools/clippy",
884 SourceType::InTree,
885 &[],
886 );
887
888 cargo.env("RUSTC_TEST_SUITE", builder.rustc(build_compiler));
889 cargo.env("RUSTC_LIB_PATH", builder.rustc_libdir(build_compiler));
890 let host_libs =
891 builder.stage_out(build_compiler, Mode::ToolRustcPrivate).join(builder.cargo_dir());
892 cargo.env("HOST_LIBS", host_libs);
893
894 builder.std(target_compiler, target);
896 cargo.env("TEST_SYSROOT", builder.sysroot(target_compiler));
897 cargo.env("TEST_RUSTC", builder.rustc(target_compiler));
898 cargo.env("TEST_RUSTC_LIB", builder.rustc_libdir(target_compiler));
899
900 'partially_test: {
902 let paths = &builder.config.paths[..];
903 let mut test_names = Vec::new();
904 for path in paths {
905 if let Some(path) =
906 helpers::is_valid_test_suite_arg(path, "src/tools/clippy/tests", builder)
907 {
908 test_names.push(path);
909 } else if path.ends_with("src/tools/clippy") {
910 break 'partially_test;
912 }
913 }
914 cargo.env("TESTNAME", test_names.join(","));
915 }
916
917 cargo.add_rustc_lib_path(builder);
918 let cargo = prepare_cargo_test(cargo, &[], &[], target, builder);
919
920 let _guard = builder.msg_test("clippy", target, target_compiler.stage);
921
922 if cargo.allow_failure().run(builder) {
924 return;
926 }
927
928 if !builder.config.cmd.bless() {
929 crate::exit!(1);
930 }
931 }
932
933 fn metadata(&self) -> Option<StepMetadata> {
934 Some(
935 StepMetadata::test("clippy", self.compilers.target())
936 .built_by(self.compilers.build_compiler()),
937 )
938 }
939}
940
941fn bin_path_for_cargo(builder: &Builder<'_>, compiler: Compiler) -> OsString {
942 let path = builder.sysroot(compiler).join("bin");
943 let old_path = env::var_os("PATH").unwrap_or_default();
944 env::join_paths(iter::once(path).chain(env::split_paths(&old_path))).expect("")
945}
946
947#[derive(Debug, Clone, Hash, PartialEq, Eq)]
949pub struct RustdocTheme {
950 test_compiler: Compiler,
952}
953
954impl Step for RustdocTheme {
955 type Output = ();
956 const IS_HOST: bool = true;
957
958 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
959 run.path("src/tools/rustdoc-themes")
960 }
961
962 fn is_default_step(_builder: &Builder<'_>) -> bool {
963 true
964 }
965
966 fn make_run(run: RunConfig<'_>) {
967 let test_compiler = run.builder.compiler(run.builder.top_stage, run.target);
968
969 run.builder.ensure(RustdocTheme { test_compiler });
970 }
971
972 fn run(self, builder: &Builder<'_>) {
973 let rustdoc = builder.bootstrap_out.join("rustdoc");
974 let mut cmd = builder.tool_cmd(Tool::RustdocTheme);
975 cmd.arg(rustdoc.to_str().unwrap())
976 .arg(builder.src.join("src/librustdoc/html/static/css/rustdoc.css").to_str().unwrap())
977 .env("RUSTC_STAGE", self.test_compiler.stage.to_string())
978 .env("RUSTC_SYSROOT", builder.sysroot(self.test_compiler))
979 .env(
980 "RUSTDOC_LIBDIR",
981 builder.sysroot_target_libdir(self.test_compiler, self.test_compiler.host),
982 )
983 .env("CFG_RELEASE_CHANNEL", &builder.config.channel)
984 .env("RUSTDOC_REAL", builder.rustdoc_for_compiler(self.test_compiler))
985 .env("RUSTC_BOOTSTRAP", "1");
986 cmd.args(linker_args(builder, self.test_compiler.host, LldThreads::No));
987
988 cmd.delay_failure().run(builder);
989 }
990
991 fn metadata(&self) -> Option<StepMetadata> {
992 Some(
993 StepMetadata::test("rustdoc-theme", self.test_compiler.host)
994 .stage(self.test_compiler.stage),
995 )
996 }
997}
998
999#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1001pub struct RustdocJSStd {
1002 build_compiler: Compiler,
1004 target: TargetSelection,
1005}
1006
1007impl Step for RustdocJSStd {
1008 type Output = ();
1009 const IS_HOST: bool = true;
1010
1011 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1012 run.suite_path("tests/rustdoc-js-std")
1013 }
1014
1015 fn is_default_step(builder: &Builder<'_>) -> bool {
1016 builder.config.nodejs.is_some()
1017 }
1018
1019 fn make_run(run: RunConfig<'_>) {
1020 run.builder.ensure(RustdocJSStd {
1021 build_compiler: run.builder.compiler(run.builder.top_stage, run.builder.host_target),
1022 target: run.target,
1023 });
1024 }
1025
1026 fn run(self, builder: &Builder<'_>) {
1027 let nodejs =
1028 builder.config.nodejs.as_ref().expect("need nodejs to run rustdoc-js-std tests");
1029 let mut command = command(nodejs);
1030 command
1031 .arg(builder.src.join("src/tools/rustdoc-js/tester.js"))
1032 .arg("--crate-name")
1033 .arg("std")
1034 .arg("--resource-suffix")
1035 .arg(&builder.version)
1036 .arg("--doc-folder")
1037 .arg(builder.doc_out(self.target))
1038 .arg("--test-folder")
1039 .arg(builder.src.join("tests/rustdoc-js-std"));
1040 for path in &builder.paths {
1041 if let Some(p) = helpers::is_valid_test_suite_arg(path, "tests/rustdoc-js-std", builder)
1042 {
1043 if !p.ends_with(".js") {
1044 eprintln!("A non-js file was given: `{}`", path.display());
1045 panic!("Cannot run rustdoc-js-std tests");
1046 }
1047 command.arg("--test-file").arg(path);
1048 }
1049 }
1050 builder.ensure(crate::core::build_steps::doc::Std::from_build_compiler(
1051 self.build_compiler,
1052 self.target,
1053 DocumentationFormat::Html,
1054 ));
1055 let _guard = builder.msg_test("rustdoc-js-std", self.target, self.build_compiler.stage);
1056 command.run(builder);
1057 }
1058
1059 fn metadata(&self) -> Option<StepMetadata> {
1060 Some(StepMetadata::test("rustdoc-js-std", self.target).stage(self.build_compiler.stage))
1061 }
1062}
1063
1064#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1065pub struct RustdocJSNotStd {
1066 pub target: TargetSelection,
1067 pub compiler: Compiler,
1068}
1069
1070impl Step for RustdocJSNotStd {
1071 type Output = ();
1072 const IS_HOST: bool = true;
1073
1074 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1075 run.suite_path("tests/rustdoc-js")
1076 }
1077
1078 fn is_default_step(builder: &Builder<'_>) -> bool {
1079 builder.config.nodejs.is_some()
1080 }
1081
1082 fn make_run(run: RunConfig<'_>) {
1083 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1084 run.builder.ensure(RustdocJSNotStd { target: run.target, compiler });
1085 }
1086
1087 fn run(self, builder: &Builder<'_>) {
1088 builder.ensure(Compiletest {
1089 test_compiler: self.compiler,
1090 target: self.target,
1091 mode: "rustdoc-js",
1092 suite: "rustdoc-js",
1093 path: "tests/rustdoc-js",
1094 compare_mode: None,
1095 });
1096 }
1097}
1098
1099fn get_browser_ui_test_version_inner(
1100 builder: &Builder<'_>,
1101 yarn: &Path,
1102 global: bool,
1103) -> Option<String> {
1104 let mut command = command(yarn);
1105 command
1106 .arg("--cwd")
1107 .arg(&builder.build.out)
1108 .arg("list")
1109 .arg("--parseable")
1110 .arg("--long")
1111 .arg("--depth=0");
1112 if global {
1113 command.arg("--global");
1114 }
1115 let lines = command.allow_failure().cached().run_capture(builder).stdout();
1118 lines
1119 .lines()
1120 .find_map(|l| l.split(':').nth(1)?.strip_prefix("browser-ui-test@"))
1121 .map(|v| v.to_owned())
1122}
1123
1124fn get_browser_ui_test_version(builder: &Builder<'_>) -> Option<String> {
1125 let yarn = builder.config.yarn.as_deref()?;
1126 get_browser_ui_test_version_inner(builder, yarn, false)
1127 .or_else(|| get_browser_ui_test_version_inner(builder, yarn, true))
1128}
1129
1130#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1132pub struct RustdocGUI {
1133 test_compiler: Compiler,
1135 target: TargetSelection,
1136}
1137
1138impl Step for RustdocGUI {
1139 type Output = ();
1140 const IS_HOST: bool = true;
1141
1142 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1143 run.suite_path("tests/rustdoc-gui")
1144 }
1145
1146 fn is_default_step(builder: &Builder<'_>) -> bool {
1147 builder.config.nodejs.is_some()
1148 && builder.doc_tests != DocTests::Only
1149 && get_browser_ui_test_version(builder).is_some()
1150 }
1151
1152 fn make_run(run: RunConfig<'_>) {
1153 let test_compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1154 run.builder.ensure(RustdocGUI { test_compiler, target: run.target });
1155 }
1156
1157 fn run(self, builder: &Builder<'_>) {
1158 builder.std(self.test_compiler, self.target);
1159
1160 let mut cmd = builder.tool_cmd(Tool::RustdocGUITest);
1161
1162 let out_dir = builder.test_out(self.target).join("rustdoc-gui");
1163 build_stamp::clear_if_dirty(
1164 builder,
1165 &out_dir,
1166 &builder.rustdoc_for_compiler(self.test_compiler),
1167 );
1168
1169 if let Some(src) = builder.config.src.to_str() {
1170 cmd.arg("--rust-src").arg(src);
1171 }
1172
1173 if let Some(out_dir) = out_dir.to_str() {
1174 cmd.arg("--out-dir").arg(out_dir);
1175 }
1176
1177 if let Some(initial_cargo) = builder.config.initial_cargo.to_str() {
1178 cmd.arg("--initial-cargo").arg(initial_cargo);
1179 }
1180
1181 cmd.arg("--jobs").arg(builder.jobs().to_string());
1182
1183 cmd.env("RUSTDOC", builder.rustdoc_for_compiler(self.test_compiler))
1184 .env("RUSTC", builder.rustc(self.test_compiler));
1185
1186 add_rustdoc_cargo_linker_args(&mut cmd, builder, self.test_compiler.host, LldThreads::No);
1187
1188 for path in &builder.paths {
1189 if let Some(p) = helpers::is_valid_test_suite_arg(path, "tests/rustdoc-gui", builder) {
1190 if !p.ends_with(".goml") {
1191 eprintln!("A non-goml file was given: `{}`", path.display());
1192 panic!("Cannot run rustdoc-gui tests");
1193 }
1194 if let Some(name) = path.file_name().and_then(|f| f.to_str()) {
1195 cmd.arg("--goml-file").arg(name);
1196 }
1197 }
1198 }
1199
1200 for test_arg in builder.config.test_args() {
1201 cmd.arg("--test-arg").arg(test_arg);
1202 }
1203
1204 if let Some(ref nodejs) = builder.config.nodejs {
1205 cmd.arg("--nodejs").arg(nodejs);
1206 }
1207
1208 if let Some(ref yarn) = builder.config.yarn {
1209 cmd.arg("--yarn").arg(yarn);
1210 }
1211
1212 let _time = helpers::timeit(builder);
1213 let _guard = builder.msg_test("rustdoc-gui", self.target, self.test_compiler.stage);
1214 try_run_tests(builder, &mut cmd, true);
1215 }
1216
1217 fn metadata(&self) -> Option<StepMetadata> {
1218 Some(StepMetadata::test("rustdoc-gui", self.target).stage(self.test_compiler.stage))
1219 }
1220}
1221
1222#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1227pub struct Tidy;
1228
1229impl Step for Tidy {
1230 type Output = ();
1231 const IS_HOST: bool = true;
1232
1233 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1234 run.path("src/tools/tidy")
1235 }
1236
1237 fn is_default_step(builder: &Builder<'_>) -> bool {
1238 builder.doc_tests != DocTests::Only
1239 }
1240
1241 fn make_run(run: RunConfig<'_>) {
1242 run.builder.ensure(Tidy);
1243 }
1244
1245 fn run(self, builder: &Builder<'_>) {
1254 let mut cmd = builder.tool_cmd(Tool::Tidy);
1255 cmd.arg(&builder.src);
1256 cmd.arg(&builder.initial_cargo);
1257 cmd.arg(&builder.out);
1258 let jobs = builder.config.jobs.unwrap_or_else(|| {
1260 8 * std::thread::available_parallelism().map_or(1, std::num::NonZeroUsize::get) as u32
1261 });
1262 cmd.arg(jobs.to_string());
1263 if let Some(yarn) = &builder.config.yarn {
1265 cmd.arg(yarn);
1266 } else {
1267 cmd.arg("yarn");
1268 }
1269 if builder.is_verbose() {
1270 cmd.arg("--verbose");
1271 }
1272 if builder.config.cmd.bless() {
1273 cmd.arg("--bless");
1274 }
1275 if let Some(s) =
1276 builder.config.cmd.extra_checks().or(builder.config.tidy_extra_checks.as_deref())
1277 {
1278 cmd.arg(format!("--extra-checks={s}"));
1279 }
1280 let mut args = std::env::args_os();
1281 if args.any(|arg| arg == OsStr::new("--")) {
1282 cmd.arg("--");
1283 cmd.args(args);
1284 }
1285
1286 if builder.config.channel == "dev" || builder.config.channel == "nightly" {
1287 if !builder.config.json_output {
1288 builder.info("fmt check");
1289 if builder.config.initial_rustfmt.is_none() {
1290 let inferred_rustfmt_dir = builder.initial_sysroot.join("bin");
1291 eprintln!(
1292 "\
1293ERROR: no `rustfmt` binary found in {PATH}
1294INFO: `rust.channel` is currently set to \"{CHAN}\"
1295HELP: if you are testing a beta branch, set `rust.channel` to \"beta\" in the `bootstrap.toml` file
1296HELP: to skip test's attempt to check tidiness, pass `--skip src/tools/tidy` to `x.py test`",
1297 PATH = inferred_rustfmt_dir.display(),
1298 CHAN = builder.config.channel,
1299 );
1300 crate::exit!(1);
1301 }
1302 let all = false;
1303 crate::core::build_steps::format::format(
1304 builder,
1305 !builder.config.cmd.bless(),
1306 all,
1307 &[],
1308 );
1309 } else {
1310 eprintln!(
1311 "WARNING: `--json-output` is not supported on rustfmt, formatting will be skipped"
1312 );
1313 }
1314 }
1315
1316 builder.info("tidy check");
1317 cmd.delay_failure().run(builder);
1318
1319 builder.info("x.py completions check");
1320 let completion_paths = get_completion_paths(builder);
1321 if builder.config.cmd.bless() {
1322 builder.ensure(crate::core::build_steps::run::GenerateCompletions);
1323 } else if completion_paths
1324 .into_iter()
1325 .any(|(shell, path)| get_completion(shell, &path).is_some())
1326 {
1327 eprintln!(
1328 "x.py completions were changed; run `x.py run generate-completions` to update them"
1329 );
1330 crate::exit!(1);
1331 }
1332
1333 builder.info("x.py help check");
1334 if builder.config.cmd.bless() {
1335 builder.ensure(crate::core::build_steps::run::GenerateHelp);
1336 } else {
1337 let help_path = get_help_path(builder);
1338 let cur_help = std::fs::read_to_string(&help_path).unwrap_or_else(|err| {
1339 eprintln!("couldn't read {}: {}", help_path.display(), err);
1340 crate::exit!(1);
1341 });
1342 let new_help = top_level_help();
1343
1344 if new_help != cur_help {
1345 eprintln!("x.py help was changed; run `x.py run generate-help` to update it");
1346 crate::exit!(1);
1347 }
1348 }
1349 }
1350
1351 fn metadata(&self) -> Option<StepMetadata> {
1352 Some(StepMetadata::test("tidy", TargetSelection::default()))
1353 }
1354}
1355
1356#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1359pub struct CrateRunMakeSupport {
1360 host: TargetSelection,
1361}
1362
1363impl Step for CrateRunMakeSupport {
1364 type Output = ();
1365 const IS_HOST: bool = true;
1366
1367 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1368 run.path("src/tools/run-make-support")
1369 }
1370
1371 fn make_run(run: RunConfig<'_>) {
1372 run.builder.ensure(CrateRunMakeSupport { host: run.target });
1373 }
1374
1375 fn run(self, builder: &Builder<'_>) {
1377 let host = self.host;
1378 let compiler = builder.compiler(0, host);
1379
1380 let mut cargo = tool::prepare_tool_cargo(
1381 builder,
1382 compiler,
1383 Mode::ToolBootstrap,
1384 host,
1385 Kind::Test,
1386 "src/tools/run-make-support",
1387 SourceType::InTree,
1388 &[],
1389 );
1390 cargo.allow_features("test");
1391 run_cargo_test(cargo, &[], &[], "run-make-support self test", host, builder);
1392 }
1393}
1394
1395#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1396pub struct CrateBuildHelper {
1397 host: TargetSelection,
1398}
1399
1400impl Step for CrateBuildHelper {
1401 type Output = ();
1402 const IS_HOST: bool = true;
1403
1404 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1405 run.path("src/build_helper")
1406 }
1407
1408 fn make_run(run: RunConfig<'_>) {
1409 run.builder.ensure(CrateBuildHelper { host: run.target });
1410 }
1411
1412 fn run(self, builder: &Builder<'_>) {
1414 let host = self.host;
1415 let compiler = builder.compiler(0, host);
1416
1417 let mut cargo = tool::prepare_tool_cargo(
1418 builder,
1419 compiler,
1420 Mode::ToolBootstrap,
1421 host,
1422 Kind::Test,
1423 "src/build_helper",
1424 SourceType::InTree,
1425 &[],
1426 );
1427 cargo.allow_features("test");
1428 run_cargo_test(cargo, &[], &[], "build_helper self test", host, builder);
1429 }
1430}
1431
1432fn testdir(builder: &Builder<'_>, host: TargetSelection) -> PathBuf {
1433 builder.out.join(host).join("test")
1434}
1435
1436macro_rules! test {
1438 (
1439 $( #[$attr:meta] )* $name:ident {
1441 path: $path:expr,
1442 mode: $mode:expr,
1443 suite: $suite:expr,
1444 default: $default:expr
1445 $( , IS_HOST: $IS_HOST:expr )? $( , compare_mode: $compare_mode:expr )? $( , )? }
1449 ) => {
1450 $( #[$attr] )*
1451 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
1452 pub struct $name {
1453 test_compiler: Compiler,
1454 target: TargetSelection,
1455 }
1456
1457 impl Step for $name {
1458 type Output = ();
1459 const IS_HOST: bool = (const {
1460 #[allow(unused_assignments, unused_mut)]
1461 let mut value = false;
1462 $( value = $IS_HOST; )?
1463 value
1464 });
1465
1466 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1467 run.suite_path($path)
1468 }
1469
1470 fn is_default_step(_builder: &Builder<'_>) -> bool {
1471 const { $default }
1472 }
1473
1474 fn make_run(run: RunConfig<'_>) {
1475 let test_compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1476
1477 run.builder.ensure($name { test_compiler, target: run.target });
1478 }
1479
1480 fn run(self, builder: &Builder<'_>) {
1481 builder.ensure(Compiletest {
1482 test_compiler: self.test_compiler,
1483 target: self.target,
1484 mode: $mode,
1485 suite: $suite,
1486 path: $path,
1487 compare_mode: (const {
1488 #[allow(unused_assignments, unused_mut)]
1489 let mut value = None;
1490 $( value = $compare_mode; )?
1491 value
1492 }),
1493 })
1494 }
1495 }
1496 };
1497}
1498
1499test!(Ui { path: "tests/ui", mode: "ui", suite: "ui", default: true });
1500
1501test!(Crashes { path: "tests/crashes", mode: "crashes", suite: "crashes", default: true });
1502
1503test!(CodegenLlvm {
1504 path: "tests/codegen-llvm",
1505 mode: "codegen",
1506 suite: "codegen-llvm",
1507 default: true
1508});
1509
1510test!(CodegenUnits {
1511 path: "tests/codegen-units",
1512 mode: "codegen-units",
1513 suite: "codegen-units",
1514 default: true,
1515});
1516
1517test!(Incremental {
1518 path: "tests/incremental",
1519 mode: "incremental",
1520 suite: "incremental",
1521 default: true,
1522});
1523
1524test!(Debuginfo {
1525 path: "tests/debuginfo",
1526 mode: "debuginfo",
1527 suite: "debuginfo",
1528 default: true,
1529 compare_mode: Some("split-dwarf"),
1530});
1531
1532test!(UiFullDeps {
1533 path: "tests/ui-fulldeps",
1534 mode: "ui",
1535 suite: "ui-fulldeps",
1536 default: true,
1537 IS_HOST: true,
1538});
1539
1540test!(Rustdoc {
1541 path: "tests/rustdoc",
1542 mode: "rustdoc",
1543 suite: "rustdoc",
1544 default: true,
1545 IS_HOST: true,
1546});
1547test!(RustdocUi {
1548 path: "tests/rustdoc-ui",
1549 mode: "ui",
1550 suite: "rustdoc-ui",
1551 default: true,
1552 IS_HOST: true,
1553});
1554
1555test!(RustdocJson {
1556 path: "tests/rustdoc-json",
1557 mode: "rustdoc-json",
1558 suite: "rustdoc-json",
1559 default: true,
1560 IS_HOST: true,
1561});
1562
1563test!(Pretty {
1564 path: "tests/pretty",
1565 mode: "pretty",
1566 suite: "pretty",
1567 default: true,
1568 IS_HOST: true,
1569});
1570
1571test!(RunMake { path: "tests/run-make", mode: "run-make", suite: "run-make", default: true });
1572test!(RunMakeCargo {
1573 path: "tests/run-make-cargo",
1574 mode: "run-make",
1575 suite: "run-make-cargo",
1576 default: true
1577});
1578
1579test!(AssemblyLlvm {
1580 path: "tests/assembly-llvm",
1581 mode: "assembly",
1582 suite: "assembly-llvm",
1583 default: true
1584});
1585
1586#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
1589pub struct Coverage {
1590 pub compiler: Compiler,
1591 pub target: TargetSelection,
1592 pub mode: &'static str,
1593}
1594
1595impl Coverage {
1596 const PATH: &'static str = "tests/coverage";
1597 const SUITE: &'static str = "coverage";
1598 const ALL_MODES: &[&str] = &["coverage-map", "coverage-run"];
1599}
1600
1601impl Step for Coverage {
1602 type Output = ();
1603 const IS_HOST: bool = false;
1605
1606 fn should_run(mut run: ShouldRun<'_>) -> ShouldRun<'_> {
1607 run = run.suite_path(Self::PATH);
1613 for mode in Self::ALL_MODES {
1614 run = run.alias(mode);
1615 }
1616 run
1617 }
1618
1619 fn is_default_step(_builder: &Builder<'_>) -> bool {
1620 true
1621 }
1622
1623 fn make_run(run: RunConfig<'_>) {
1624 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1625 let target = run.target;
1626
1627 let mut modes = vec![];
1631
1632 for path in &run.paths {
1635 match path {
1636 PathSet::Set(_) => {
1637 for mode in Self::ALL_MODES {
1638 if path.assert_single_path().path == Path::new(mode) {
1639 modes.push(mode);
1640 break;
1641 }
1642 }
1643 }
1644 PathSet::Suite(_) => {
1645 modes.extend(Self::ALL_MODES);
1646 break;
1647 }
1648 }
1649 }
1650
1651 modes.retain(|mode| !run.builder.config.skip.iter().any(|skip| skip == Path::new(mode)));
1654
1655 for mode in modes {
1663 run.builder.ensure(Coverage { compiler, target, mode });
1664 }
1665 }
1666
1667 fn run(self, builder: &Builder<'_>) {
1668 let Self { compiler, target, mode } = self;
1669 builder.ensure(Compiletest {
1672 test_compiler: compiler,
1673 target,
1674 mode,
1675 suite: Self::SUITE,
1676 path: Self::PATH,
1677 compare_mode: None,
1678 });
1679 }
1680}
1681
1682test!(CoverageRunRustdoc {
1683 path: "tests/coverage-run-rustdoc",
1684 mode: "coverage-run",
1685 suite: "coverage-run-rustdoc",
1686 default: true,
1687 IS_HOST: true,
1688});
1689
1690#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1692pub struct MirOpt {
1693 pub compiler: Compiler,
1694 pub target: TargetSelection,
1695}
1696
1697impl Step for MirOpt {
1698 type Output = ();
1699
1700 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1701 run.suite_path("tests/mir-opt")
1702 }
1703
1704 fn is_default_step(_builder: &Builder<'_>) -> bool {
1705 true
1706 }
1707
1708 fn make_run(run: RunConfig<'_>) {
1709 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1710 run.builder.ensure(MirOpt { compiler, target: run.target });
1711 }
1712
1713 fn run(self, builder: &Builder<'_>) {
1714 let run = |target| {
1715 builder.ensure(Compiletest {
1716 test_compiler: self.compiler,
1717 target,
1718 mode: "mir-opt",
1719 suite: "mir-opt",
1720 path: "tests/mir-opt",
1721 compare_mode: None,
1722 })
1723 };
1724
1725 run(self.target);
1726
1727 if builder.config.cmd.bless() {
1730 for target in ["aarch64-unknown-linux-gnu", "i686-pc-windows-msvc"] {
1736 run(TargetSelection::from_user(target));
1737 }
1738
1739 for target in ["x86_64-apple-darwin", "i686-unknown-linux-musl"] {
1740 let target = TargetSelection::from_user(target);
1741 let panic_abort_target = builder.ensure(MirOptPanicAbortSyntheticTarget {
1742 compiler: self.compiler,
1743 base: target,
1744 });
1745 run(panic_abort_target);
1746 }
1747 }
1748 }
1749}
1750
1751#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1757struct Compiletest {
1758 test_compiler: Compiler,
1760 target: TargetSelection,
1761 mode: &'static str,
1762 suite: &'static str,
1763 path: &'static str,
1764 compare_mode: Option<&'static str>,
1765}
1766
1767impl Step for Compiletest {
1768 type Output = ();
1769
1770 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1771 run.never()
1772 }
1773
1774 fn run(self, builder: &Builder<'_>) {
1775 if builder.doc_tests == DocTests::Only {
1776 return;
1777 }
1778
1779 if builder.top_stage == 0 && !builder.config.compiletest_allow_stage0 {
1780 eprintln!("\
1781ERROR: `--stage 0` runs compiletest on the stage0 (precompiled) compiler, not your local changes, and will almost always cause tests to fail
1782HELP: to test the compiler or standard library, omit the stage or explicitly use `--stage 1` instead
1783NOTE: 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`."
1784 );
1785 crate::exit!(1);
1786 }
1787
1788 let mut test_compiler = self.test_compiler;
1789 let target = self.target;
1790 let mode = self.mode;
1791 let suite = self.suite;
1792
1793 let suite_path = self.path;
1795
1796 if !builder.config.codegen_tests && mode == "codegen" {
1798 return;
1799 }
1800
1801 let query_compiler;
1808 let (stage, stage_id) = if suite == "ui-fulldeps" && test_compiler.stage == 1 {
1809 query_compiler = Some(test_compiler);
1812 let build = builder.build.host_target;
1816 test_compiler = builder.compiler(test_compiler.stage - 1, build);
1817 let test_stage = test_compiler.stage + 1;
1818 (test_stage, format!("stage{test_stage}-{build}"))
1819 } else {
1820 query_compiler = None;
1821 let stage = test_compiler.stage;
1822 (stage, format!("stage{stage}-{target}"))
1823 };
1824
1825 if suite.ends_with("fulldeps") {
1826 builder.ensure(compile::Rustc::new(test_compiler, target));
1827 }
1828
1829 if suite == "debuginfo" {
1830 builder.ensure(dist::DebuggerScripts {
1831 sysroot: builder.sysroot(test_compiler).to_path_buf(),
1832 target,
1833 });
1834 }
1835 if mode == "run-make" {
1836 builder.tool_exe(Tool::RunMakeSupport);
1837 }
1838
1839 if suite == "mir-opt" {
1841 builder.ensure(
1842 compile::Std::new(test_compiler, test_compiler.host).is_for_mir_opt_tests(true),
1843 );
1844 } else {
1845 builder.std(test_compiler, test_compiler.host);
1846 }
1847
1848 let mut cmd = builder.tool_cmd(Tool::Compiletest);
1849
1850 if suite == "mir-opt" {
1851 builder.ensure(compile::Std::new(test_compiler, target).is_for_mir_opt_tests(true));
1852 } else {
1853 builder.std(test_compiler, target);
1854 }
1855
1856 builder.ensure(RemoteCopyLibs { build_compiler: test_compiler, target });
1857
1858 cmd.arg("--stage").arg(stage.to_string());
1862 cmd.arg("--stage-id").arg(stage_id);
1863
1864 cmd.arg("--compile-lib-path").arg(builder.rustc_libdir(test_compiler));
1865 cmd.arg("--run-lib-path").arg(builder.sysroot_target_libdir(test_compiler, target));
1866 cmd.arg("--rustc-path").arg(builder.rustc(test_compiler));
1867 if let Some(query_compiler) = query_compiler {
1868 cmd.arg("--query-rustc-path").arg(builder.rustc(query_compiler));
1869 }
1870
1871 cmd.arg("--minicore-path")
1874 .arg(builder.src.join("tests").join("auxiliary").join("minicore.rs"));
1875
1876 let is_rustdoc = suite == "rustdoc-ui" || suite == "rustdoc-js";
1877
1878 if mode == "run-make" {
1893 let stage0_rustc_path = builder.compiler(0, test_compiler.host);
1896 cmd.arg("--stage0-rustc-path").arg(builder.rustc(stage0_rustc_path));
1897
1898 if suite == "run-make-cargo" {
1899 let cargo_path = if test_compiler.stage == 0 {
1900 builder.initial_cargo.clone()
1902 } else {
1903 builder
1904 .ensure(tool::Cargo::from_build_compiler(
1905 builder.compiler(test_compiler.stage - 1, test_compiler.host),
1906 test_compiler.host,
1907 ))
1908 .tool_path
1909 };
1910
1911 cmd.arg("--cargo-path").arg(cargo_path);
1912 }
1913 }
1914
1915 if mode == "rustdoc"
1917 || mode == "run-make"
1918 || (mode == "ui" && is_rustdoc)
1919 || mode == "rustdoc-js"
1920 || mode == "rustdoc-json"
1921 || suite == "coverage-run-rustdoc"
1922 {
1923 cmd.arg("--rustdoc-path").arg(builder.rustdoc_for_compiler(test_compiler));
1924 }
1925
1926 if mode == "rustdoc-json" {
1927 let json_compiler = builder.compiler(0, builder.host_target);
1929 cmd.arg("--jsondocck-path")
1930 .arg(builder.ensure(tool::JsonDocCk { compiler: json_compiler, target }).tool_path);
1931 cmd.arg("--jsondoclint-path").arg(
1932 builder.ensure(tool::JsonDocLint { compiler: json_compiler, target }).tool_path,
1933 );
1934 }
1935
1936 if matches!(mode, "coverage-map" | "coverage-run") {
1937 let coverage_dump = builder.tool_exe(Tool::CoverageDump);
1938 cmd.arg("--coverage-dump-path").arg(coverage_dump);
1939 }
1940
1941 cmd.arg("--src-root").arg(&builder.src);
1942 cmd.arg("--src-test-suite-root").arg(builder.src.join("tests").join(suite));
1943
1944 cmd.arg("--build-root").arg(&builder.out);
1948 cmd.arg("--build-test-suite-root").arg(testdir(builder, test_compiler.host).join(suite));
1949
1950 let sysroot = if builder.top_stage == 0 {
1955 builder.initial_sysroot.clone()
1956 } else {
1957 builder.sysroot(test_compiler)
1958 };
1959
1960 cmd.arg("--sysroot-base").arg(sysroot);
1961
1962 cmd.arg("--suite").arg(suite);
1963 cmd.arg("--mode").arg(mode);
1964 cmd.arg("--target").arg(target.rustc_target_arg());
1965 cmd.arg("--host").arg(&*test_compiler.host.triple);
1966 cmd.arg("--llvm-filecheck").arg(builder.llvm_filecheck(builder.config.host_target));
1967
1968 if let Some(codegen_backend) = builder.config.cmd.test_codegen_backend() {
1969 if !builder
1970 .config
1971 .enabled_codegen_backends(test_compiler.host)
1972 .contains(codegen_backend)
1973 {
1974 eprintln!(
1975 "\
1976ERROR: No configured backend named `{name}`
1977HELP: You can add it into `bootstrap.toml` in `rust.codegen-backends = [{name:?}]`",
1978 name = codegen_backend.name(),
1979 );
1980 crate::exit!(1);
1981 }
1982
1983 if let CodegenBackendKind::Gcc = codegen_backend
1984 && builder.config.rustc_debug_assertions
1985 {
1986 eprintln!(
1987 r#"WARNING: Running tests with the GCC codegen backend while rustc debug assertions are enabled. This might lead to test failures.
1988Please disable assertions with `rust.debug-assertions = false`.
1989 "#
1990 );
1991 }
1992
1993 cmd.arg("--override-codegen-backend").arg(codegen_backend.name());
1996 cmd.arg("--default-codegen-backend").arg(codegen_backend.name());
1999 } else {
2000 cmd.arg("--default-codegen-backend")
2003 .arg(builder.config.default_codegen_backend(test_compiler.host).name());
2004 }
2005 if builder.config.cmd.bypass_ignore_backends() {
2006 cmd.arg("--bypass-ignore-backends");
2007 }
2008
2009 if builder.build.config.llvm_enzyme {
2010 cmd.arg("--has-enzyme");
2011 }
2012
2013 if builder.config.cmd.bless() {
2014 cmd.arg("--bless");
2015 }
2016
2017 if builder.config.cmd.force_rerun() {
2018 cmd.arg("--force-rerun");
2019 }
2020
2021 if builder.config.cmd.no_capture() {
2022 cmd.arg("--no-capture");
2023 }
2024
2025 let compare_mode =
2026 builder.config.cmd.compare_mode().or_else(|| {
2027 if builder.config.test_compare_mode { self.compare_mode } else { None }
2028 });
2029
2030 if let Some(ref pass) = builder.config.cmd.pass() {
2031 cmd.arg("--pass");
2032 cmd.arg(pass);
2033 }
2034
2035 if let Some(ref run) = builder.config.cmd.run() {
2036 cmd.arg("--run");
2037 cmd.arg(run);
2038 }
2039
2040 if let Some(ref nodejs) = builder.config.nodejs {
2041 cmd.arg("--nodejs").arg(nodejs);
2042 } else if mode == "rustdoc-js" {
2043 panic!("need nodejs to run rustdoc-js suite");
2044 }
2045 if builder.config.rust_optimize_tests {
2046 cmd.arg("--optimize-tests");
2047 }
2048 if builder.config.rust_randomize_layout {
2049 cmd.arg("--rust-randomized-layout");
2050 }
2051 if builder.config.cmd.only_modified() {
2052 cmd.arg("--only-modified");
2053 }
2054 if let Some(compiletest_diff_tool) = &builder.config.compiletest_diff_tool {
2055 cmd.arg("--compiletest-diff-tool").arg(compiletest_diff_tool);
2056 }
2057
2058 let mut flags = if is_rustdoc { Vec::new() } else { vec!["-Crpath".to_string()] };
2059 flags.push(format!(
2060 "-Cdebuginfo={}",
2061 if mode == "codegen" {
2062 if builder.config.rust_debuginfo_level_tests
2065 != crate::core::config::DebuginfoLevel::None
2066 {
2067 println!(
2068 "NOTE: ignoring `rust.debuginfo-level-tests={}` for codegen tests",
2069 builder.config.rust_debuginfo_level_tests
2070 );
2071 }
2072 crate::core::config::DebuginfoLevel::None
2073 } else {
2074 builder.config.rust_debuginfo_level_tests
2075 }
2076 ));
2077 flags.extend(builder.config.cmd.compiletest_rustc_args().iter().map(|s| s.to_string()));
2078
2079 if suite != "mir-opt" {
2080 if let Some(linker) = builder.linker(target) {
2081 cmd.arg("--target-linker").arg(linker);
2082 }
2083 if let Some(linker) = builder.linker(test_compiler.host) {
2084 cmd.arg("--host-linker").arg(linker);
2085 }
2086 }
2087
2088 if suite == "ui-fulldeps" && target.ends_with("darwin") {
2090 flags.push("-Alinker_messages".into());
2091 }
2092
2093 let mut hostflags = flags.clone();
2094 hostflags.extend(linker_flags(builder, test_compiler.host, LldThreads::No));
2095
2096 let mut targetflags = flags;
2097
2098 if suite == "ui" || suite == "incremental" {
2100 builder.ensure(TestHelpers { target: test_compiler.host });
2101 builder.ensure(TestHelpers { target });
2102 hostflags.push(format!(
2103 "-Lnative={}",
2104 builder.test_helpers_out(test_compiler.host).display()
2105 ));
2106 targetflags.push(format!("-Lnative={}", builder.test_helpers_out(target).display()));
2107 }
2108
2109 for flag in hostflags {
2110 cmd.arg("--host-rustcflags").arg(flag);
2111 }
2112 for flag in targetflags {
2113 cmd.arg("--target-rustcflags").arg(flag);
2114 }
2115
2116 cmd.arg("--python").arg(
2117 builder.config.python.as_ref().expect("python is required for running rustdoc tests"),
2118 );
2119
2120 if let Some(debuggers::Android { adb_path, adb_test_dir, android_cross_path }) =
2125 debuggers::discover_android(builder, target)
2126 {
2127 cmd.arg("--adb-path").arg(adb_path);
2128 cmd.arg("--adb-test-dir").arg(adb_test_dir);
2129 cmd.arg("--android-cross-path").arg(android_cross_path);
2130 }
2131
2132 if mode == "debuginfo" {
2133 if let Some(debuggers::Gdb { gdb }) = debuggers::discover_gdb(builder) {
2134 cmd.arg("--gdb").arg(gdb);
2135 }
2136
2137 if let Some(debuggers::Lldb { lldb_exe, lldb_version }) =
2138 debuggers::discover_lldb(builder)
2139 {
2140 cmd.arg("--lldb").arg(lldb_exe);
2141 cmd.arg("--lldb-version").arg(lldb_version);
2142 }
2143 }
2144
2145 if helpers::forcing_clang_based_tests() {
2146 let clang_exe = builder.llvm_out(target).join("bin").join("clang");
2147 cmd.arg("--run-clang-based-tests-with").arg(clang_exe);
2148 }
2149
2150 for exclude in &builder.config.skip {
2151 cmd.arg("--skip");
2152 cmd.arg(exclude);
2153 }
2154
2155 let mut paths = match &builder.config.cmd {
2157 Subcommand::Test { .. } => &builder.config.paths[..],
2158 _ => &[],
2159 };
2160
2161 let mut paths_v;
2164 if mode == "rustdoc-js" {
2165 paths_v = paths.to_vec();
2166 for p in &mut paths_v {
2167 if let Some(ext) = p.extension()
2168 && ext == "js"
2169 {
2170 p.set_extension("rs");
2171 }
2172 }
2173 paths = &paths_v;
2174 }
2175 let mut test_args: Vec<&str> = paths
2177 .iter()
2178 .filter_map(|p| helpers::is_valid_test_suite_arg(p, suite_path, builder))
2179 .collect();
2180
2181 test_args.append(&mut builder.config.test_args());
2182
2183 if cfg!(windows) {
2186 let test_args_win: Vec<String> =
2187 test_args.iter().map(|s| s.replace('/', "\\")).collect();
2188 cmd.args(&test_args_win);
2189 } else {
2190 cmd.args(&test_args);
2191 }
2192
2193 if builder.is_verbose() {
2194 cmd.arg("--verbose");
2195 }
2196
2197 if builder.config.rustc_debug_assertions {
2198 cmd.arg("--with-rustc-debug-assertions");
2199 }
2200
2201 if builder.config.std_debug_assertions {
2202 cmd.arg("--with-std-debug-assertions");
2203 }
2204
2205 let mut llvm_components_passed = false;
2206 let mut copts_passed = false;
2207 if builder.config.llvm_enabled(test_compiler.host) {
2208 let llvm::LlvmResult { host_llvm_config, .. } =
2209 builder.ensure(llvm::Llvm { target: builder.config.host_target });
2210 if !builder.config.dry_run() {
2211 let llvm_version = get_llvm_version(builder, &host_llvm_config);
2212 let llvm_components = command(&host_llvm_config)
2213 .cached()
2214 .arg("--components")
2215 .run_capture_stdout(builder)
2216 .stdout();
2217 cmd.arg("--llvm-version")
2219 .arg(llvm_version.trim())
2220 .arg("--llvm-components")
2221 .arg(llvm_components.trim());
2222 llvm_components_passed = true;
2223 }
2224 if !builder.config.is_rust_llvm(target) {
2225 cmd.arg("--system-llvm");
2226 }
2227
2228 if !builder.config.dry_run() && suite.ends_with("fulldeps") {
2233 let llvm_libdir = command(&host_llvm_config)
2234 .cached()
2235 .arg("--libdir")
2236 .run_capture_stdout(builder)
2237 .stdout();
2238 let link_llvm = if target.is_msvc() {
2239 format!("-Clink-arg=-LIBPATH:{llvm_libdir}")
2240 } else {
2241 format!("-Clink-arg=-L{llvm_libdir}")
2242 };
2243 cmd.arg("--host-rustcflags").arg(link_llvm);
2244 }
2245
2246 if !builder.config.dry_run() && matches!(mode, "run-make" | "coverage-run") {
2247 let llvm_bin_path = host_llvm_config
2252 .parent()
2253 .expect("Expected llvm-config to be contained in directory");
2254 assert!(llvm_bin_path.is_dir());
2255 cmd.arg("--llvm-bin-dir").arg(llvm_bin_path);
2256 }
2257
2258 if !builder.config.dry_run() && mode == "run-make" {
2259 if builder.config.lld_enabled {
2261 let lld_install_root =
2262 builder.ensure(llvm::Lld { target: builder.config.host_target });
2263
2264 let lld_bin_path = lld_install_root.join("bin");
2265
2266 let old_path = env::var_os("PATH").unwrap_or_default();
2267 let new_path = env::join_paths(
2268 std::iter::once(lld_bin_path).chain(env::split_paths(&old_path)),
2269 )
2270 .expect("Could not add LLD bin path to PATH");
2271 cmd.env("PATH", new_path);
2272 }
2273 }
2274 }
2275
2276 if !builder.config.dry_run() && mode == "run-make" {
2279 let mut cflags = builder.cc_handled_clags(target, CLang::C);
2280 cflags.extend(builder.cc_unhandled_cflags(target, GitRepo::Rustc, CLang::C));
2281 let mut cxxflags = builder.cc_handled_clags(target, CLang::Cxx);
2282 cxxflags.extend(builder.cc_unhandled_cflags(target, GitRepo::Rustc, CLang::Cxx));
2283 cmd.arg("--cc")
2284 .arg(builder.cc(target))
2285 .arg("--cxx")
2286 .arg(builder.cxx(target).unwrap())
2287 .arg("--cflags")
2288 .arg(cflags.join(" "))
2289 .arg("--cxxflags")
2290 .arg(cxxflags.join(" "));
2291 copts_passed = true;
2292 if let Some(ar) = builder.ar(target) {
2293 cmd.arg("--ar").arg(ar);
2294 }
2295 }
2296
2297 if !llvm_components_passed {
2298 cmd.arg("--llvm-components").arg("");
2299 }
2300 if !copts_passed {
2301 cmd.arg("--cc")
2302 .arg("")
2303 .arg("--cxx")
2304 .arg("")
2305 .arg("--cflags")
2306 .arg("")
2307 .arg("--cxxflags")
2308 .arg("");
2309 }
2310
2311 if builder.remote_tested(target) {
2312 cmd.arg("--remote-test-client").arg(builder.tool_exe(Tool::RemoteTestClient));
2313 } else if let Some(tool) = builder.runner(target) {
2314 cmd.arg("--runner").arg(tool);
2315 }
2316
2317 if suite != "mir-opt" {
2318 if !builder.config.dry_run() && target.is_msvc() {
2324 for (k, v) in builder.cc[&target].env() {
2325 if k != "PATH" {
2326 cmd.env(k, v);
2327 }
2328 }
2329 }
2330 }
2331
2332 if !builder.config.dry_run()
2334 && target.contains("msvc")
2335 && builder.config.sanitizers_enabled(target)
2336 {
2337 cmd.env("ASAN_WIN_CONTINUE_ON_INTERCEPTION_FAILURE", "1");
2340 let asan_runtime_path = builder.cc[&target].path().parent().unwrap().to_path_buf();
2342 let old_path = cmd
2343 .get_envs()
2344 .find_map(|(k, v)| (k == "PATH").then_some(v))
2345 .flatten()
2346 .map_or_else(|| env::var_os("PATH").unwrap_or_default(), |v| v.to_owned());
2347 let new_path = env::join_paths(
2348 env::split_paths(&old_path).chain(std::iter::once(asan_runtime_path)),
2349 )
2350 .expect("Could not add ASAN runtime path to PATH");
2351 cmd.env("PATH", new_path);
2352 }
2353
2354 cmd.env_remove("CARGO");
2357
2358 cmd.env("RUSTC_BOOTSTRAP", "1");
2359 cmd.env("RUSTC_FORCE_RUSTC_VERSION", "compiletest");
2362 cmd.env("DOC_RUST_LANG_ORG_CHANNEL", builder.doc_rust_lang_org_channel());
2363 builder.add_rust_test_threads(&mut cmd);
2364
2365 if builder.config.sanitizers_enabled(target) {
2366 cmd.env("RUSTC_SANITIZER_SUPPORT", "1");
2367 }
2368
2369 if builder.config.profiler_enabled(target) {
2370 cmd.arg("--profiler-runtime");
2371 }
2372
2373 cmd.env("RUST_TEST_TMPDIR", builder.tempdir());
2374
2375 if builder.config.cmd.rustfix_coverage() {
2376 cmd.arg("--rustfix-coverage");
2377 }
2378
2379 cmd.arg("--channel").arg(&builder.config.channel);
2380
2381 if !builder.config.omit_git_hash {
2382 cmd.arg("--git-hash");
2383 }
2384
2385 let git_config = builder.config.git_config();
2386 cmd.arg("--nightly-branch").arg(git_config.nightly_branch);
2387 cmd.arg("--git-merge-commit-email").arg(git_config.git_merge_commit_email);
2388 cmd.force_coloring_in_ci();
2389
2390 #[cfg(feature = "build-metrics")]
2391 builder.metrics.begin_test_suite(
2392 build_helper::metrics::TestSuiteMetadata::Compiletest {
2393 suite: suite.into(),
2394 mode: mode.into(),
2395 compare_mode: None,
2396 target: self.target.triple.to_string(),
2397 host: self.test_compiler.host.triple.to_string(),
2398 stage: self.test_compiler.stage,
2399 },
2400 builder,
2401 );
2402
2403 let _group = builder.msg_test(
2404 format!("with compiletest suite={suite} mode={mode}"),
2405 target,
2406 test_compiler.stage,
2407 );
2408 try_run_tests(builder, &mut cmd, false);
2409
2410 if let Some(compare_mode) = compare_mode {
2411 cmd.arg("--compare-mode").arg(compare_mode);
2412
2413 #[cfg(feature = "build-metrics")]
2414 builder.metrics.begin_test_suite(
2415 build_helper::metrics::TestSuiteMetadata::Compiletest {
2416 suite: suite.into(),
2417 mode: mode.into(),
2418 compare_mode: Some(compare_mode.into()),
2419 target: self.target.triple.to_string(),
2420 host: self.test_compiler.host.triple.to_string(),
2421 stage: self.test_compiler.stage,
2422 },
2423 builder,
2424 );
2425
2426 builder.info(&format!(
2427 "Check compiletest suite={} mode={} compare_mode={} ({} -> {})",
2428 suite, mode, compare_mode, &test_compiler.host, target
2429 ));
2430 let _time = helpers::timeit(builder);
2431 try_run_tests(builder, &mut cmd, false);
2432 }
2433 }
2434
2435 fn metadata(&self) -> Option<StepMetadata> {
2436 Some(
2437 StepMetadata::test(&format!("compiletest-{}", self.suite), self.target)
2438 .stage(self.test_compiler.stage),
2439 )
2440 }
2441}
2442
2443#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2445struct BookTest {
2446 test_compiler: Compiler,
2447 path: PathBuf,
2448 name: &'static str,
2449 is_ext_doc: bool,
2450 dependencies: Vec<&'static str>,
2451}
2452
2453impl Step for BookTest {
2454 type Output = ();
2455 const IS_HOST: bool = true;
2456
2457 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2458 run.never()
2459 }
2460
2461 fn run(self, builder: &Builder<'_>) {
2462 if self.is_ext_doc {
2472 self.run_ext_doc(builder);
2473 } else {
2474 self.run_local_doc(builder);
2475 }
2476 }
2477}
2478
2479impl BookTest {
2480 fn run_ext_doc(self, builder: &Builder<'_>) {
2483 let test_compiler = self.test_compiler;
2484
2485 builder.std(test_compiler, test_compiler.host);
2486
2487 let mut rustdoc_path = builder.rustdoc_for_compiler(test_compiler);
2490 rustdoc_path.pop();
2491 let old_path = env::var_os("PATH").unwrap_or_default();
2492 let new_path = env::join_paths(iter::once(rustdoc_path).chain(env::split_paths(&old_path)))
2493 .expect("could not add rustdoc to PATH");
2494
2495 let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook);
2496 let path = builder.src.join(&self.path);
2497 rustbook_cmd.env("RUSTC_BOOTSTRAP", "1");
2499 rustbook_cmd.env("PATH", new_path).arg("test").arg(path);
2500
2501 let libs = if !self.dependencies.is_empty() {
2506 let mut lib_paths = vec![];
2507 for dep in self.dependencies {
2508 let mode = Mode::ToolRustcPrivate;
2509 let target = builder.config.host_target;
2510 let cargo = tool::prepare_tool_cargo(
2511 builder,
2512 test_compiler,
2513 mode,
2514 target,
2515 Kind::Build,
2516 dep,
2517 SourceType::Submodule,
2518 &[],
2519 );
2520
2521 let stamp = BuildStamp::new(&builder.cargo_out(test_compiler, mode, target))
2522 .with_prefix(PathBuf::from(dep).file_name().and_then(|v| v.to_str()).unwrap());
2523
2524 let output_paths = run_cargo(builder, cargo, vec![], &stamp, vec![], false, false);
2525 let directories = output_paths
2526 .into_iter()
2527 .filter_map(|p| p.parent().map(ToOwned::to_owned))
2528 .fold(HashSet::new(), |mut set, dir| {
2529 set.insert(dir);
2530 set
2531 });
2532
2533 lib_paths.extend(directories);
2534 }
2535 lib_paths
2536 } else {
2537 vec![]
2538 };
2539
2540 if !libs.is_empty() {
2541 let paths = libs
2542 .into_iter()
2543 .map(|path| path.into_os_string())
2544 .collect::<Vec<OsString>>()
2545 .join(OsStr::new(","));
2546 rustbook_cmd.args([OsString::from("--library-path"), paths]);
2547 }
2548
2549 builder.add_rust_test_threads(&mut rustbook_cmd);
2550 let _guard = builder.msg_test(
2551 format_args!("mdbook {}", self.path.display()),
2552 test_compiler.host,
2553 test_compiler.stage,
2554 );
2555 let _time = helpers::timeit(builder);
2556 let toolstate = if rustbook_cmd.delay_failure().run(builder) {
2557 ToolState::TestPass
2558 } else {
2559 ToolState::TestFail
2560 };
2561 builder.save_toolstate(self.name, toolstate);
2562 }
2563
2564 fn run_local_doc(self, builder: &Builder<'_>) {
2566 let test_compiler = self.test_compiler;
2567 let host = self.test_compiler.host;
2568
2569 builder.std(test_compiler, host);
2570
2571 let _guard = builder.msg_test(
2572 format!("book {}", self.name),
2573 test_compiler.host,
2574 test_compiler.stage,
2575 );
2576
2577 let mut stack = vec![builder.src.join(self.path)];
2580 let _time = helpers::timeit(builder);
2581 let mut files = Vec::new();
2582 while let Some(p) = stack.pop() {
2583 if p.is_dir() {
2584 stack.extend(t!(p.read_dir()).map(|p| t!(p).path()));
2585 continue;
2586 }
2587
2588 if p.extension().and_then(|s| s.to_str()) != Some("md") {
2589 continue;
2590 }
2591
2592 files.push(p);
2593 }
2594
2595 files.sort();
2596
2597 for file in files {
2598 markdown_test(builder, test_compiler, &file);
2599 }
2600 }
2601}
2602
2603macro_rules! test_book {
2604 ($(
2605 $name:ident, $path:expr, $book_name:expr,
2606 default=$default:expr
2607 $(,submodules = $submodules:expr)?
2608 $(,dependencies=$dependencies:expr)?
2609 ;
2610 )+) => {
2611 $(
2612 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
2613 pub struct $name {
2614 test_compiler: Compiler,
2615 }
2616
2617 impl Step for $name {
2618 type Output = ();
2619 const IS_HOST: bool = true;
2620
2621 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2622 run.path($path)
2623 }
2624
2625 fn is_default_step(_builder: &Builder<'_>) -> bool {
2626 const { $default }
2627 }
2628
2629 fn make_run(run: RunConfig<'_>) {
2630 run.builder.ensure($name {
2631 test_compiler: run.builder.compiler(run.builder.top_stage, run.target),
2632 });
2633 }
2634
2635 fn run(self, builder: &Builder<'_>) {
2636 $(
2637 for submodule in $submodules {
2638 builder.require_submodule(submodule, None);
2639 }
2640 )*
2641
2642 let dependencies = vec![];
2643 $(
2644 let mut dependencies = dependencies;
2645 for dep in $dependencies {
2646 dependencies.push(dep);
2647 }
2648 )?
2649
2650 builder.ensure(BookTest {
2651 test_compiler: self.test_compiler,
2652 path: PathBuf::from($path),
2653 name: $book_name,
2654 is_ext_doc: !$default,
2655 dependencies,
2656 });
2657 }
2658 }
2659 )+
2660 }
2661}
2662
2663test_book!(
2664 Nomicon, "src/doc/nomicon", "nomicon", default=false, submodules=["src/doc/nomicon"];
2665 Reference, "src/doc/reference", "reference", default=false, submodules=["src/doc/reference"];
2666 RustdocBook, "src/doc/rustdoc", "rustdoc", default=true;
2667 RustcBook, "src/doc/rustc", "rustc", default=true;
2668 RustByExample, "src/doc/rust-by-example", "rust-by-example", default=false, submodules=["src/doc/rust-by-example"];
2669 EmbeddedBook, "src/doc/embedded-book", "embedded-book", default=false, submodules=["src/doc/embedded-book"];
2670 TheBook, "src/doc/book", "book", default=false, submodules=["src/doc/book"], dependencies=["src/doc/book/packages/trpl"];
2671 UnstableBook, "src/doc/unstable-book", "unstable-book", default=true;
2672 EditionGuide, "src/doc/edition-guide", "edition-guide", default=false, submodules=["src/doc/edition-guide"];
2673);
2674
2675#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2676pub struct ErrorIndex {
2677 compilers: RustcPrivateCompilers,
2678}
2679
2680impl Step for ErrorIndex {
2681 type Output = ();
2682 const IS_HOST: bool = true;
2683
2684 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2685 run.path("src/tools/error_index_generator").alias("error-index")
2688 }
2689
2690 fn is_default_step(_builder: &Builder<'_>) -> bool {
2691 true
2692 }
2693
2694 fn make_run(run: RunConfig<'_>) {
2695 let compilers = RustcPrivateCompilers::new(
2699 run.builder,
2700 run.builder.top_stage,
2701 run.builder.config.host_target,
2702 );
2703 run.builder.ensure(ErrorIndex { compilers });
2704 }
2705
2706 fn run(self, builder: &Builder<'_>) {
2713 let target_compiler = self.compilers.target_compiler();
2715
2716 let dir = testdir(builder, target_compiler.host);
2717 t!(fs::create_dir_all(&dir));
2718 let output = dir.join("error-index.md");
2719
2720 let mut tool = tool::ErrorIndex::command(builder, self.compilers);
2721 tool.arg("markdown").arg(&output);
2722
2723 let guard = builder.msg_test("error-index", target_compiler.host, target_compiler.stage);
2724 let _time = helpers::timeit(builder);
2725 tool.run_capture(builder);
2726 drop(guard);
2727 builder.std(target_compiler, target_compiler.host);
2730 markdown_test(builder, target_compiler, &output);
2731 }
2732}
2733
2734fn markdown_test(builder: &Builder<'_>, compiler: Compiler, markdown: &Path) -> bool {
2735 if let Ok(contents) = fs::read_to_string(markdown)
2736 && !contents.contains("```")
2737 {
2738 return true;
2739 }
2740
2741 builder.do_if_verbose(|| println!("doc tests for: {}", markdown.display()));
2742 let mut cmd = builder.rustdoc_cmd(compiler);
2743 builder.add_rust_test_threads(&mut cmd);
2744 cmd.arg("-Z");
2746 cmd.arg("unstable-options");
2747 cmd.arg("--test");
2748 cmd.arg(markdown);
2749 cmd.env("RUSTC_BOOTSTRAP", "1");
2750
2751 let test_args = builder.config.test_args().join(" ");
2752 cmd.arg("--test-args").arg(test_args);
2753
2754 cmd = cmd.delay_failure();
2755 if !builder.config.verbose_tests {
2756 cmd.run_capture(builder).is_success()
2757 } else {
2758 cmd.run(builder)
2759 }
2760}
2761
2762#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2767pub struct CrateLibrustc {
2768 build_compiler: Compiler,
2770 target: TargetSelection,
2771 crates: Vec<String>,
2772}
2773
2774impl Step for CrateLibrustc {
2775 type Output = ();
2776 const IS_HOST: bool = true;
2777
2778 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2779 run.crate_or_deps("rustc-main").path("compiler")
2780 }
2781
2782 fn is_default_step(_builder: &Builder<'_>) -> bool {
2783 true
2784 }
2785
2786 fn make_run(run: RunConfig<'_>) {
2787 let builder = run.builder;
2788 let host = run.build_triple();
2789 let build_compiler = builder.compiler(builder.top_stage - 1, host);
2790 let crates = run.make_run_crates(Alias::Compiler);
2791
2792 builder.ensure(CrateLibrustc { build_compiler, target: run.target, crates });
2793 }
2794
2795 fn run(self, builder: &Builder<'_>) {
2796 builder.std(self.build_compiler, self.target);
2797
2798 builder.ensure(Crate {
2800 build_compiler: self.build_compiler,
2801 target: self.target,
2802 mode: Mode::Rustc,
2803 crates: self.crates,
2804 });
2805 }
2806
2807 fn metadata(&self) -> Option<StepMetadata> {
2808 Some(StepMetadata::test("CrateLibrustc", self.target).built_by(self.build_compiler))
2809 }
2810}
2811
2812fn run_cargo_test<'a>(
2816 cargo: builder::Cargo,
2817 libtest_args: &[&str],
2818 crates: &[String],
2819 description: impl Into<Option<&'a str>>,
2820 target: TargetSelection,
2821 builder: &Builder<'_>,
2822) -> bool {
2823 let compiler = cargo.compiler();
2824 let mut cargo = prepare_cargo_test(cargo, libtest_args, crates, target, builder);
2825 let _time = helpers::timeit(builder);
2826 let _group =
2827 description.into().and_then(|what| builder.msg_test(what, target, compiler.stage + 1));
2828
2829 #[cfg(feature = "build-metrics")]
2830 builder.metrics.begin_test_suite(
2831 build_helper::metrics::TestSuiteMetadata::CargoPackage {
2832 crates: crates.iter().map(|c| c.to_string()).collect(),
2833 target: target.triple.to_string(),
2834 host: compiler.host.triple.to_string(),
2835 stage: compiler.stage,
2836 },
2837 builder,
2838 );
2839 add_flags_and_try_run_tests(builder, &mut cargo)
2840}
2841
2842fn prepare_cargo_test(
2844 cargo: builder::Cargo,
2845 libtest_args: &[&str],
2846 crates: &[String],
2847 target: TargetSelection,
2848 builder: &Builder<'_>,
2849) -> BootstrapCommand {
2850 let compiler = cargo.compiler();
2851 let mut cargo: BootstrapCommand = cargo.into();
2852
2853 if builder.config.cmd.bless() && !cargo.get_envs().any(|v| v.0 == "RUSTC_BLESS") {
2857 cargo.env("RUSTC_BLESS", "Gesundheit");
2858 }
2859
2860 if builder.kind == Kind::Test && !builder.fail_fast {
2864 cargo.arg("--no-fail-fast");
2865 }
2866
2867 if builder.config.json_output {
2868 cargo.arg("--message-format=json");
2869 }
2870
2871 match builder.doc_tests {
2872 DocTests::Only => {
2873 cargo.arg("--doc");
2874 }
2875 DocTests::No => {
2876 cargo.args(["--bins", "--examples", "--tests", "--benches"]);
2877 }
2878 DocTests::Yes => {}
2879 }
2880
2881 for krate in crates {
2882 cargo.arg("-p").arg(krate);
2883 }
2884
2885 cargo.arg("--").args(builder.config.test_args()).args(libtest_args);
2886 if !builder.config.verbose_tests {
2887 cargo.arg("--quiet");
2888 }
2889
2890 if builder.kind != Kind::Miri {
2899 let mut dylib_paths = builder.rustc_lib_paths(compiler);
2900 dylib_paths.push(builder.sysroot_target_libdir(compiler, target));
2901 helpers::add_dylib_path(dylib_paths, &mut cargo);
2902 }
2903
2904 if builder.remote_tested(target) {
2905 cargo.env(
2906 format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)),
2907 format!("{} run 0", builder.tool_exe(Tool::RemoteTestClient).display()),
2908 );
2909 } else if let Some(tool) = builder.runner(target) {
2910 cargo.env(format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)), tool);
2911 }
2912
2913 cargo
2914}
2915
2916#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2924pub struct Crate {
2925 build_compiler: Compiler,
2927 target: TargetSelection,
2928 mode: Mode,
2929 crates: Vec<String>,
2930}
2931
2932impl Step for Crate {
2933 type Output = ();
2934
2935 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2936 run.crate_or_deps("sysroot").crate_or_deps("coretests").crate_or_deps("alloctests")
2937 }
2938
2939 fn is_default_step(_builder: &Builder<'_>) -> bool {
2940 true
2941 }
2942
2943 fn make_run(run: RunConfig<'_>) {
2944 let builder = run.builder;
2945 let host = run.build_triple();
2946 let build_compiler = builder.compiler(builder.top_stage, host);
2947 let crates = run
2948 .paths
2949 .iter()
2950 .map(|p| builder.crate_paths[&p.assert_single_path().path].clone())
2951 .collect();
2952
2953 builder.ensure(Crate { build_compiler, target: run.target, mode: Mode::Std, crates });
2954 }
2955
2956 fn run(self, builder: &Builder<'_>) {
2965 let build_compiler = self.build_compiler;
2966 let target = self.target;
2967 let mode = self.mode;
2968
2969 builder.ensure(Std::new(build_compiler, build_compiler.host).force_recompile(true));
2972
2973 let mut cargo = if builder.kind == Kind::Miri {
2974 if builder.top_stage == 0 {
2975 eprintln!("ERROR: `x.py miri` requires stage 1 or higher");
2976 std::process::exit(1);
2977 }
2978
2979 let mut cargo = builder::Cargo::new(
2982 builder,
2983 build_compiler,
2984 mode,
2985 SourceType::InTree,
2986 target,
2987 Kind::MiriTest,
2988 );
2989 cargo.env("MIRI_REPLACE_LIBRS_IF_NOT_TEST", "1");
3001 cargo.rustflag("-Zforce-unstable-if-unmarked");
3005 cargo
3006 } else {
3007 if !builder.config.is_host_target(target) {
3009 builder.ensure(compile::Std::new(build_compiler, target).force_recompile(true));
3010 builder.ensure(RemoteCopyLibs { build_compiler, target });
3011 }
3012
3013 builder::Cargo::new(
3015 builder,
3016 build_compiler,
3017 mode,
3018 SourceType::InTree,
3019 target,
3020 builder.kind,
3021 )
3022 };
3023
3024 match mode {
3025 Mode::Std => {
3026 if builder.kind == Kind::Miri {
3027 cargo
3033 .arg("--manifest-path")
3034 .arg(builder.src.join("library/sysroot/Cargo.toml"));
3035 } else {
3036 compile::std_cargo(builder, target, &mut cargo, &[]);
3037 }
3038 }
3039 Mode::Rustc => {
3040 compile::rustc_cargo(builder, &mut cargo, target, &build_compiler, &self.crates);
3041 }
3042 _ => panic!("can only test libraries"),
3043 };
3044
3045 let mut crates = self.crates.clone();
3046 if crates.iter().any(|crate_| crate_ == "core") {
3051 crates.push("coretests".to_owned());
3052 }
3053 if crates.iter().any(|crate_| crate_ == "alloc") {
3054 crates.push("alloctests".to_owned());
3055 }
3056
3057 run_cargo_test(cargo, &[], &crates, &*crate_description(&self.crates), target, builder);
3058 }
3059}
3060
3061#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3064pub struct CrateRustdoc {
3065 host: TargetSelection,
3066}
3067
3068impl Step for CrateRustdoc {
3069 type Output = ();
3070 const IS_HOST: bool = true;
3071
3072 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3073 run.paths(&["src/librustdoc", "src/tools/rustdoc"])
3074 }
3075
3076 fn is_default_step(_builder: &Builder<'_>) -> bool {
3077 true
3078 }
3079
3080 fn make_run(run: RunConfig<'_>) {
3081 let builder = run.builder;
3082
3083 builder.ensure(CrateRustdoc { host: run.target });
3084 }
3085
3086 fn run(self, builder: &Builder<'_>) {
3087 let target = self.host;
3088
3089 let compiler = if builder.download_rustc() {
3090 builder.compiler(builder.top_stage, target)
3091 } else {
3092 builder.compiler_for(builder.top_stage, target, target)
3097 };
3098 builder.std(compiler, target);
3103 builder.ensure(compile::Rustc::new(compiler, target));
3104
3105 let mut cargo = tool::prepare_tool_cargo(
3106 builder,
3107 compiler,
3108 Mode::ToolRustcPrivate,
3109 target,
3110 builder.kind,
3111 "src/tools/rustdoc",
3112 SourceType::InTree,
3113 &[],
3114 );
3115 if self.host.contains("musl") {
3116 cargo.arg("'-Ctarget-feature=-crt-static'");
3117 }
3118
3119 let libdir = if builder.download_rustc() {
3146 builder.rustc_libdir(compiler)
3147 } else {
3148 builder.sysroot_target_libdir(compiler, target).to_path_buf()
3149 };
3150 let mut dylib_path = dylib_path();
3151 dylib_path.insert(0, PathBuf::from(&*libdir));
3152 cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());
3153
3154 run_cargo_test(cargo, &[], &["rustdoc:0.0.0".to_string()], "rustdoc", target, builder);
3155 }
3156}
3157
3158#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3159pub struct CrateRustdocJsonTypes {
3160 build_compiler: Compiler,
3161 target: TargetSelection,
3162}
3163
3164impl Step for CrateRustdocJsonTypes {
3165 type Output = ();
3166 const IS_HOST: bool = true;
3167
3168 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3169 run.path("src/rustdoc-json-types")
3170 }
3171
3172 fn is_default_step(_builder: &Builder<'_>) -> bool {
3173 true
3174 }
3175
3176 fn make_run(run: RunConfig<'_>) {
3177 let builder = run.builder;
3178
3179 builder.ensure(CrateRustdocJsonTypes {
3180 build_compiler: get_tool_target_compiler(
3181 builder,
3182 ToolTargetBuildMode::Build(run.target),
3183 ),
3184 target: run.target,
3185 });
3186 }
3187
3188 fn run(self, builder: &Builder<'_>) {
3189 let target = self.target;
3190
3191 let cargo = tool::prepare_tool_cargo(
3192 builder,
3193 self.build_compiler,
3194 Mode::ToolTarget,
3195 target,
3196 builder.kind,
3197 "src/rustdoc-json-types",
3198 SourceType::InTree,
3199 &[],
3200 );
3201
3202 let libtest_args = if target.contains("musl") {
3204 ["'-Ctarget-feature=-crt-static'"].as_slice()
3205 } else {
3206 &[]
3207 };
3208
3209 run_cargo_test(
3210 cargo,
3211 libtest_args,
3212 &["rustdoc-json-types".to_string()],
3213 "rustdoc-json-types",
3214 target,
3215 builder,
3216 );
3217 }
3218}
3219
3220#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3230pub struct RemoteCopyLibs {
3231 build_compiler: Compiler,
3232 target: TargetSelection,
3233}
3234
3235impl Step for RemoteCopyLibs {
3236 type Output = ();
3237
3238 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3239 run.never()
3240 }
3241
3242 fn run(self, builder: &Builder<'_>) {
3243 let build_compiler = self.build_compiler;
3244 let target = self.target;
3245 if !builder.remote_tested(target) {
3246 return;
3247 }
3248
3249 builder.std(build_compiler, target);
3250
3251 builder.info(&format!("REMOTE copy libs to emulator ({target})"));
3252
3253 let remote_test_server = builder.ensure(tool::RemoteTestServer { build_compiler, target });
3254
3255 let tool = builder.tool_exe(Tool::RemoteTestClient);
3257 let mut cmd = command(&tool);
3258 cmd.arg("spawn-emulator")
3259 .arg(target.triple)
3260 .arg(&remote_test_server.tool_path)
3261 .arg(builder.tempdir());
3262 if let Some(rootfs) = builder.qemu_rootfs(target) {
3263 cmd.arg(rootfs);
3264 }
3265 cmd.run(builder);
3266
3267 for f in t!(builder.sysroot_target_libdir(build_compiler, target).read_dir()) {
3269 let f = t!(f);
3270 if helpers::is_dylib(&f.path()) {
3271 command(&tool).arg("push").arg(f.path()).run(builder);
3272 }
3273 }
3274 }
3275}
3276
3277#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3278pub struct Distcheck;
3279
3280impl Step for Distcheck {
3281 type Output = ();
3282
3283 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3284 run.alias("distcheck")
3285 }
3286
3287 fn make_run(run: RunConfig<'_>) {
3288 run.builder.ensure(Distcheck);
3289 }
3290
3291 fn run(self, builder: &Builder<'_>) {
3301 let root_dir = std::env::temp_dir().join("distcheck");
3304
3305 distcheck_plain_source_tarball(builder, &root_dir.join("distcheck-rustc-src"));
3306 distcheck_rust_src(builder, &root_dir.join("distcheck-rust-src"));
3307 distcheck_rustc_dev(builder, &root_dir.join("distcheck-rustc-dev"));
3308 }
3309}
3310
3311fn distcheck_plain_source_tarball(builder: &Builder<'_>, plain_src_dir: &Path) {
3313 builder.info("Distcheck plain source tarball");
3314 let plain_src_tarball = builder.ensure(dist::PlainSourceTarball);
3315 builder.clear_dir(plain_src_dir);
3316
3317 let configure_args: Vec<String> = std::env::var("DISTCHECK_CONFIGURE_ARGS")
3318 .map(|args| args.split(" ").map(|s| s.to_string()).collect::<Vec<String>>())
3319 .unwrap_or_default();
3320
3321 command("tar")
3322 .arg("-xf")
3323 .arg(plain_src_tarball.tarball())
3324 .arg("--strip-components=1")
3325 .current_dir(plain_src_dir)
3326 .run(builder);
3327 command("./configure")
3328 .arg("--set")
3329 .arg("rust.omit-git-hash=false")
3330 .args(&configure_args)
3331 .arg("--enable-vendor")
3332 .current_dir(plain_src_dir)
3333 .run(builder);
3334 command(helpers::make(&builder.config.host_target.triple))
3335 .arg("check")
3336 .env("GITHUB_ACTIONS", "0")
3339 .current_dir(plain_src_dir)
3340 .run(builder);
3341 builder.remove_dir(plain_src_dir);
3343}
3344
3345fn distcheck_rust_src(builder: &Builder<'_>, src_dir: &Path) {
3347 builder.info("Distcheck rust-src");
3348 let src_tarball = builder.ensure(dist::Src);
3349 builder.clear_dir(src_dir);
3350
3351 command("tar")
3352 .arg("-xf")
3353 .arg(src_tarball.tarball())
3354 .arg("--strip-components=1")
3355 .current_dir(src_dir)
3356 .run(builder);
3357
3358 let toml = src_dir.join("rust-src/lib/rustlib/src/rust/library/std/Cargo.toml");
3359 command(&builder.initial_cargo)
3360 .env("RUSTC_BOOTSTRAP", "1")
3363 .arg("generate-lockfile")
3364 .arg("--manifest-path")
3365 .arg(&toml)
3366 .current_dir(src_dir)
3367 .run(builder);
3368 builder.remove_dir(src_dir);
3370}
3371
3372fn distcheck_rustc_dev(builder: &Builder<'_>, dir: &Path) {
3374 builder.info("Distcheck rustc-dev");
3375 let tarball = builder.ensure(dist::RustcDev::new(builder, builder.host_target)).unwrap();
3376 builder.clear_dir(dir);
3377
3378 command("tar")
3379 .arg("-xf")
3380 .arg(tarball.tarball())
3381 .arg("--strip-components=1")
3382 .current_dir(dir)
3383 .run(builder);
3384
3385 command(&builder.initial_cargo)
3386 .arg("metadata")
3387 .arg("--manifest-path")
3388 .arg("rustc-dev/lib/rustlib/rustc-src/rust/compiler/rustc/Cargo.toml")
3389 .env("RUSTC_BOOTSTRAP", "1")
3390 .env("RUSTC", &builder.initial_rustc)
3392 .current_dir(dir)
3393 .run(builder);
3394 builder.remove_dir(dir);
3396}
3397
3398#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3400pub(crate) struct BootstrapPy;
3401
3402impl Step for BootstrapPy {
3403 type Output = ();
3404 const IS_HOST: bool = true;
3405
3406 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3407 run.alias("bootstrap-py")
3408 }
3409
3410 fn is_default_step(builder: &Builder<'_>) -> bool {
3411 builder.config.is_running_on_ci
3415 }
3416
3417 fn make_run(run: RunConfig<'_>) {
3418 run.builder.ensure(BootstrapPy)
3419 }
3420
3421 fn run(self, builder: &Builder<'_>) -> Self::Output {
3422 let mut check_bootstrap = command(
3423 builder.config.python.as_ref().expect("python is required for running bootstrap tests"),
3424 );
3425 check_bootstrap
3426 .args(["-m", "unittest", "bootstrap_test.py"])
3427 .args(builder.config.test_args())
3429 .env("BUILD_DIR", &builder.out)
3430 .env("BUILD_PLATFORM", builder.build.host_target.triple)
3431 .env("BOOTSTRAP_TEST_RUSTC_BIN", &builder.initial_rustc)
3432 .env("BOOTSTRAP_TEST_CARGO_BIN", &builder.initial_cargo)
3433 .current_dir(builder.src.join("src/bootstrap/"));
3434 check_bootstrap.delay_failure().run(builder);
3435 }
3436}
3437
3438#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3439pub struct Bootstrap;
3440
3441impl Step for Bootstrap {
3442 type Output = ();
3443 const IS_HOST: bool = true;
3444
3445 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3446 run.path("src/bootstrap")
3447 }
3448
3449 fn is_default_step(builder: &Builder<'_>) -> bool {
3450 builder.config.is_running_on_ci
3454 }
3455
3456 fn run(self, builder: &Builder<'_>) {
3458 let host = builder.config.host_target;
3459 let build_compiler = builder.compiler(0, host);
3460
3461 builder.build.require_submodule("src/tools/cargo", None);
3463
3464 let mut cargo = tool::prepare_tool_cargo(
3465 builder,
3466 build_compiler,
3467 Mode::ToolBootstrap,
3468 host,
3469 Kind::Test,
3470 "src/bootstrap",
3471 SourceType::InTree,
3472 &[],
3473 );
3474
3475 cargo.release_build(false);
3476
3477 cargo
3478 .rustflag("-Cdebuginfo=2")
3479 .env("CARGO_TARGET_DIR", builder.out.join("bootstrap"))
3480 .env("INSTA_WORKSPACE_ROOT", &builder.src)
3482 .env("RUSTC_BOOTSTRAP", "1");
3483
3484 if builder.config.cmd.bless() {
3485 cargo.env("INSTA_UPDATE", "always");
3489 }
3490
3491 run_cargo_test(cargo, &[], &[], None, host, builder);
3492 }
3493
3494 fn make_run(run: RunConfig<'_>) {
3495 run.builder.ensure(Bootstrap);
3496 }
3497}
3498
3499fn get_compiler_to_test(builder: &Builder<'_>, target: TargetSelection) -> Compiler {
3500 builder.compiler(builder.top_stage, target)
3501}
3502
3503#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3506pub struct TierCheck {
3507 test_compiler: Compiler,
3508}
3509
3510impl Step for TierCheck {
3511 type Output = ();
3512 const IS_HOST: bool = true;
3513
3514 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3515 run.path("src/tools/tier-check")
3516 }
3517
3518 fn is_default_step(_builder: &Builder<'_>) -> bool {
3519 true
3520 }
3521
3522 fn make_run(run: RunConfig<'_>) {
3523 run.builder
3524 .ensure(TierCheck { test_compiler: get_compiler_to_test(run.builder, run.target) });
3525 }
3526
3527 fn run(self, builder: &Builder<'_>) {
3528 let tool_build_compiler = builder.compiler(0, builder.host_target);
3529
3530 let mut cargo = tool::prepare_tool_cargo(
3531 builder,
3532 tool_build_compiler,
3533 Mode::ToolBootstrap,
3534 tool_build_compiler.host,
3535 Kind::Run,
3536 "src/tools/tier-check",
3537 SourceType::InTree,
3538 &[],
3539 );
3540 cargo.arg(builder.src.join("src/doc/rustc/src/platform-support.md"));
3541 cargo.arg(builder.rustc(self.test_compiler));
3542
3543 let _guard = builder.msg_test(
3544 "platform support check",
3545 self.test_compiler.host,
3546 self.test_compiler.stage,
3547 );
3548 BootstrapCommand::from(cargo).delay_failure().run(builder);
3549 }
3550
3551 fn metadata(&self) -> Option<StepMetadata> {
3552 Some(StepMetadata::test("tier-check", self.test_compiler.host))
3553 }
3554}
3555
3556#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3557pub struct LintDocs {
3558 build_compiler: Compiler,
3559 target: TargetSelection,
3560}
3561
3562impl Step for LintDocs {
3563 type Output = ();
3564 const IS_HOST: bool = true;
3565
3566 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3567 run.path("src/tools/lint-docs")
3568 }
3569
3570 fn is_default_step(builder: &Builder<'_>) -> bool {
3571 builder.top_stage >= 2
3574 }
3575
3576 fn make_run(run: RunConfig<'_>) {
3577 if run.builder.top_stage < 2 {
3578 eprintln!("WARNING: lint-docs tests might not work below stage 2");
3579 }
3580
3581 run.builder.ensure(LintDocs {
3582 build_compiler: prepare_doc_compiler(
3583 run.builder,
3584 run.builder.config.host_target,
3585 run.builder.top_stage,
3586 ),
3587 target: run.target,
3588 });
3589 }
3590
3591 fn run(self, builder: &Builder<'_>) {
3594 builder.ensure(crate::core::build_steps::doc::RustcBook::validate(
3595 self.build_compiler,
3596 self.target,
3597 ));
3598 }
3599
3600 fn metadata(&self) -> Option<StepMetadata> {
3601 Some(StepMetadata::test("lint-docs", self.target).built_by(self.build_compiler))
3602 }
3603}
3604
3605#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3606pub struct RustInstaller;
3607
3608impl Step for RustInstaller {
3609 type Output = ();
3610 const IS_HOST: bool = true;
3611
3612 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3613 run.path("src/tools/rust-installer")
3614 }
3615
3616 fn is_default_step(_builder: &Builder<'_>) -> bool {
3617 true
3618 }
3619
3620 fn make_run(run: RunConfig<'_>) {
3621 run.builder.ensure(Self);
3622 }
3623
3624 fn run(self, builder: &Builder<'_>) {
3626 let bootstrap_host = builder.config.host_target;
3627 let build_compiler = builder.compiler(0, bootstrap_host);
3628 let cargo = tool::prepare_tool_cargo(
3629 builder,
3630 build_compiler,
3631 Mode::ToolBootstrap,
3632 bootstrap_host,
3633 Kind::Test,
3634 "src/tools/rust-installer",
3635 SourceType::InTree,
3636 &[],
3637 );
3638
3639 let _guard = builder.msg_test("rust-installer", bootstrap_host, 1);
3640 run_cargo_test(cargo, &[], &[], None, bootstrap_host, builder);
3641
3642 if bootstrap_host != "x86_64-unknown-linux-gnu" {
3646 return;
3647 }
3648
3649 let mut cmd = command(builder.src.join("src/tools/rust-installer/test.sh"));
3650 let tmpdir = testdir(builder, build_compiler.host).join("rust-installer");
3651 let _ = std::fs::remove_dir_all(&tmpdir);
3652 let _ = std::fs::create_dir_all(&tmpdir);
3653 cmd.current_dir(&tmpdir);
3654 cmd.env("CARGO_TARGET_DIR", tmpdir.join("cargo-target"));
3655 cmd.env("CARGO", &builder.initial_cargo);
3656 cmd.env("RUSTC", &builder.initial_rustc);
3657 cmd.env("TMP_DIR", &tmpdir);
3658 cmd.delay_failure().run(builder);
3659 }
3660}
3661
3662#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3663pub struct TestHelpers {
3664 pub target: TargetSelection,
3665}
3666
3667impl Step for TestHelpers {
3668 type Output = ();
3669
3670 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3671 run.path("tests/auxiliary/rust_test_helpers.c")
3672 }
3673
3674 fn make_run(run: RunConfig<'_>) {
3675 run.builder.ensure(TestHelpers { target: run.target })
3676 }
3677
3678 fn run(self, builder: &Builder<'_>) {
3681 if builder.config.dry_run() {
3682 return;
3683 }
3684 let target = if self.target == "x86_64-fortanix-unknown-sgx" {
3688 TargetSelection::from_user("x86_64-unknown-linux-gnu")
3689 } else {
3690 self.target
3691 };
3692 let dst = builder.test_helpers_out(target);
3693 let src = builder.src.join("tests/auxiliary/rust_test_helpers.c");
3694 if up_to_date(&src, &dst.join("librust_test_helpers.a")) {
3695 return;
3696 }
3697
3698 let _guard = builder.msg_unstaged(Kind::Build, "test helpers", target);
3699 t!(fs::create_dir_all(&dst));
3700 let mut cfg = cc::Build::new();
3701
3702 if !target.is_msvc() {
3706 if let Some(ar) = builder.ar(target) {
3707 cfg.archiver(ar);
3708 }
3709 cfg.compiler(builder.cc(target));
3710 }
3711 cfg.cargo_metadata(false)
3712 .out_dir(&dst)
3713 .target(&target.triple)
3714 .host(&builder.config.host_target.triple)
3715 .opt_level(0)
3716 .warnings(false)
3717 .debug(false)
3718 .file(builder.src.join("tests/auxiliary/rust_test_helpers.c"))
3719 .compile("rust_test_helpers");
3720 }
3721}
3722
3723#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3724pub struct CodegenCranelift {
3725 compilers: RustcPrivateCompilers,
3726 target: TargetSelection,
3727}
3728
3729impl Step for CodegenCranelift {
3730 type Output = ();
3731 const IS_HOST: bool = true;
3732
3733 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3734 run.paths(&["compiler/rustc_codegen_cranelift"])
3735 }
3736
3737 fn is_default_step(_builder: &Builder<'_>) -> bool {
3738 true
3739 }
3740
3741 fn make_run(run: RunConfig<'_>) {
3742 let builder = run.builder;
3743 let host = run.build_triple();
3744 let compilers = RustcPrivateCompilers::new(run.builder, run.builder.top_stage, host);
3745
3746 if builder.doc_tests == DocTests::Only {
3747 return;
3748 }
3749
3750 if builder.download_rustc() {
3751 builder.info("CI rustc uses the default codegen backend. skipping");
3752 return;
3753 }
3754
3755 if !target_supports_cranelift_backend(run.target) {
3756 builder.info("target not supported by rustc_codegen_cranelift. skipping");
3757 return;
3758 }
3759
3760 if builder.remote_tested(run.target) {
3761 builder.info("remote testing is not supported by rustc_codegen_cranelift. skipping");
3762 return;
3763 }
3764
3765 if !builder
3766 .config
3767 .enabled_codegen_backends(run.target)
3768 .contains(&CodegenBackendKind::Cranelift)
3769 {
3770 builder.info("cranelift not in rust.codegen-backends. skipping");
3771 return;
3772 }
3773
3774 builder.ensure(CodegenCranelift { compilers, target: run.target });
3775 }
3776
3777 fn run(self, builder: &Builder<'_>) {
3778 let compilers = self.compilers;
3779 let build_compiler = compilers.build_compiler();
3780
3781 let target_compiler = compilers.target_compiler();
3784 let target = self.target;
3785
3786 builder.std(target_compiler, target);
3787
3788 let mut cargo = builder::Cargo::new(
3789 builder,
3790 target_compiler,
3791 Mode::Codegen, SourceType::InTree,
3793 target,
3794 Kind::Run,
3795 );
3796
3797 cargo.current_dir(&builder.src.join("compiler/rustc_codegen_cranelift"));
3798 cargo
3799 .arg("--manifest-path")
3800 .arg(builder.src.join("compiler/rustc_codegen_cranelift/build_system/Cargo.toml"));
3801 compile::rustc_cargo_env(builder, &mut cargo, target);
3802
3803 cargo.env("CARGO_BUILD_INCREMENTAL", "false");
3805
3806 let _guard = builder.msg_test(
3807 "rustc_codegen_cranelift",
3808 target_compiler.host,
3809 target_compiler.stage,
3810 );
3811
3812 let download_dir = builder.out.join("cg_clif_download");
3814
3815 cargo
3816 .arg("--")
3817 .arg("test")
3818 .arg("--download-dir")
3819 .arg(&download_dir)
3820 .arg("--out-dir")
3821 .arg(builder.stage_out(build_compiler, Mode::Codegen).join("cg_clif"))
3822 .arg("--no-unstable-features")
3823 .arg("--use-backend")
3824 .arg("cranelift")
3825 .arg("--sysroot")
3827 .arg("llvm")
3828 .arg("--skip-test")
3831 .arg("testsuite.extended_sysroot");
3832
3833 cargo.into_cmd().run(builder);
3834 }
3835
3836 fn metadata(&self) -> Option<StepMetadata> {
3837 Some(
3838 StepMetadata::test("rustc_codegen_cranelift", self.target)
3839 .built_by(self.compilers.build_compiler()),
3840 )
3841 }
3842}
3843
3844#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3845pub struct CodegenGCC {
3846 compilers: RustcPrivateCompilers,
3847 target: TargetSelection,
3848}
3849
3850impl Step for CodegenGCC {
3851 type Output = ();
3852 const IS_HOST: bool = true;
3853
3854 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3855 run.paths(&["compiler/rustc_codegen_gcc"])
3856 }
3857
3858 fn is_default_step(_builder: &Builder<'_>) -> bool {
3859 true
3860 }
3861
3862 fn make_run(run: RunConfig<'_>) {
3863 let builder = run.builder;
3864 let host = run.build_triple();
3865 let compilers = RustcPrivateCompilers::new(run.builder, run.builder.top_stage, host);
3866
3867 if builder.doc_tests == DocTests::Only {
3868 return;
3869 }
3870
3871 if builder.download_rustc() {
3872 builder.info("CI rustc uses the default codegen backend. skipping");
3873 return;
3874 }
3875
3876 let triple = run.target.triple;
3877 let target_supported =
3878 if triple.contains("linux") { triple.contains("x86_64") } else { false };
3879 if !target_supported {
3880 builder.info("target not supported by rustc_codegen_gcc. skipping");
3881 return;
3882 }
3883
3884 if builder.remote_tested(run.target) {
3885 builder.info("remote testing is not supported by rustc_codegen_gcc. skipping");
3886 return;
3887 }
3888
3889 if !builder.config.enabled_codegen_backends(run.target).contains(&CodegenBackendKind::Gcc) {
3890 builder.info("gcc not in rust.codegen-backends. skipping");
3891 return;
3892 }
3893
3894 builder.ensure(CodegenGCC { compilers, target: run.target });
3895 }
3896
3897 fn run(self, builder: &Builder<'_>) {
3898 let compilers = self.compilers;
3899 let target = self.target;
3900
3901 let gcc = builder.ensure(Gcc { target });
3902
3903 builder.ensure(
3904 compile::Std::new(compilers.build_compiler(), target)
3905 .extra_rust_args(&["-Csymbol-mangling-version=v0", "-Cpanic=abort"]),
3906 );
3907
3908 let _guard = builder.msg_test(
3909 "rustc_codegen_gcc",
3910 compilers.target(),
3911 compilers.target_compiler().stage,
3912 );
3913
3914 let mut cargo = builder::Cargo::new(
3915 builder,
3916 compilers.build_compiler(),
3917 Mode::Codegen, SourceType::InTree,
3919 target,
3920 Kind::Run,
3921 );
3922
3923 cargo.current_dir(&builder.src.join("compiler/rustc_codegen_gcc"));
3924 cargo
3925 .arg("--manifest-path")
3926 .arg(builder.src.join("compiler/rustc_codegen_gcc/build_system/Cargo.toml"));
3927 compile::rustc_cargo_env(builder, &mut cargo, target);
3928 add_cg_gcc_cargo_flags(&mut cargo, &gcc);
3929
3930 cargo.env("CARGO_BUILD_INCREMENTAL", "false");
3932 cargo.rustflag("-Cpanic=abort");
3933
3934 cargo
3935 .env("CG_RUSTFLAGS", "-Alinker-messages")
3937 .arg("--")
3938 .arg("test")
3939 .arg("--use-backend")
3940 .arg("gcc")
3941 .arg("--gcc-path")
3942 .arg(gcc.libgccjit.parent().unwrap())
3943 .arg("--out-dir")
3944 .arg(builder.stage_out(compilers.build_compiler(), Mode::Codegen).join("cg_gcc"))
3945 .arg("--release")
3946 .arg("--mini-tests")
3947 .arg("--std-tests");
3948 cargo.args(builder.config.test_args());
3949
3950 cargo.into_cmd().run(builder);
3951 }
3952
3953 fn metadata(&self) -> Option<StepMetadata> {
3954 Some(
3955 StepMetadata::test("rustc_codegen_gcc", self.target)
3956 .built_by(self.compilers.build_compiler()),
3957 )
3958 }
3959}
3960
3961#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3966pub struct TestFloatParse {
3967 build_compiler: Compiler,
3976 target: TargetSelection,
3978}
3979
3980impl Step for TestFloatParse {
3981 type Output = ();
3982 const IS_HOST: bool = true;
3983
3984 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3985 run.path("src/tools/test-float-parse")
3986 }
3987
3988 fn is_default_step(_builder: &Builder<'_>) -> bool {
3989 true
3990 }
3991
3992 fn make_run(run: RunConfig<'_>) {
3993 run.builder.ensure(Self {
3994 build_compiler: get_compiler_to_test(run.builder, run.target),
3995 target: run.target,
3996 });
3997 }
3998
3999 fn run(self, builder: &Builder<'_>) {
4000 let build_compiler = self.build_compiler;
4001 let target = self.target;
4002
4003 builder.std(build_compiler, target);
4005 builder.std(build_compiler, builder.host_target);
4006
4007 let mut cargo_test = tool::prepare_tool_cargo(
4009 builder,
4010 build_compiler,
4011 Mode::ToolStd,
4012 target,
4013 Kind::Test,
4014 "src/tools/test-float-parse",
4015 SourceType::InTree,
4016 &[],
4017 );
4018 cargo_test.allow_features(TEST_FLOAT_PARSE_ALLOW_FEATURES);
4019
4020 run_cargo_test(cargo_test, &[], &[], "test-float-parse", target, builder);
4021
4022 let mut cargo_run = tool::prepare_tool_cargo(
4024 builder,
4025 build_compiler,
4026 Mode::ToolStd,
4027 target,
4028 Kind::Run,
4029 "src/tools/test-float-parse",
4030 SourceType::InTree,
4031 &[],
4032 );
4033 cargo_run.allow_features(TEST_FLOAT_PARSE_ALLOW_FEATURES);
4034
4035 if !matches!(env::var("FLOAT_PARSE_TESTS_NO_SKIP_HUGE").as_deref(), Ok("1") | Ok("true")) {
4036 cargo_run.args(["--", "--skip-huge"]);
4037 }
4038
4039 cargo_run.into_cmd().run(builder);
4040 }
4041}
4042
4043#[derive(Debug, Clone, Hash, PartialEq, Eq)]
4047pub struct CollectLicenseMetadata;
4048
4049impl Step for CollectLicenseMetadata {
4050 type Output = PathBuf;
4051 const IS_HOST: bool = true;
4052
4053 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
4054 run.path("src/tools/collect-license-metadata")
4055 }
4056
4057 fn make_run(run: RunConfig<'_>) {
4058 run.builder.ensure(CollectLicenseMetadata);
4059 }
4060
4061 fn run(self, builder: &Builder<'_>) -> Self::Output {
4062 let Some(reuse) = &builder.config.reuse else {
4063 panic!("REUSE is required to collect the license metadata");
4064 };
4065
4066 let dest = builder.src.join("license-metadata.json");
4067
4068 let mut cmd = builder.tool_cmd(Tool::CollectLicenseMetadata);
4069 cmd.env("REUSE_EXE", reuse);
4070 cmd.env("DEST", &dest);
4071 cmd.env("ONLY_CHECK", "1");
4072 cmd.run(builder);
4073
4074 dest
4075 }
4076}
4077
4078#[derive(Debug, Clone, PartialEq, Eq, Hash)]
4079pub struct RemoteTestClientTests {
4080 host: TargetSelection,
4081}
4082
4083impl Step for RemoteTestClientTests {
4084 type Output = ();
4085 const IS_HOST: bool = true;
4086
4087 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
4088 run.path("src/tools/remote-test-client")
4089 }
4090
4091 fn is_default_step(_builder: &Builder<'_>) -> bool {
4092 true
4093 }
4094
4095 fn make_run(run: RunConfig<'_>) {
4096 run.builder.ensure(Self { host: run.target });
4097 }
4098
4099 fn run(self, builder: &Builder<'_>) {
4100 let bootstrap_host = builder.config.host_target;
4101 let compiler = builder.compiler(0, bootstrap_host);
4102
4103 let cargo = tool::prepare_tool_cargo(
4104 builder,
4105 compiler,
4106 Mode::ToolBootstrap,
4107 bootstrap_host,
4108 Kind::Test,
4109 "src/tools/remote-test-client",
4110 SourceType::InTree,
4111 &[],
4112 );
4113
4114 run_cargo_test(cargo, &[], &[], "remote-test-client", bootstrap_host, builder);
4115 }
4116}