1use std::collections::HashSet;
10use std::env::split_paths;
11use std::ffi::{OsStr, OsString};
12use std::path::{Path, PathBuf};
13use std::{env, fs, iter};
14
15use build_helper::exit;
16
17use crate::core::build_steps::compile::{ArtifactKeepMode, Std, run_cargo};
18use crate::core::build_steps::doc::{DocumentationFormat, prepare_doc_compiler};
19use crate::core::build_steps::gcc::{Gcc, GccTargetPair, add_cg_gcc_cargo_flags};
20use crate::core::build_steps::llvm::get_llvm_version;
21use crate::core::build_steps::run::{get_completion_paths, get_help_path};
22use crate::core::build_steps::synthetic_targets::MirOptPanicAbortSyntheticTarget;
23use crate::core::build_steps::test::compiletest::CompiletestMode;
24use crate::core::build_steps::tool::{
25 self, RustcPrivateCompilers, SourceType, TEST_FLOAT_PARSE_ALLOW_FEATURES, Tool,
26 ToolTargetBuildMode, get_tool_target_compiler,
27};
28use crate::core::build_steps::toolstate::ToolState;
29use crate::core::build_steps::{compile, dist, llvm};
30use crate::core::builder::{
31 self, Alias, Builder, Compiler, Kind, RunConfig, ShouldRun, Step, StepMetadata,
32 crate_description,
33};
34use crate::core::config::TargetSelection;
35use crate::core::config::flags::{Subcommand, get_completion, top_level_help};
36use crate::core::{android, debuggers};
37use crate::utils::build_stamp::{self, BuildStamp};
38use crate::utils::exec::{BootstrapCommand, command};
39use crate::utils::helpers::{
40 self, LldThreads, add_dylib_path, add_rustdoc_cargo_linker_args, dylib_path, dylib_path_var,
41 linker_args, linker_flags, t, target_supports_cranelift_backend, up_to_date,
42};
43use crate::utils::render_tests::{add_flags_and_try_run_tests, try_run_tests};
44use crate::{CLang, CodegenBackendKind, DocTests, GitRepo, Mode, PathSet, envify};
45
46mod compiletest;
47
48#[derive(Debug, Clone, PartialEq, Eq, Hash)]
50pub struct CrateBootstrap {
51 path: PathBuf,
52 host: TargetSelection,
53}
54
55impl Step for CrateBootstrap {
56 type Output = ();
57 const IS_HOST: bool = true;
58
59 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
60 run.path("src/tools/jsondoclint")
65 .path("src/tools/replace-version-placeholder")
66 .path("src/tools/coverage-dump")
67 .alias("tidyselftest")
70 }
71
72 fn is_default_step(_builder: &Builder<'_>) -> bool {
73 true
74 }
75
76 fn make_run(run: RunConfig<'_>) {
77 for path in run.paths {
80 let path = path.assert_single_path().path.clone();
81 run.builder.ensure(CrateBootstrap { host: run.target, path });
82 }
83 }
84
85 fn run(self, builder: &Builder<'_>) {
86 let bootstrap_host = builder.config.host_target;
87 let compiler = builder.compiler(0, bootstrap_host);
88 let mut path = self.path.to_str().unwrap();
89
90 if path == "tidyselftest" {
92 path = "src/tools/tidy";
93 }
94
95 let cargo = tool::prepare_tool_cargo(
96 builder,
97 compiler,
98 Mode::ToolBootstrap,
99 bootstrap_host,
100 Kind::Test,
101 path,
102 SourceType::InTree,
103 &[],
104 );
105
106 let crate_name = path.rsplit_once('/').unwrap().1;
107 run_cargo_test(cargo, &[], &[], crate_name, bootstrap_host, builder);
108 }
109
110 fn metadata(&self) -> Option<StepMetadata> {
111 Some(
112 StepMetadata::test("crate-bootstrap", self.host)
113 .with_metadata(self.path.as_path().to_string_lossy().to_string()),
114 )
115 }
116}
117
118#[derive(Debug, Clone, PartialEq, Eq, Hash)]
119pub struct Linkcheck {
120 host: TargetSelection,
121}
122
123impl Step for Linkcheck {
124 type Output = ();
125 const IS_HOST: bool = true;
126
127 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
128 run.path("src/tools/linkchecker")
129 }
130
131 fn is_default_step(builder: &Builder<'_>) -> bool {
132 builder.config.docs
133 }
134
135 fn make_run(run: RunConfig<'_>) {
136 run.builder.ensure(Linkcheck { host: run.target });
137 }
138
139 fn run(self, builder: &Builder<'_>) {
144 let host = self.host;
145 let hosts = &builder.hosts;
146 let targets = &builder.targets;
147
148 if (hosts != targets) && !hosts.is_empty() && !targets.is_empty() {
153 panic!(
154 "Linkcheck currently does not support builds with different hosts and targets.
155You can skip linkcheck with --skip src/tools/linkchecker"
156 );
157 }
158
159 builder.info(&format!("Linkcheck ({host})"));
160
161 let bootstrap_host = builder.config.host_target;
163 let compiler = builder.compiler(0, bootstrap_host);
164
165 let cargo = tool::prepare_tool_cargo(
166 builder,
167 compiler,
168 Mode::ToolBootstrap,
169 bootstrap_host,
170 Kind::Test,
171 "src/tools/linkchecker",
172 SourceType::InTree,
173 &[],
174 );
175 run_cargo_test(cargo, &[], &[], "linkchecker self tests", bootstrap_host, builder);
176
177 if builder.doc_tests == DocTests::No {
178 return;
179 }
180
181 builder.run_default_doc_steps();
183
184 let linkchecker = builder.tool_cmd(Tool::Linkchecker);
186
187 let _guard = builder.msg_test("Linkcheck", bootstrap_host, 1);
189 let _time = helpers::timeit(builder);
190 linkchecker.delay_failure().arg(builder.out.join(host).join("doc")).run(builder);
191 }
192
193 fn metadata(&self) -> Option<StepMetadata> {
194 Some(StepMetadata::test("link-check", self.host))
195 }
196}
197
198fn check_if_tidy_is_installed(builder: &Builder<'_>) -> bool {
199 command("tidy")
200 .allow_failure()
201 .arg("--version")
202 .cached()
204 .run_capture_stdout(builder)
205 .is_success()
206}
207
208#[derive(Debug, Clone, PartialEq, Eq, Hash)]
209pub struct HtmlCheck {
210 target: TargetSelection,
211}
212
213impl Step for HtmlCheck {
214 type Output = ();
215 const IS_HOST: bool = true;
216
217 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
218 run.path("src/tools/html-checker")
219 }
220
221 fn is_default_step(builder: &Builder<'_>) -> bool {
222 check_if_tidy_is_installed(builder)
223 }
224
225 fn make_run(run: RunConfig<'_>) {
226 run.builder.ensure(HtmlCheck { target: run.target });
227 }
228
229 fn run(self, builder: &Builder<'_>) {
230 if !check_if_tidy_is_installed(builder) {
231 eprintln!("not running HTML-check tool because `tidy` is missing");
232 eprintln!(
233 "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."
234 );
235 panic!("Cannot run html-check tests");
236 }
237 builder.run_default_doc_steps();
239 builder.ensure(crate::core::build_steps::doc::Rustc::for_stage(
240 builder,
241 builder.top_stage,
242 self.target,
243 ));
244
245 builder
246 .tool_cmd(Tool::HtmlChecker)
247 .delay_failure()
248 .arg(builder.doc_out(self.target))
249 .run(builder);
250 }
251
252 fn metadata(&self) -> Option<StepMetadata> {
253 Some(StepMetadata::test("html-check", self.target))
254 }
255}
256
257#[derive(Debug, Clone, PartialEq, Eq, Hash)]
261pub struct Cargotest {
262 build_compiler: Compiler,
263 host: TargetSelection,
264}
265
266impl Step for Cargotest {
267 type Output = ();
268 const IS_HOST: bool = true;
269
270 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
271 run.path("src/tools/cargotest")
272 }
273
274 fn make_run(run: RunConfig<'_>) {
275 if run.builder.top_stage == 0 {
276 eprintln!(
277 "ERROR: running cargotest with stage 0 is currently unsupported. Use at least stage 1."
278 );
279 exit!(1);
280 }
281 run.builder.ensure(Cargotest {
285 build_compiler: run.builder.compiler(run.builder.top_stage - 1, run.target),
286 host: run.target,
287 });
288 }
289
290 fn run(self, builder: &Builder<'_>) {
295 let cargo =
305 builder.ensure(tool::Cargo::from_build_compiler(self.build_compiler, self.host));
306 let tested_compiler = builder.compiler(self.build_compiler.stage + 1, self.host);
307 builder.std(tested_compiler, self.host);
308
309 let out_dir = builder.out.join("ct");
313 t!(fs::create_dir_all(&out_dir));
314
315 let _time = helpers::timeit(builder);
316 let mut cmd = builder.tool_cmd(Tool::CargoTest);
317 cmd.arg(&cargo.tool_path)
318 .arg(&out_dir)
319 .args(builder.config.test_args())
320 .env("RUSTC", builder.rustc(tested_compiler))
321 .env("RUSTDOC", builder.rustdoc_for_compiler(tested_compiler));
322 add_rustdoc_cargo_linker_args(&mut cmd, builder, tested_compiler.host, LldThreads::No);
323 cmd.delay_failure().run(builder);
324 }
325
326 fn metadata(&self) -> Option<StepMetadata> {
327 Some(StepMetadata::test("cargotest", self.host).stage(self.build_compiler.stage + 1))
328 }
329}
330
331#[derive(Debug, Clone, PartialEq, Eq, Hash)]
334pub struct Cargo {
335 build_compiler: Compiler,
336 host: TargetSelection,
337}
338
339impl Cargo {
340 const CRATE_PATH: &str = "src/tools/cargo";
341}
342
343impl Step for Cargo {
344 type Output = ();
345 const IS_HOST: bool = true;
346
347 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
348 run.path(Self::CRATE_PATH)
349 }
350
351 fn make_run(run: RunConfig<'_>) {
352 run.builder.ensure(Cargo {
353 build_compiler: get_tool_target_compiler(
354 run.builder,
355 ToolTargetBuildMode::Build(run.target),
356 ),
357 host: run.target,
358 });
359 }
360
361 fn run(self, builder: &Builder<'_>) {
363 builder.ensure(tool::Cargo::from_build_compiler(self.build_compiler, self.host));
367
368 let tested_compiler = builder.compiler(self.build_compiler.stage + 1, self.host);
369 builder.std(tested_compiler, self.host);
370 builder.rustdoc_for_compiler(tested_compiler);
374
375 let cargo = tool::prepare_tool_cargo(
376 builder,
377 self.build_compiler,
378 Mode::ToolTarget,
379 self.host,
380 Kind::Test,
381 Self::CRATE_PATH,
382 SourceType::Submodule,
383 &[],
384 );
385
386 let mut cargo = prepare_cargo_test(cargo, &[], &[], self.host, builder);
388
389 cargo.env("CFG_DISABLE_CROSS_TESTS", "1");
392 cargo.env("CARGO_TEST_DISABLE_NIGHTLY", "1");
395
396 cargo.env("PATH", bin_path_for_cargo(builder, tested_compiler));
400
401 let mut existing_dylib_paths = cargo
406 .get_envs()
407 .find(|(k, _)| *k == OsStr::new(dylib_path_var()))
408 .and_then(|(_, v)| v)
409 .map(|value| split_paths(value).collect::<Vec<PathBuf>>())
410 .unwrap_or_default();
411 existing_dylib_paths.insert(0, builder.rustc_libdir(tested_compiler));
412 add_dylib_path(existing_dylib_paths, &mut cargo);
413
414 cargo.env("CARGO_RUSTC_CURRENT_DIR", builder.src.display().to_string());
418
419 #[cfg(feature = "build-metrics")]
420 builder.metrics.begin_test_suite(
421 build_helper::metrics::TestSuiteMetadata::CargoPackage {
422 crates: vec!["cargo".into()],
423 target: self.host.triple.to_string(),
424 host: self.host.triple.to_string(),
425 stage: self.build_compiler.stage + 1,
426 },
427 builder,
428 );
429
430 let _time = helpers::timeit(builder);
431 add_flags_and_try_run_tests(builder, &mut cargo);
432 }
433
434 fn metadata(&self) -> Option<StepMetadata> {
435 Some(StepMetadata::test("cargo", self.host).built_by(self.build_compiler))
436 }
437}
438
439#[derive(Debug, Clone, PartialEq, Eq, Hash)]
440pub struct RustAnalyzer {
441 compilers: RustcPrivateCompilers,
442}
443
444impl Step for RustAnalyzer {
445 type Output = ();
446 const IS_HOST: bool = true;
447
448 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
449 run.path("src/tools/rust-analyzer")
450 }
451
452 fn is_default_step(_builder: &Builder<'_>) -> bool {
453 true
454 }
455
456 fn make_run(run: RunConfig<'_>) {
457 run.builder.ensure(Self {
458 compilers: RustcPrivateCompilers::new(
459 run.builder,
460 run.builder.top_stage,
461 run.builder.host_target,
462 ),
463 });
464 }
465
466 fn run(self, builder: &Builder<'_>) {
468 let build_compiler = self.compilers.build_compiler();
469 let target = self.compilers.target();
470
471 if target.starts_with("i686") {
481 return;
482 }
483
484 let mut cargo = tool::prepare_tool_cargo(
485 builder,
486 build_compiler,
487 Mode::ToolRustcPrivate,
488 target,
489 Kind::Test,
490 "src/tools/rust-analyzer",
491 SourceType::InTree,
492 &["in-rust-tree".to_owned()],
493 );
494 cargo.allow_features(tool::RustAnalyzer::ALLOW_FEATURES);
495
496 cargo.env("SKIP_SLOW_TESTS", "1");
503
504 cargo.arg("--workspace");
510 cargo.arg("--exclude=xtask");
511
512 if build_compiler.stage == 0 {
513 cargo.arg("--exclude=proc-macro-srv");
516 cargo.arg("--exclude=proc-macro-srv-cli");
517 }
518
519 let mut skip_tests = vec![];
520
521 skip_tests.extend_from_slice(&[
529 "tests::smoke_test_real_sysroot_cargo",
532 "check_code_formatting",
535 ]);
536
537 let skip_tests = skip_tests.iter().map(|name| format!("--skip={name}")).collect::<Vec<_>>();
538 let skip_tests = skip_tests.iter().map(|s| s.as_str()).collect::<Vec<_>>();
539
540 cargo.add_rustc_lib_path(builder);
541 run_cargo_test(cargo, skip_tests.as_slice(), &[], "rust-analyzer", target, builder);
542 }
543
544 fn metadata(&self) -> Option<StepMetadata> {
545 Some(
546 StepMetadata::test("rust-analyzer", self.compilers.target())
547 .built_by(self.compilers.build_compiler()),
548 )
549 }
550}
551
552#[derive(Debug, Clone, PartialEq, Eq, Hash)]
554pub struct Rustfmt {
555 compilers: RustcPrivateCompilers,
556}
557
558impl Step for Rustfmt {
559 type Output = ();
560 const IS_HOST: bool = true;
561
562 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
563 run.path("src/tools/rustfmt")
564 }
565
566 fn make_run(run: RunConfig<'_>) {
567 run.builder.ensure(Rustfmt {
568 compilers: RustcPrivateCompilers::new(
569 run.builder,
570 run.builder.top_stage,
571 run.builder.host_target,
572 ),
573 });
574 }
575
576 fn run(self, builder: &Builder<'_>) {
578 let build_compiler = self.compilers.build_compiler();
579 let target = self.compilers.target();
580
581 let mut cargo = tool::prepare_tool_cargo(
582 builder,
583 build_compiler,
584 Mode::ToolRustcPrivate,
585 target,
586 Kind::Test,
587 "src/tools/rustfmt",
588 SourceType::InTree,
589 &[],
590 );
591
592 let dir = testdir(builder, target);
593 t!(fs::create_dir_all(&dir));
594 cargo.env("RUSTFMT_TEST_DIR", dir);
595
596 cargo.add_rustc_lib_path(builder);
597
598 run_cargo_test(cargo, &[], &[], "rustfmt", target, builder);
599 }
600
601 fn metadata(&self) -> Option<StepMetadata> {
602 Some(
603 StepMetadata::test("rustfmt", self.compilers.target())
604 .built_by(self.compilers.build_compiler()),
605 )
606 }
607}
608
609#[derive(Debug, Clone, PartialEq, Eq, Hash)]
610pub struct Miri {
611 target: TargetSelection,
612}
613
614impl Miri {
615 pub fn build_miri_sysroot(
617 builder: &Builder<'_>,
618 compiler: Compiler,
619 target: TargetSelection,
620 ) -> PathBuf {
621 let miri_sysroot = builder.out.join(compiler.host).join("miri-sysroot");
622 let mut cargo = builder::Cargo::new(
623 builder,
624 compiler,
625 Mode::Std,
626 SourceType::Submodule,
627 target,
628 Kind::MiriSetup,
629 );
630
631 cargo.env("MIRI_LIB_SRC", builder.src.join("library"));
633 cargo.env("MIRI_SYSROOT", &miri_sysroot);
635
636 let mut cargo = BootstrapCommand::from(cargo);
637 let _guard =
638 builder.msg(Kind::Build, "miri sysroot", Mode::ToolRustcPrivate, compiler, target);
639 cargo.run(builder);
640
641 cargo.arg("--print-sysroot");
647
648 builder.do_if_verbose(|| println!("running: {cargo:?}"));
649 let stdout = cargo.run_capture_stdout(builder).stdout();
650 let sysroot = stdout.trim_end();
652 builder.do_if_verbose(|| println!("`cargo miri setup --print-sysroot` said: {sysroot:?}"));
653 PathBuf::from(sysroot)
654 }
655}
656
657impl Step for Miri {
658 type Output = ();
659
660 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
661 run.path("src/tools/miri")
662 }
663
664 fn make_run(run: RunConfig<'_>) {
665 run.builder.ensure(Miri { target: run.target });
666 }
667
668 fn run(self, builder: &Builder<'_>) {
670 let host = builder.build.host_target;
671 let target = self.target;
672 let stage = builder.top_stage;
673 if stage == 0 {
674 eprintln!("miri cannot be tested at stage 0");
675 std::process::exit(1);
676 }
677
678 let compilers = RustcPrivateCompilers::new(builder, stage, host);
680
681 let miri = builder.ensure(tool::Miri::from_compilers(compilers));
683 builder.ensure(tool::CargoMiri::from_compilers(compilers));
685
686 let target_compiler = compilers.target_compiler();
687
688 let miri_sysroot = Miri::build_miri_sysroot(builder, target_compiler, target);
691 builder.std(target_compiler, host);
692 let host_sysroot = builder.sysroot(target_compiler);
693
694 if !builder.config.dry_run() {
697 let ui_test_dep_dir = builder
700 .stage_out(miri.build_compiler, Mode::ToolStd)
701 .join(host)
702 .join("tmp")
703 .join("miri_ui");
704 build_stamp::clear_if_dirty(builder, &ui_test_dep_dir, &miri_sysroot);
708 }
709
710 let mut cargo = tool::prepare_tool_cargo(
713 builder,
714 miri.build_compiler,
715 Mode::ToolRustcPrivate,
716 host,
717 Kind::Test,
718 "src/tools/miri",
719 SourceType::InTree,
720 &[],
721 );
722
723 cargo.add_rustc_lib_path(builder);
724
725 let mut cargo = prepare_cargo_test(cargo, &[], &[], host, builder);
728
729 cargo.env("MIRI_SYSROOT", &miri_sysroot);
731 cargo.env("MIRI_HOST_SYSROOT", &host_sysroot);
732
733 cargo.env("MIRI_TEST_TARGET", target.rustc_target_arg());
735
736 {
737 let _guard = builder.msg_test("miri", target, target_compiler.stage);
738 let _time = helpers::timeit(builder);
739 cargo.run(builder);
740 }
741
742 if builder.config.test_args().is_empty() {
744 cargo.env("MIRIFLAGS", "-O -Zmir-opt-level=4 -Cdebug-assertions=yes");
745 cargo.env("MIRI_SKIP_UI_CHECKS", "1");
747 cargo.env_remove("RUSTC_BLESS");
749 cargo.args(["tests/pass", "tests/panic"]);
751
752 {
753 let _guard =
754 builder.msg_test("miri (mir-opt-level 4)", target, target_compiler.stage);
755 let _time = helpers::timeit(builder);
756 cargo.run(builder);
757 }
758 }
759 }
760}
761
762#[derive(Debug, Clone, PartialEq, Eq, Hash)]
765pub struct CargoMiri {
766 target: TargetSelection,
767}
768
769impl Step for CargoMiri {
770 type Output = ();
771
772 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
773 run.path("src/tools/miri/cargo-miri")
774 }
775
776 fn make_run(run: RunConfig<'_>) {
777 run.builder.ensure(CargoMiri { target: run.target });
778 }
779
780 fn run(self, builder: &Builder<'_>) {
782 let host = builder.build.host_target;
783 let target = self.target;
784 let stage = builder.top_stage;
785 if stage == 0 {
786 eprintln!("cargo-miri cannot be tested at stage 0");
787 std::process::exit(1);
788 }
789
790 let build_compiler = builder.compiler(stage, host);
792
793 let mut cargo = tool::prepare_tool_cargo(
798 builder,
799 build_compiler,
800 Mode::ToolStd, target,
802 Kind::MiriTest,
803 "src/tools/miri/test-cargo-miri",
804 SourceType::Submodule,
805 &[],
806 );
807
808 match builder.doc_tests {
811 DocTests::Yes => {}
812 DocTests::No => {
813 cargo.args(["--lib", "--bins", "--examples", "--tests", "--benches"]);
814 }
815 DocTests::Only => {
816 cargo.arg("--doc");
817 }
818 }
819 cargo.arg("--").args(builder.config.test_args());
820
821 let mut cargo = BootstrapCommand::from(cargo);
823 {
824 let _guard = builder.msg_test("cargo-miri", target, stage);
825 let _time = helpers::timeit(builder);
826 cargo.run(builder);
827 }
828 }
829}
830
831#[derive(Debug, Clone, PartialEq, Eq, Hash)]
832pub struct CompiletestTest {
833 host: TargetSelection,
834}
835
836impl Step for CompiletestTest {
837 type Output = ();
838
839 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
840 run.path("src/tools/compiletest")
841 }
842
843 fn make_run(run: RunConfig<'_>) {
844 run.builder.ensure(CompiletestTest { host: run.target });
845 }
846
847 fn run(self, builder: &Builder<'_>) {
849 let host = self.host;
850
851 if builder.top_stage == 0 && !builder.config.compiletest_allow_stage0 {
857 eprintln!("\
858ERROR: `--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
859NOTE: 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`."
860 );
861 crate::exit!(1);
862 }
863
864 let bootstrap_compiler = builder.compiler(0, host);
865 let staged_compiler = builder.compiler(builder.top_stage, host);
866
867 let mut cargo = tool::prepare_tool_cargo(
868 builder,
869 bootstrap_compiler,
870 Mode::ToolBootstrap,
871 host,
872 Kind::Test,
873 "src/tools/compiletest",
874 SourceType::InTree,
875 &[],
876 );
877
878 cargo.env("TEST_RUSTC", builder.rustc(staged_compiler));
882
883 run_cargo_test(cargo, &[], &[], "compiletest self test", host, builder);
884 }
885}
886
887#[derive(Debug, Clone, PartialEq, Eq, Hash)]
888pub struct Clippy {
889 compilers: RustcPrivateCompilers,
890}
891
892impl Step for Clippy {
893 type Output = ();
894 const IS_HOST: bool = true;
895
896 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
897 run.suite_path("src/tools/clippy/tests").path("src/tools/clippy")
898 }
899
900 fn is_default_step(_builder: &Builder<'_>) -> bool {
901 false
902 }
903
904 fn make_run(run: RunConfig<'_>) {
905 run.builder.ensure(Clippy {
906 compilers: RustcPrivateCompilers::new(
907 run.builder,
908 run.builder.top_stage,
909 run.builder.host_target,
910 ),
911 });
912 }
913
914 fn run(self, builder: &Builder<'_>) {
916 let target = self.compilers.target();
917
918 let target_compiler = self.compilers.target_compiler();
922 let build_compiler = self.compilers.build_compiler();
923
924 let mut cargo = tool::prepare_tool_cargo(
925 builder,
926 build_compiler,
927 Mode::ToolRustcPrivate,
928 target,
929 Kind::Test,
930 "src/tools/clippy",
931 SourceType::InTree,
932 &[],
933 );
934
935 cargo.env("RUSTC_TEST_SUITE", builder.rustc(build_compiler));
936 cargo.env("RUSTC_LIB_PATH", builder.rustc_libdir(build_compiler));
937 let host_libs = builder
938 .stage_out(build_compiler, Mode::ToolRustcPrivate)
939 .join(builder.cargo_dir(Mode::ToolRustcPrivate));
940 cargo.env("HOST_LIBS", host_libs);
941
942 builder.std(target_compiler, target);
944 cargo.env("TEST_SYSROOT", builder.sysroot(target_compiler));
945 cargo.env("TEST_RUSTC", builder.rustc(target_compiler));
946 cargo.env("TEST_RUSTC_LIB", builder.rustc_libdir(target_compiler));
947
948 'partially_test: {
950 let paths = &builder.config.paths[..];
951 let mut test_names = Vec::new();
952 for path in paths {
953 if let Some(path) =
954 helpers::is_valid_test_suite_arg(path, "src/tools/clippy/tests", builder)
955 {
956 test_names.push(path);
957 } else if path.ends_with("src/tools/clippy") {
958 break 'partially_test;
960 }
961 }
962 cargo.env("TESTNAME", test_names.join(","));
963 }
964
965 cargo.add_rustc_lib_path(builder);
966 let cargo = prepare_cargo_test(cargo, &[], &[], target, builder);
967
968 let _guard = builder.msg_test("clippy", target, target_compiler.stage);
969
970 if cargo.allow_failure().run(builder) {
972 return;
974 }
975
976 if !builder.config.cmd.bless() {
977 crate::exit!(1);
978 }
979 }
980
981 fn metadata(&self) -> Option<StepMetadata> {
982 Some(
983 StepMetadata::test("clippy", self.compilers.target())
984 .built_by(self.compilers.build_compiler()),
985 )
986 }
987}
988
989fn bin_path_for_cargo(builder: &Builder<'_>, compiler: Compiler) -> OsString {
990 let path = builder.sysroot(compiler).join("bin");
991 let old_path = env::var_os("PATH").unwrap_or_default();
992 env::join_paths(iter::once(path).chain(env::split_paths(&old_path))).expect("")
993}
994
995#[derive(Debug, Clone, Hash, PartialEq, Eq)]
997pub struct RustdocTheme {
998 test_compiler: Compiler,
1000}
1001
1002impl Step for RustdocTheme {
1003 type Output = ();
1004 const IS_HOST: bool = true;
1005
1006 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1007 run.path("src/tools/rustdoc-themes")
1008 }
1009
1010 fn is_default_step(_builder: &Builder<'_>) -> bool {
1011 true
1012 }
1013
1014 fn make_run(run: RunConfig<'_>) {
1015 let test_compiler = run.builder.compiler(run.builder.top_stage, run.target);
1016
1017 run.builder.ensure(RustdocTheme { test_compiler });
1018 }
1019
1020 fn run(self, builder: &Builder<'_>) {
1021 let rustdoc = builder.bootstrap_out.join("rustdoc");
1022 let mut cmd = builder.tool_cmd(Tool::RustdocTheme);
1023 cmd.arg(rustdoc.to_str().unwrap())
1024 .arg(builder.src.join("src/librustdoc/html/static/css/rustdoc.css").to_str().unwrap())
1025 .env("RUSTC_STAGE", self.test_compiler.stage.to_string())
1026 .env("RUSTC_SYSROOT", builder.sysroot(self.test_compiler))
1027 .env(
1028 "RUSTDOC_LIBDIR",
1029 builder.sysroot_target_libdir(self.test_compiler, self.test_compiler.host),
1030 )
1031 .env("CFG_RELEASE_CHANNEL", &builder.config.channel)
1032 .env("RUSTDOC_REAL", builder.rustdoc_for_compiler(self.test_compiler))
1033 .env("RUSTC_BOOTSTRAP", "1");
1034 cmd.args(linker_args(builder, self.test_compiler.host, LldThreads::No));
1035
1036 cmd.delay_failure().run(builder);
1037 }
1038
1039 fn metadata(&self) -> Option<StepMetadata> {
1040 Some(
1041 StepMetadata::test("rustdoc-theme", self.test_compiler.host)
1042 .stage(self.test_compiler.stage),
1043 )
1044 }
1045}
1046
1047#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1049pub struct RustdocJSStd {
1050 build_compiler: Compiler,
1052 target: TargetSelection,
1053}
1054
1055impl Step for RustdocJSStd {
1056 type Output = ();
1057 const IS_HOST: bool = true;
1058
1059 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1060 run.suite_path("tests/rustdoc-js-std")
1061 }
1062
1063 fn is_default_step(builder: &Builder<'_>) -> bool {
1064 builder.config.nodejs.is_some()
1065 }
1066
1067 fn make_run(run: RunConfig<'_>) {
1068 run.builder.ensure(RustdocJSStd {
1069 build_compiler: run.builder.compiler(run.builder.top_stage, run.builder.host_target),
1070 target: run.target,
1071 });
1072 }
1073
1074 fn run(self, builder: &Builder<'_>) {
1075 let nodejs =
1076 builder.config.nodejs.as_ref().expect("need nodejs to run rustdoc-js-std tests");
1077 let mut command = command(nodejs);
1078 command
1079 .arg(builder.src.join("src/tools/rustdoc-js/tester.js"))
1080 .arg("--crate-name")
1081 .arg("std")
1082 .arg("--resource-suffix")
1083 .arg(&builder.version)
1084 .arg("--doc-folder")
1085 .arg(builder.doc_out(self.target))
1086 .arg("--test-folder")
1087 .arg(builder.src.join("tests/rustdoc-js-std"));
1088 for path in &builder.paths {
1089 if let Some(p) = helpers::is_valid_test_suite_arg(path, "tests/rustdoc-js-std", builder)
1090 {
1091 if !p.ends_with(".js") {
1092 eprintln!("A non-js file was given: `{}`", path.display());
1093 panic!("Cannot run rustdoc-js-std tests");
1094 }
1095 command.arg("--test-file").arg(path);
1096 }
1097 }
1098 builder.ensure(crate::core::build_steps::doc::Std::from_build_compiler(
1099 self.build_compiler,
1100 self.target,
1101 DocumentationFormat::Html,
1102 ));
1103 let _guard = builder.msg_test("rustdoc-js-std", self.target, self.build_compiler.stage);
1104 command.run(builder);
1105 }
1106
1107 fn metadata(&self) -> Option<StepMetadata> {
1108 Some(StepMetadata::test("rustdoc-js-std", self.target).stage(self.build_compiler.stage))
1109 }
1110}
1111
1112#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1113pub struct RustdocJSNotStd {
1114 pub target: TargetSelection,
1115 pub compiler: Compiler,
1116}
1117
1118impl Step for RustdocJSNotStd {
1119 type Output = ();
1120 const IS_HOST: bool = true;
1121
1122 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1123 run.suite_path("tests/rustdoc-js")
1124 }
1125
1126 fn is_default_step(builder: &Builder<'_>) -> bool {
1127 builder.config.nodejs.is_some()
1128 }
1129
1130 fn make_run(run: RunConfig<'_>) {
1131 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1132 run.builder.ensure(RustdocJSNotStd { target: run.target, compiler });
1133 }
1134
1135 fn run(self, builder: &Builder<'_>) {
1136 builder.ensure(Compiletest {
1137 test_compiler: self.compiler,
1138 target: self.target,
1139 mode: CompiletestMode::RustdocJs,
1140 suite: "rustdoc-js",
1141 path: "tests/rustdoc-js",
1142 compare_mode: None,
1143 });
1144 }
1145}
1146
1147fn get_browser_ui_test_version_inner(
1148 builder: &Builder<'_>,
1149 yarn: &Path,
1150 global: bool,
1151) -> Option<String> {
1152 let mut command = command(yarn);
1153 command
1154 .arg("--cwd")
1155 .arg(&builder.build.out)
1156 .arg("list")
1157 .arg("--parseable")
1158 .arg("--long")
1159 .arg("--depth=0");
1160 if global {
1161 command.arg("--global");
1162 }
1163 let lines = command.allow_failure().cached().run_capture(builder).stdout();
1166 lines
1167 .lines()
1168 .find_map(|l| l.split(':').nth(1)?.strip_prefix("browser-ui-test@"))
1169 .map(|v| v.to_owned())
1170}
1171
1172fn get_browser_ui_test_version(builder: &Builder<'_>) -> Option<String> {
1173 let yarn = builder.config.yarn.as_deref()?;
1174 get_browser_ui_test_version_inner(builder, yarn, false)
1175 .or_else(|| get_browser_ui_test_version_inner(builder, yarn, true))
1176}
1177
1178#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1180pub struct RustdocGUI {
1181 test_compiler: Compiler,
1183 target: TargetSelection,
1184}
1185
1186impl Step for RustdocGUI {
1187 type Output = ();
1188 const IS_HOST: bool = true;
1189
1190 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1191 run.suite_path("tests/rustdoc-gui")
1192 }
1193
1194 fn is_default_step(builder: &Builder<'_>) -> bool {
1195 builder.config.nodejs.is_some()
1196 && builder.doc_tests != DocTests::Only
1197 && get_browser_ui_test_version(builder).is_some()
1198 }
1199
1200 fn make_run(run: RunConfig<'_>) {
1201 let test_compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1202 run.builder.ensure(RustdocGUI { test_compiler, target: run.target });
1203 }
1204
1205 fn run(self, builder: &Builder<'_>) {
1206 builder.std(self.test_compiler, self.target);
1207
1208 let mut cmd = builder.tool_cmd(Tool::RustdocGUITest);
1209
1210 let out_dir = builder.test_out(self.target).join("rustdoc-gui");
1211 build_stamp::clear_if_dirty(
1212 builder,
1213 &out_dir,
1214 &builder.rustdoc_for_compiler(self.test_compiler),
1215 );
1216
1217 if let Some(src) = builder.config.src.to_str() {
1218 cmd.arg("--rust-src").arg(src);
1219 }
1220
1221 if let Some(out_dir) = out_dir.to_str() {
1222 cmd.arg("--out-dir").arg(out_dir);
1223 }
1224
1225 if let Some(initial_cargo) = builder.config.initial_cargo.to_str() {
1226 cmd.arg("--initial-cargo").arg(initial_cargo);
1227 }
1228
1229 cmd.arg("--jobs").arg(builder.jobs().to_string());
1230
1231 cmd.env("RUSTDOC", builder.rustdoc_for_compiler(self.test_compiler))
1232 .env("RUSTC", builder.rustc(self.test_compiler));
1233
1234 add_rustdoc_cargo_linker_args(&mut cmd, builder, self.test_compiler.host, LldThreads::No);
1235
1236 for path in &builder.paths {
1237 if let Some(p) = helpers::is_valid_test_suite_arg(path, "tests/rustdoc-gui", builder) {
1238 if !p.ends_with(".goml") {
1239 eprintln!("A non-goml file was given: `{}`", path.display());
1240 panic!("Cannot run rustdoc-gui tests");
1241 }
1242 if let Some(name) = path.file_name().and_then(|f| f.to_str()) {
1243 cmd.arg("--goml-file").arg(name);
1244 }
1245 }
1246 }
1247
1248 for test_arg in builder.config.test_args() {
1249 cmd.arg("--test-arg").arg(test_arg);
1250 }
1251
1252 if let Some(ref nodejs) = builder.config.nodejs {
1253 cmd.arg("--nodejs").arg(nodejs);
1254 }
1255
1256 if let Some(ref yarn) = builder.config.yarn {
1257 cmd.arg("--yarn").arg(yarn);
1258 }
1259
1260 let _time = helpers::timeit(builder);
1261 let _guard = builder.msg_test("rustdoc-gui", self.target, self.test_compiler.stage);
1262 try_run_tests(builder, &mut cmd, true);
1263 }
1264
1265 fn metadata(&self) -> Option<StepMetadata> {
1266 Some(StepMetadata::test("rustdoc-gui", self.target).stage(self.test_compiler.stage))
1267 }
1268}
1269
1270#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1275pub struct Tidy;
1276
1277impl Step for Tidy {
1278 type Output = ();
1279 const IS_HOST: bool = true;
1280
1281 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1282 run.path("src/tools/tidy")
1283 }
1284
1285 fn is_default_step(builder: &Builder<'_>) -> bool {
1286 builder.doc_tests != DocTests::Only
1287 }
1288
1289 fn make_run(run: RunConfig<'_>) {
1290 run.builder.ensure(Tidy);
1291 }
1292
1293 fn run(self, builder: &Builder<'_>) {
1302 let mut cmd = builder.tool_cmd(Tool::Tidy);
1303 cmd.arg(format!("--root-path={}", &builder.src.display()));
1304 cmd.arg(format!("--cargo-path={}", &builder.initial_cargo.display()));
1305 cmd.arg(format!("--output-dir={}", &builder.out.display()));
1306 let jobs = builder.config.jobs.unwrap_or_else(|| {
1308 8 * std::thread::available_parallelism().map_or(1, std::num::NonZeroUsize::get) as u32
1309 });
1310 cmd.arg(format!("--concurrency={jobs}"));
1311 if let Some(yarn) = &builder.config.yarn {
1313 cmd.arg(format!("--npm-path={}", yarn.display()));
1314 } else {
1315 cmd.arg("--npm-path=yarn");
1316 }
1317 if builder.is_verbose() {
1318 cmd.arg("--verbose");
1319 }
1320 if builder.config.cmd.bless() {
1321 cmd.arg("--bless");
1322 }
1323 if let Some(s) =
1324 builder.config.cmd.extra_checks().or(builder.config.tidy_extra_checks.as_deref())
1325 {
1326 cmd.arg(format!("--extra-checks={s}"));
1327 }
1328 let mut args = std::env::args_os();
1329 if args.any(|arg| arg == OsStr::new("--")) {
1330 cmd.arg("--");
1331 cmd.args(args);
1332 }
1333
1334 if builder.config.channel == "dev" || builder.config.channel == "nightly" {
1335 if !builder.config.json_output {
1336 builder.info("fmt check");
1337 if builder.config.initial_rustfmt.is_none() {
1338 let inferred_rustfmt_dir = builder.initial_sysroot.join("bin");
1339 eprintln!(
1340 "\
1341ERROR: no `rustfmt` binary found in {PATH}
1342INFO: `rust.channel` is currently set to \"{CHAN}\"
1343HELP: if you are testing a beta branch, set `rust.channel` to \"beta\" in the `bootstrap.toml` file
1344HELP: to skip test's attempt to check tidiness, pass `--skip src/tools/tidy` to `x.py test`",
1345 PATH = inferred_rustfmt_dir.display(),
1346 CHAN = builder.config.channel,
1347 );
1348 crate::exit!(1);
1349 }
1350 let all = false;
1351 crate::core::build_steps::format::format(
1352 builder,
1353 !builder.config.cmd.bless(),
1354 all,
1355 &[],
1356 );
1357 } else {
1358 eprintln!(
1359 "WARNING: `--json-output` is not supported on rustfmt, formatting will be skipped"
1360 );
1361 }
1362 }
1363
1364 builder.info("tidy check");
1365 cmd.delay_failure().run(builder);
1366
1367 builder.info("x.py completions check");
1368 let completion_paths = get_completion_paths(builder);
1369 if builder.config.cmd.bless() {
1370 builder.ensure(crate::core::build_steps::run::GenerateCompletions);
1371 } else if completion_paths
1372 .into_iter()
1373 .any(|(shell, path)| get_completion(shell, &path).is_some())
1374 {
1375 eprintln!(
1376 "x.py completions were changed; run `x.py run generate-completions` to update them"
1377 );
1378 crate::exit!(1);
1379 }
1380
1381 builder.info("x.py help check");
1382 if builder.config.cmd.bless() {
1383 builder.ensure(crate::core::build_steps::run::GenerateHelp);
1384 } else {
1385 let help_path = get_help_path(builder);
1386 let cur_help = std::fs::read_to_string(&help_path).unwrap_or_else(|err| {
1387 eprintln!("couldn't read {}: {}", help_path.display(), err);
1388 crate::exit!(1);
1389 });
1390 let new_help = top_level_help();
1391
1392 if new_help != cur_help {
1393 eprintln!("x.py help was changed; run `x.py run generate-help` to update it");
1394 crate::exit!(1);
1395 }
1396 }
1397 }
1398
1399 fn metadata(&self) -> Option<StepMetadata> {
1400 Some(StepMetadata::test("tidy", TargetSelection::default()))
1401 }
1402}
1403
1404#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1407pub struct CrateRunMakeSupport {
1408 host: TargetSelection,
1409}
1410
1411impl Step for CrateRunMakeSupport {
1412 type Output = ();
1413 const IS_HOST: bool = true;
1414
1415 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1416 run.path("src/tools/run-make-support")
1417 }
1418
1419 fn make_run(run: RunConfig<'_>) {
1420 run.builder.ensure(CrateRunMakeSupport { host: run.target });
1421 }
1422
1423 fn run(self, builder: &Builder<'_>) {
1425 let host = self.host;
1426 let compiler = builder.compiler(0, host);
1427
1428 let mut cargo = tool::prepare_tool_cargo(
1429 builder,
1430 compiler,
1431 Mode::ToolBootstrap,
1432 host,
1433 Kind::Test,
1434 "src/tools/run-make-support",
1435 SourceType::InTree,
1436 &[],
1437 );
1438 cargo.allow_features("test");
1439 run_cargo_test(cargo, &[], &[], "run-make-support self test", host, builder);
1440 }
1441}
1442
1443#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1444pub struct CrateBuildHelper {
1445 host: TargetSelection,
1446}
1447
1448impl Step for CrateBuildHelper {
1449 type Output = ();
1450 const IS_HOST: bool = true;
1451
1452 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1453 run.path("src/build_helper")
1454 }
1455
1456 fn make_run(run: RunConfig<'_>) {
1457 run.builder.ensure(CrateBuildHelper { host: run.target });
1458 }
1459
1460 fn run(self, builder: &Builder<'_>) {
1462 let host = self.host;
1463 let compiler = builder.compiler(0, host);
1464
1465 let mut cargo = tool::prepare_tool_cargo(
1466 builder,
1467 compiler,
1468 Mode::ToolBootstrap,
1469 host,
1470 Kind::Test,
1471 "src/build_helper",
1472 SourceType::InTree,
1473 &[],
1474 );
1475 cargo.allow_features("test");
1476 run_cargo_test(cargo, &[], &[], "build_helper self test", host, builder);
1477 }
1478}
1479
1480fn testdir(builder: &Builder<'_>, host: TargetSelection) -> PathBuf {
1481 builder.out.join(host).join("test")
1482}
1483
1484macro_rules! test {
1486 (
1487 $( #[$attr:meta] )* $name:ident {
1489 path: $path:expr,
1490 mode: $mode:expr,
1491 suite: $suite:expr,
1492 default: $default:expr
1493 $( , IS_HOST: $IS_HOST:expr )? $( , compare_mode: $compare_mode:expr )? $( , )? }
1497 ) => {
1498 $( #[$attr] )*
1499 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
1500 pub struct $name {
1501 test_compiler: Compiler,
1502 target: TargetSelection,
1503 }
1504
1505 impl Step for $name {
1506 type Output = ();
1507 const IS_HOST: bool = (const {
1508 #[allow(unused_assignments, unused_mut)]
1509 let mut value = false;
1510 $( value = $IS_HOST; )?
1511 value
1512 });
1513
1514 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1515 run.suite_path($path)
1516 }
1517
1518 fn is_default_step(_builder: &Builder<'_>) -> bool {
1519 const { $default }
1520 }
1521
1522 fn make_run(run: RunConfig<'_>) {
1523 let test_compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1524
1525 run.builder.ensure($name { test_compiler, target: run.target });
1526 }
1527
1528 fn run(self, builder: &Builder<'_>) {
1529 builder.ensure(Compiletest {
1530 test_compiler: self.test_compiler,
1531 target: self.target,
1532 mode: const { $mode },
1533 suite: $suite,
1534 path: $path,
1535 compare_mode: (const {
1536 #[allow(unused_assignments, unused_mut)]
1537 let mut value = None;
1538 $( value = $compare_mode; )?
1539 value
1540 }),
1541 })
1542 }
1543 }
1544 };
1545}
1546
1547test!(Ui { path: "tests/ui", mode: CompiletestMode::Ui, suite: "ui", default: true });
1548
1549test!(Crashes {
1550 path: "tests/crashes",
1551 mode: CompiletestMode::Crashes,
1552 suite: "crashes",
1553 default: true,
1554});
1555
1556test!(CodegenLlvm {
1557 path: "tests/codegen-llvm",
1558 mode: CompiletestMode::Codegen,
1559 suite: "codegen-llvm",
1560 default: true
1561});
1562
1563test!(CodegenUnits {
1564 path: "tests/codegen-units",
1565 mode: CompiletestMode::CodegenUnits,
1566 suite: "codegen-units",
1567 default: true,
1568});
1569
1570test!(Incremental {
1571 path: "tests/incremental",
1572 mode: CompiletestMode::Incremental,
1573 suite: "incremental",
1574 default: true,
1575});
1576
1577test!(Debuginfo {
1578 path: "tests/debuginfo",
1579 mode: CompiletestMode::Debuginfo,
1580 suite: "debuginfo",
1581 default: true,
1582 compare_mode: Some("split-dwarf"),
1583});
1584
1585test!(UiFullDeps {
1586 path: "tests/ui-fulldeps",
1587 mode: CompiletestMode::Ui,
1588 suite: "ui-fulldeps",
1589 default: true,
1590 IS_HOST: true,
1591});
1592
1593test!(RustdocHtml {
1594 path: "tests/rustdoc-html",
1595 mode: CompiletestMode::RustdocHtml,
1596 suite: "rustdoc-html",
1597 default: true,
1598 IS_HOST: true,
1599});
1600test!(RustdocUi {
1601 path: "tests/rustdoc-ui",
1602 mode: CompiletestMode::Ui,
1603 suite: "rustdoc-ui",
1604 default: true,
1605 IS_HOST: true,
1606});
1607
1608test!(RustdocJson {
1609 path: "tests/rustdoc-json",
1610 mode: CompiletestMode::RustdocJson,
1611 suite: "rustdoc-json",
1612 default: true,
1613 IS_HOST: true,
1614});
1615
1616test!(Pretty {
1617 path: "tests/pretty",
1618 mode: CompiletestMode::Pretty,
1619 suite: "pretty",
1620 default: true,
1621 IS_HOST: true,
1622});
1623
1624test!(RunMake {
1625 path: "tests/run-make",
1626 mode: CompiletestMode::RunMake,
1627 suite: "run-make",
1628 default: true,
1629});
1630test!(RunMakeCargo {
1631 path: "tests/run-make-cargo",
1632 mode: CompiletestMode::RunMake,
1633 suite: "run-make-cargo",
1634 default: true
1635});
1636test!(BuildStd {
1637 path: "tests/build-std",
1638 mode: CompiletestMode::RunMake,
1639 suite: "build-std",
1640 default: false
1641});
1642
1643test!(AssemblyLlvm {
1644 path: "tests/assembly-llvm",
1645 mode: CompiletestMode::Assembly,
1646 suite: "assembly-llvm",
1647 default: true
1648});
1649
1650#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1653pub struct Coverage {
1654 pub compiler: Compiler,
1655 pub target: TargetSelection,
1656 pub(crate) mode: CompiletestMode,
1657}
1658
1659impl Coverage {
1660 const PATH: &'static str = "tests/coverage";
1661 const SUITE: &'static str = "coverage";
1662 const ALL_MODES: &[CompiletestMode] =
1663 &[CompiletestMode::CoverageMap, CompiletestMode::CoverageRun];
1664}
1665
1666impl Step for Coverage {
1667 type Output = ();
1668 const IS_HOST: bool = false;
1670
1671 fn should_run(mut run: ShouldRun<'_>) -> ShouldRun<'_> {
1672 run = run.suite_path(Self::PATH);
1678 for mode in Self::ALL_MODES {
1679 run = run.alias(mode.as_str());
1680 }
1681 run
1682 }
1683
1684 fn is_default_step(_builder: &Builder<'_>) -> bool {
1685 true
1686 }
1687
1688 fn make_run(run: RunConfig<'_>) {
1689 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1690 let target = run.target;
1691
1692 let mut modes = vec![];
1696
1697 for path in &run.paths {
1700 match path {
1701 PathSet::Set(_) => {
1702 for &mode in Self::ALL_MODES {
1703 if path.assert_single_path().path == Path::new(mode.as_str()) {
1704 modes.push(mode);
1705 break;
1706 }
1707 }
1708 }
1709 PathSet::Suite(_) => {
1710 modes.extend_from_slice(Self::ALL_MODES);
1711 break;
1712 }
1713 }
1714 }
1715
1716 modes.retain(|mode| {
1719 !run.builder.config.skip.iter().any(|skip| skip == Path::new(mode.as_str()))
1720 });
1721
1722 for mode in modes {
1730 run.builder.ensure(Coverage { compiler, target, mode });
1731 }
1732 }
1733
1734 fn run(self, builder: &Builder<'_>) {
1735 let Self { compiler, target, mode } = self;
1736 builder.ensure(Compiletest {
1739 test_compiler: compiler,
1740 target,
1741 mode,
1742 suite: Self::SUITE,
1743 path: Self::PATH,
1744 compare_mode: None,
1745 });
1746 }
1747}
1748
1749test!(CoverageRunRustdoc {
1750 path: "tests/coverage-run-rustdoc",
1751 mode: CompiletestMode::CoverageRun,
1752 suite: "coverage-run-rustdoc",
1753 default: true,
1754 IS_HOST: true,
1755});
1756
1757#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1759pub struct MirOpt {
1760 pub compiler: Compiler,
1761 pub target: TargetSelection,
1762}
1763
1764impl Step for MirOpt {
1765 type Output = ();
1766
1767 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1768 run.suite_path("tests/mir-opt")
1769 }
1770
1771 fn is_default_step(_builder: &Builder<'_>) -> bool {
1772 true
1773 }
1774
1775 fn make_run(run: RunConfig<'_>) {
1776 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1777 run.builder.ensure(MirOpt { compiler, target: run.target });
1778 }
1779
1780 fn run(self, builder: &Builder<'_>) {
1781 let run = |target| {
1782 builder.ensure(Compiletest {
1783 test_compiler: self.compiler,
1784 target,
1785 mode: CompiletestMode::MirOpt,
1786 suite: "mir-opt",
1787 path: "tests/mir-opt",
1788 compare_mode: None,
1789 })
1790 };
1791
1792 run(self.target);
1793
1794 if builder.config.cmd.bless() {
1797 for target in ["aarch64-unknown-linux-gnu", "i686-pc-windows-msvc"] {
1803 run(TargetSelection::from_user(target));
1804 }
1805
1806 for target in ["x86_64-apple-darwin", "i686-unknown-linux-musl"] {
1807 let target = TargetSelection::from_user(target);
1808 let panic_abort_target = builder.ensure(MirOptPanicAbortSyntheticTarget {
1809 compiler: self.compiler,
1810 base: target,
1811 });
1812 run(panic_abort_target);
1813 }
1814 }
1815 }
1816}
1817
1818#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1824struct Compiletest {
1825 test_compiler: Compiler,
1827 target: TargetSelection,
1828 mode: CompiletestMode,
1829 suite: &'static str,
1830 path: &'static str,
1831 compare_mode: Option<&'static str>,
1832}
1833
1834impl Step for Compiletest {
1835 type Output = ();
1836
1837 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1838 run.never()
1839 }
1840
1841 fn run(self, builder: &Builder<'_>) {
1842 if builder.doc_tests == DocTests::Only {
1843 return;
1844 }
1845
1846 if builder.top_stage == 0 && !builder.config.compiletest_allow_stage0 {
1847 eprintln!("\
1848ERROR: `--stage 0` runs compiletest on the stage0 (precompiled) compiler, not your local changes, and will almost always cause tests to fail
1849HELP: to test the compiler or standard library, omit the stage or explicitly use `--stage 1` instead
1850NOTE: 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`."
1851 );
1852 crate::exit!(1);
1853 }
1854
1855 let mut test_compiler = self.test_compiler;
1856 let target = self.target;
1857 let mode = self.mode;
1858 let suite = self.suite;
1859
1860 let suite_path = self.path;
1862
1863 if !builder.config.codegen_tests && mode == CompiletestMode::Codegen {
1865 return;
1866 }
1867
1868 let query_compiler;
1875 let (stage, stage_id) = if suite == "ui-fulldeps" && test_compiler.stage == 1 {
1876 query_compiler = Some(test_compiler);
1879 let build = builder.build.host_target;
1883 test_compiler = builder.compiler(test_compiler.stage - 1, build);
1884 let test_stage = test_compiler.stage + 1;
1885 (test_stage, format!("stage{test_stage}-{build}"))
1886 } else {
1887 query_compiler = None;
1888 let stage = test_compiler.stage;
1889 (stage, format!("stage{stage}-{target}"))
1890 };
1891
1892 if suite.ends_with("fulldeps") {
1893 builder.ensure(compile::Rustc::new(test_compiler, target));
1894 }
1895
1896 if suite == "debuginfo" {
1897 builder.ensure(dist::DebuggerScripts {
1898 sysroot: builder.sysroot(test_compiler).to_path_buf(),
1899 target,
1900 });
1901 }
1902 if mode == CompiletestMode::RunMake {
1903 builder.tool_exe(Tool::RunMakeSupport);
1904 }
1905
1906 if suite == "mir-opt" {
1908 builder.ensure(
1909 compile::Std::new(test_compiler, test_compiler.host).is_for_mir_opt_tests(true),
1910 );
1911 } else {
1912 builder.std(test_compiler, test_compiler.host);
1913 }
1914
1915 let mut cmd = builder.tool_cmd(Tool::Compiletest);
1916
1917 if suite == "mir-opt" {
1918 builder.ensure(compile::Std::new(test_compiler, target).is_for_mir_opt_tests(true));
1919 } else {
1920 builder.std(test_compiler, target);
1921 }
1922
1923 builder.ensure(RemoteCopyLibs { build_compiler: test_compiler, target });
1924
1925 cmd.arg("--stage").arg(stage.to_string());
1929 cmd.arg("--stage-id").arg(stage_id);
1930
1931 cmd.arg("--compile-lib-path").arg(builder.rustc_libdir(test_compiler));
1932 cmd.arg("--run-lib-path").arg(builder.sysroot_target_libdir(test_compiler, target));
1933 cmd.arg("--rustc-path").arg(builder.rustc(test_compiler));
1934 if let Some(query_compiler) = query_compiler {
1935 cmd.arg("--query-rustc-path").arg(builder.rustc(query_compiler));
1936 }
1937
1938 cmd.arg("--minicore-path")
1941 .arg(builder.src.join("tests").join("auxiliary").join("minicore.rs"));
1942
1943 let is_rustdoc = suite == "rustdoc-ui" || suite == "rustdoc-js";
1944
1945 if mode == CompiletestMode::RunMake {
1960 let stage0_rustc_path = builder.compiler(0, test_compiler.host);
1963 cmd.arg("--stage0-rustc-path").arg(builder.rustc(stage0_rustc_path));
1964
1965 if matches!(suite, "run-make-cargo" | "build-std") {
1966 let cargo_path = if test_compiler.stage == 0 {
1967 builder.initial_cargo.clone()
1969 } else {
1970 builder
1971 .ensure(tool::Cargo::from_build_compiler(
1972 builder.compiler(test_compiler.stage - 1, test_compiler.host),
1973 test_compiler.host,
1974 ))
1975 .tool_path
1976 };
1977
1978 cmd.arg("--cargo-path").arg(cargo_path);
1979 }
1980 }
1981
1982 if matches!(
1984 mode,
1985 CompiletestMode::RunMake
1986 | CompiletestMode::RustdocHtml
1987 | CompiletestMode::RustdocJs
1988 | CompiletestMode::RustdocJson
1989 ) || matches!(suite, "rustdoc-ui" | "coverage-run-rustdoc")
1990 {
1991 cmd.arg("--rustdoc-path").arg(builder.rustdoc_for_compiler(test_compiler));
1992 }
1993
1994 if mode == CompiletestMode::RustdocJson {
1995 let json_compiler = builder.compiler(0, builder.host_target);
1997 cmd.arg("--jsondocck-path")
1998 .arg(builder.ensure(tool::JsonDocCk { compiler: json_compiler, target }).tool_path);
1999 cmd.arg("--jsondoclint-path").arg(
2000 builder.ensure(tool::JsonDocLint { compiler: json_compiler, target }).tool_path,
2001 );
2002 }
2003
2004 if matches!(mode, CompiletestMode::CoverageMap | CompiletestMode::CoverageRun) {
2005 let coverage_dump = builder.tool_exe(Tool::CoverageDump);
2006 cmd.arg("--coverage-dump-path").arg(coverage_dump);
2007 }
2008
2009 cmd.arg("--src-root").arg(&builder.src);
2010 cmd.arg("--src-test-suite-root").arg(builder.src.join("tests").join(suite));
2011
2012 cmd.arg("--build-root").arg(&builder.out);
2016 cmd.arg("--build-test-suite-root").arg(testdir(builder, test_compiler.host).join(suite));
2017
2018 let sysroot = if builder.top_stage == 0 {
2023 builder.initial_sysroot.clone()
2024 } else {
2025 builder.sysroot(test_compiler)
2026 };
2027
2028 cmd.arg("--sysroot-base").arg(sysroot);
2029
2030 cmd.arg("--suite").arg(suite);
2031 cmd.arg("--mode").arg(mode.as_str());
2032 cmd.arg("--target").arg(target.rustc_target_arg());
2033 cmd.arg("--host").arg(&*test_compiler.host.triple);
2034 cmd.arg("--llvm-filecheck").arg(builder.llvm_filecheck(builder.config.host_target));
2035
2036 if let Some(codegen_backend) = builder.config.cmd.test_codegen_backend() {
2037 if !builder
2038 .config
2039 .enabled_codegen_backends(test_compiler.host)
2040 .contains(codegen_backend)
2041 {
2042 eprintln!(
2043 "\
2044ERROR: No configured backend named `{name}`
2045HELP: You can add it into `bootstrap.toml` in `rust.codegen-backends = [{name:?}]`",
2046 name = codegen_backend.name(),
2047 );
2048 crate::exit!(1);
2049 }
2050
2051 if let CodegenBackendKind::Gcc = codegen_backend
2052 && builder.config.rustc_debug_assertions
2053 {
2054 eprintln!(
2055 r#"WARNING: Running tests with the GCC codegen backend while rustc debug assertions are enabled. This might lead to test failures.
2056Please disable assertions with `rust.debug-assertions = false`.
2057 "#
2058 );
2059 }
2060
2061 cmd.arg("--override-codegen-backend").arg(codegen_backend.name());
2064 cmd.arg("--default-codegen-backend").arg(codegen_backend.name());
2067 } else {
2068 cmd.arg("--default-codegen-backend")
2071 .arg(builder.config.default_codegen_backend(test_compiler.host).name());
2072 }
2073 if builder.config.cmd.bypass_ignore_backends() {
2074 cmd.arg("--bypass-ignore-backends");
2075 }
2076
2077 if builder.build.config.llvm_enzyme {
2078 cmd.arg("--has-enzyme");
2079 }
2080
2081 if builder.build.config.llvm_offload {
2082 cmd.arg("--has-offload");
2083 }
2084
2085 if builder.config.cmd.bless() {
2086 cmd.arg("--bless");
2087 }
2088
2089 if builder.config.cmd.force_rerun() {
2090 cmd.arg("--force-rerun");
2091 }
2092
2093 if builder.config.cmd.no_capture() {
2094 cmd.arg("--no-capture");
2095 }
2096
2097 let compare_mode =
2098 builder.config.cmd.compare_mode().or_else(|| {
2099 if builder.config.test_compare_mode { self.compare_mode } else { None }
2100 });
2101
2102 if let Some(ref pass) = builder.config.cmd.pass() {
2103 cmd.arg("--pass");
2104 cmd.arg(pass);
2105 }
2106
2107 if let Some(ref run) = builder.config.cmd.run() {
2108 cmd.arg("--run");
2109 cmd.arg(run);
2110 }
2111
2112 if let Some(ref nodejs) = builder.config.nodejs {
2113 cmd.arg("--nodejs").arg(nodejs);
2114 } else if mode == CompiletestMode::RustdocJs {
2115 panic!("need nodejs to run rustdoc-js suite");
2116 }
2117 if builder.config.rust_optimize_tests {
2118 cmd.arg("--optimize-tests");
2119 }
2120 if builder.config.rust_randomize_layout {
2121 cmd.arg("--rust-randomized-layout");
2122 }
2123 if builder.config.cmd.only_modified() {
2124 cmd.arg("--only-modified");
2125 }
2126 if let Some(compiletest_diff_tool) = &builder.config.compiletest_diff_tool {
2127 cmd.arg("--compiletest-diff-tool").arg(compiletest_diff_tool);
2128 }
2129
2130 let mut flags = if is_rustdoc { Vec::new() } else { vec!["-Crpath".to_string()] };
2131 flags.push(format!(
2132 "-Cdebuginfo={}",
2133 if mode == CompiletestMode::Codegen {
2134 if builder.config.rust_debuginfo_level_tests
2137 != crate::core::config::DebuginfoLevel::None
2138 {
2139 println!(
2140 "NOTE: ignoring `rust.debuginfo-level-tests={}` for codegen tests",
2141 builder.config.rust_debuginfo_level_tests
2142 );
2143 }
2144 crate::core::config::DebuginfoLevel::None
2145 } else {
2146 builder.config.rust_debuginfo_level_tests
2147 }
2148 ));
2149 flags.extend(builder.config.cmd.compiletest_rustc_args().iter().map(|s| s.to_string()));
2150
2151 if suite != "mir-opt" {
2152 if let Some(linker) = builder.linker(target) {
2153 cmd.arg("--target-linker").arg(linker);
2154 }
2155 if let Some(linker) = builder.linker(test_compiler.host) {
2156 cmd.arg("--host-linker").arg(linker);
2157 }
2158 }
2159
2160 if suite == "ui-fulldeps" && target.ends_with("darwin") {
2162 flags.push("-Alinker_messages".into());
2163 }
2164
2165 let mut hostflags = flags.clone();
2166 hostflags.extend(linker_flags(builder, test_compiler.host, LldThreads::No));
2167
2168 let mut targetflags = flags;
2169
2170 if suite == "ui" || suite == "incremental" {
2172 builder.ensure(TestHelpers { target: test_compiler.host });
2173 builder.ensure(TestHelpers { target });
2174 hostflags.push(format!(
2175 "-Lnative={}",
2176 builder.test_helpers_out(test_compiler.host).display()
2177 ));
2178 targetflags.push(format!("-Lnative={}", builder.test_helpers_out(target).display()));
2179 }
2180
2181 for flag in hostflags {
2182 cmd.arg("--host-rustcflags").arg(flag);
2183 }
2184 for flag in targetflags {
2185 cmd.arg("--target-rustcflags").arg(flag);
2186 }
2187 if target.is_synthetic() {
2188 cmd.arg("--target-rustcflags").arg("-Zunstable-options");
2189 }
2190
2191 cmd.arg("--python").arg(
2192 builder.config.python.as_ref().expect("python is required for running rustdoc tests"),
2193 );
2194
2195 let android = android::discover_android(builder, target);
2197 if let Some(android::Android { adb_path, adb_test_dir, android_cross_path }) = &android {
2198 cmd.arg("--adb-path").arg(adb_path);
2199 cmd.arg("--adb-test-dir").arg(adb_test_dir);
2200 cmd.arg("--android-cross-path").arg(android_cross_path);
2201 }
2202
2203 if mode == CompiletestMode::Debuginfo {
2204 if let Some(debuggers::Cdb { cdb }) = debuggers::discover_cdb(target) {
2205 cmd.arg("--cdb").arg(cdb);
2206 }
2207
2208 if let Some(debuggers::Gdb { gdb }) = debuggers::discover_gdb(builder, android.as_ref())
2209 {
2210 cmd.arg("--gdb").arg(gdb.as_ref());
2211 }
2212
2213 if let Some(debuggers::Lldb { lldb_exe, lldb_version }) =
2214 debuggers::discover_lldb(builder)
2215 {
2216 cmd.arg("--lldb").arg(lldb_exe);
2217 cmd.arg("--lldb-version").arg(lldb_version);
2218 }
2219 }
2220
2221 if helpers::forcing_clang_based_tests() {
2222 let clang_exe = builder.llvm_out(target).join("bin").join("clang");
2223 cmd.arg("--run-clang-based-tests-with").arg(clang_exe);
2224 }
2225
2226 for exclude in &builder.config.skip {
2227 cmd.arg("--skip");
2228 cmd.arg(exclude);
2229 }
2230
2231 let mut paths = match &builder.config.cmd {
2233 Subcommand::Test { .. } => &builder.config.paths[..],
2234 _ => &[],
2235 };
2236
2237 let mut paths_v;
2240 if mode == CompiletestMode::RustdocJs {
2241 paths_v = paths.to_vec();
2242 for p in &mut paths_v {
2243 if let Some(ext) = p.extension()
2244 && ext == "js"
2245 {
2246 p.set_extension("rs");
2247 }
2248 }
2249 paths = &paths_v;
2250 }
2251 let mut test_args: Vec<&str> = paths
2253 .iter()
2254 .filter_map(|p| helpers::is_valid_test_suite_arg(p, suite_path, builder))
2255 .collect();
2256
2257 test_args.append(&mut builder.config.test_args());
2258
2259 if cfg!(windows) {
2262 let test_args_win: Vec<String> =
2263 test_args.iter().map(|s| s.replace('/', "\\")).collect();
2264 cmd.args(&test_args_win);
2265 } else {
2266 cmd.args(&test_args);
2267 }
2268
2269 if builder.is_verbose() {
2270 cmd.arg("--verbose");
2271 }
2272
2273 if builder.config.rustc_debug_assertions {
2274 cmd.arg("--with-rustc-debug-assertions");
2275 }
2276
2277 if builder.config.std_debug_assertions {
2278 cmd.arg("--with-std-debug-assertions");
2279 }
2280
2281 if builder.config.rust_remap_debuginfo {
2282 cmd.arg("--with-std-remap-debuginfo");
2283 }
2284
2285 cmd.arg("--jobs").arg(builder.jobs().to_string());
2286
2287 let mut llvm_components_passed = false;
2288 let mut copts_passed = false;
2289 if builder.config.llvm_enabled(test_compiler.host) {
2290 let llvm::LlvmResult { host_llvm_config, .. } =
2291 builder.ensure(llvm::Llvm { target: builder.config.host_target });
2292 if !builder.config.dry_run() {
2293 let llvm_version = get_llvm_version(builder, &host_llvm_config);
2294 let llvm_components = command(&host_llvm_config)
2295 .cached()
2296 .arg("--components")
2297 .run_capture_stdout(builder)
2298 .stdout();
2299 cmd.arg("--llvm-version")
2301 .arg(llvm_version.trim())
2302 .arg("--llvm-components")
2303 .arg(llvm_components.trim());
2304 llvm_components_passed = true;
2305 }
2306 if !builder.config.is_rust_llvm(target) {
2307 cmd.arg("--system-llvm");
2308 }
2309
2310 if !builder.config.dry_run() && suite.ends_with("fulldeps") {
2315 let llvm_libdir = command(&host_llvm_config)
2316 .cached()
2317 .arg("--libdir")
2318 .run_capture_stdout(builder)
2319 .stdout();
2320 let link_llvm = if target.is_msvc() {
2321 format!("-Clink-arg=-LIBPATH:{llvm_libdir}")
2322 } else {
2323 format!("-Clink-arg=-L{llvm_libdir}")
2324 };
2325 cmd.arg("--host-rustcflags").arg(link_llvm);
2326 }
2327
2328 if !builder.config.dry_run()
2329 && matches!(mode, CompiletestMode::RunMake | CompiletestMode::CoverageRun)
2330 {
2331 let llvm_bin_path = host_llvm_config
2336 .parent()
2337 .expect("Expected llvm-config to be contained in directory");
2338 assert!(llvm_bin_path.is_dir());
2339 cmd.arg("--llvm-bin-dir").arg(llvm_bin_path);
2340 }
2341
2342 if !builder.config.dry_run() && mode == CompiletestMode::RunMake {
2343 if builder.config.lld_enabled {
2345 let lld_install_root =
2346 builder.ensure(llvm::Lld { target: builder.config.host_target });
2347
2348 let lld_bin_path = lld_install_root.join("bin");
2349
2350 let old_path = env::var_os("PATH").unwrap_or_default();
2351 let new_path = env::join_paths(
2352 std::iter::once(lld_bin_path).chain(env::split_paths(&old_path)),
2353 )
2354 .expect("Could not add LLD bin path to PATH");
2355 cmd.env("PATH", new_path);
2356 }
2357 }
2358 }
2359
2360 if !builder.config.dry_run() && mode == CompiletestMode::RunMake {
2363 let mut cflags = builder.cc_handled_clags(target, CLang::C);
2364 cflags.extend(builder.cc_unhandled_cflags(target, GitRepo::Rustc, CLang::C));
2365 let mut cxxflags = builder.cc_handled_clags(target, CLang::Cxx);
2366 cxxflags.extend(builder.cc_unhandled_cflags(target, GitRepo::Rustc, CLang::Cxx));
2367 cmd.arg("--cc")
2368 .arg(builder.cc(target))
2369 .arg("--cxx")
2370 .arg(builder.cxx(target).unwrap())
2371 .arg("--cflags")
2372 .arg(cflags.join(" "))
2373 .arg("--cxxflags")
2374 .arg(cxxflags.join(" "));
2375 copts_passed = true;
2376 if let Some(ar) = builder.ar(target) {
2377 cmd.arg("--ar").arg(ar);
2378 }
2379 }
2380
2381 if !llvm_components_passed {
2382 cmd.arg("--llvm-components").arg("");
2383 }
2384 if !copts_passed {
2385 cmd.arg("--cc")
2386 .arg("")
2387 .arg("--cxx")
2388 .arg("")
2389 .arg("--cflags")
2390 .arg("")
2391 .arg("--cxxflags")
2392 .arg("");
2393 }
2394
2395 if builder.remote_tested(target) {
2396 cmd.arg("--remote-test-client").arg(builder.tool_exe(Tool::RemoteTestClient));
2397 } else if let Some(tool) = builder.runner(target) {
2398 cmd.arg("--runner").arg(tool);
2399 }
2400
2401 if suite != "mir-opt" {
2402 if !builder.config.dry_run() && target.is_msvc() {
2408 for (k, v) in builder.cc[&target].env() {
2409 if k != "PATH" {
2410 cmd.env(k, v);
2411 }
2412 }
2413 }
2414 }
2415
2416 if !builder.config.dry_run()
2418 && target.contains("msvc")
2419 && builder.config.sanitizers_enabled(target)
2420 {
2421 cmd.env("ASAN_WIN_CONTINUE_ON_INTERCEPTION_FAILURE", "1");
2424 let asan_runtime_path = builder.cc[&target].path().parent().unwrap().to_path_buf();
2426 let old_path = cmd
2427 .get_envs()
2428 .find_map(|(k, v)| (k == "PATH").then_some(v))
2429 .flatten()
2430 .map_or_else(|| env::var_os("PATH").unwrap_or_default(), |v| v.to_owned());
2431 let new_path = env::join_paths(
2432 env::split_paths(&old_path).chain(std::iter::once(asan_runtime_path)),
2433 )
2434 .expect("Could not add ASAN runtime path to PATH");
2435 cmd.env("PATH", new_path);
2436 }
2437
2438 cmd.env_remove("CARGO");
2441
2442 cmd.env("RUSTC_BOOTSTRAP", "1");
2443 cmd.env("RUSTC_FORCE_RUSTC_VERSION", "compiletest");
2446 cmd.env("DOC_RUST_LANG_ORG_CHANNEL", builder.doc_rust_lang_org_channel());
2447 builder.add_rust_test_threads(&mut cmd);
2448
2449 if builder.config.sanitizers_enabled(target) {
2450 cmd.env("RUSTC_SANITIZER_SUPPORT", "1");
2451 }
2452
2453 if builder.config.profiler_enabled(target) {
2454 cmd.arg("--profiler-runtime");
2455 }
2456
2457 cmd.env("RUST_TEST_TMPDIR", builder.tempdir());
2458
2459 if builder.config.cmd.rustfix_coverage() {
2460 cmd.arg("--rustfix-coverage");
2461 }
2462
2463 cmd.arg("--channel").arg(&builder.config.channel);
2464
2465 if !builder.config.omit_git_hash {
2466 cmd.arg("--git-hash");
2467 }
2468
2469 let git_config = builder.config.git_config();
2470 cmd.arg("--nightly-branch").arg(git_config.nightly_branch);
2471 cmd.arg("--git-merge-commit-email").arg(git_config.git_merge_commit_email);
2472
2473 #[cfg(feature = "build-metrics")]
2474 builder.metrics.begin_test_suite(
2475 build_helper::metrics::TestSuiteMetadata::Compiletest {
2476 suite: suite.into(),
2477 mode: mode.to_string(),
2478 compare_mode: None,
2479 target: self.target.triple.to_string(),
2480 host: self.test_compiler.host.triple.to_string(),
2481 stage: self.test_compiler.stage,
2482 },
2483 builder,
2484 );
2485
2486 let _group = builder.msg_test(
2487 format!("with compiletest suite={suite} mode={mode}"),
2488 target,
2489 test_compiler.stage,
2490 );
2491 try_run_tests(builder, &mut cmd, false);
2492
2493 if let Some(compare_mode) = compare_mode {
2494 cmd.arg("--compare-mode").arg(compare_mode);
2495
2496 #[cfg(feature = "build-metrics")]
2497 builder.metrics.begin_test_suite(
2498 build_helper::metrics::TestSuiteMetadata::Compiletest {
2499 suite: suite.into(),
2500 mode: mode.to_string(),
2501 compare_mode: Some(compare_mode.into()),
2502 target: self.target.triple.to_string(),
2503 host: self.test_compiler.host.triple.to_string(),
2504 stage: self.test_compiler.stage,
2505 },
2506 builder,
2507 );
2508
2509 builder.info(&format!(
2510 "Check compiletest suite={} mode={} compare_mode={} ({} -> {})",
2511 suite, mode, compare_mode, &test_compiler.host, target
2512 ));
2513 let _time = helpers::timeit(builder);
2514 try_run_tests(builder, &mut cmd, false);
2515 }
2516 }
2517
2518 fn metadata(&self) -> Option<StepMetadata> {
2519 Some(
2520 StepMetadata::test(&format!("compiletest-{}", self.suite), self.target)
2521 .stage(self.test_compiler.stage),
2522 )
2523 }
2524}
2525
2526#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2528struct BookTest {
2529 test_compiler: Compiler,
2530 path: PathBuf,
2531 name: &'static str,
2532 is_ext_doc: bool,
2533 dependencies: Vec<&'static str>,
2534}
2535
2536impl Step for BookTest {
2537 type Output = ();
2538 const IS_HOST: bool = true;
2539
2540 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2541 run.never()
2542 }
2543
2544 fn run(self, builder: &Builder<'_>) {
2545 if self.is_ext_doc {
2555 self.run_ext_doc(builder);
2556 } else {
2557 self.run_local_doc(builder);
2558 }
2559 }
2560}
2561
2562impl BookTest {
2563 fn run_ext_doc(self, builder: &Builder<'_>) {
2566 let test_compiler = self.test_compiler;
2567
2568 builder.std(test_compiler, test_compiler.host);
2569
2570 let mut rustdoc_path = builder.rustdoc_for_compiler(test_compiler);
2573 rustdoc_path.pop();
2574 let old_path = env::var_os("PATH").unwrap_or_default();
2575 let new_path = env::join_paths(iter::once(rustdoc_path).chain(env::split_paths(&old_path)))
2576 .expect("could not add rustdoc to PATH");
2577
2578 let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook);
2579 let path = builder.src.join(&self.path);
2580 rustbook_cmd.env("RUSTC_BOOTSTRAP", "1");
2582 rustbook_cmd.env("PATH", new_path).arg("test").arg(path);
2583
2584 let libs = if !self.dependencies.is_empty() {
2589 let mut lib_paths = vec![];
2590 for dep in self.dependencies {
2591 let mode = Mode::ToolRustcPrivate;
2592 let target = builder.config.host_target;
2593 let cargo = tool::prepare_tool_cargo(
2594 builder,
2595 test_compiler,
2596 mode,
2597 target,
2598 Kind::Build,
2599 dep,
2600 SourceType::Submodule,
2601 &[],
2602 );
2603
2604 let stamp = BuildStamp::new(&builder.cargo_out(test_compiler, mode, target))
2605 .with_prefix(PathBuf::from(dep).file_name().and_then(|v| v.to_str()).unwrap());
2606
2607 let output_paths =
2608 run_cargo(builder, cargo, vec![], &stamp, vec![], ArtifactKeepMode::OnlyRlib);
2609 let directories = output_paths
2610 .into_iter()
2611 .filter_map(|p| p.parent().map(ToOwned::to_owned))
2612 .fold(HashSet::new(), |mut set, dir| {
2613 set.insert(dir);
2614 set
2615 });
2616
2617 lib_paths.extend(directories);
2618 }
2619 lib_paths
2620 } else {
2621 vec![]
2622 };
2623
2624 if !libs.is_empty() {
2625 let paths = libs
2626 .into_iter()
2627 .map(|path| path.into_os_string())
2628 .collect::<Vec<OsString>>()
2629 .join(OsStr::new(","));
2630 rustbook_cmd.args([OsString::from("--library-path"), paths]);
2631 }
2632
2633 builder.add_rust_test_threads(&mut rustbook_cmd);
2634 let _guard = builder.msg_test(
2635 format_args!("mdbook {}", self.path.display()),
2636 test_compiler.host,
2637 test_compiler.stage,
2638 );
2639 let _time = helpers::timeit(builder);
2640 let toolstate = if rustbook_cmd.delay_failure().run(builder) {
2641 ToolState::TestPass
2642 } else {
2643 ToolState::TestFail
2644 };
2645 builder.save_toolstate(self.name, toolstate);
2646 }
2647
2648 fn run_local_doc(self, builder: &Builder<'_>) {
2650 let test_compiler = self.test_compiler;
2651 let host = self.test_compiler.host;
2652
2653 builder.std(test_compiler, host);
2654
2655 let _guard = builder.msg_test(
2656 format!("book {}", self.name),
2657 test_compiler.host,
2658 test_compiler.stage,
2659 );
2660
2661 let mut stack = vec![builder.src.join(self.path)];
2664 let _time = helpers::timeit(builder);
2665 let mut files = Vec::new();
2666 while let Some(p) = stack.pop() {
2667 if p.is_dir() {
2668 stack.extend(t!(p.read_dir()).map(|p| t!(p).path()));
2669 continue;
2670 }
2671
2672 if p.extension().and_then(|s| s.to_str()) != Some("md") {
2673 continue;
2674 }
2675
2676 files.push(p);
2677 }
2678
2679 files.sort();
2680
2681 for file in files {
2682 markdown_test(builder, test_compiler, &file);
2683 }
2684 }
2685}
2686
2687macro_rules! test_book {
2688 ($(
2689 $name:ident, $path:expr, $book_name:expr,
2690 default=$default:expr
2691 $(,submodules = $submodules:expr)?
2692 $(,dependencies=$dependencies:expr)?
2693 ;
2694 )+) => {
2695 $(
2696 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
2697 pub struct $name {
2698 test_compiler: Compiler,
2699 }
2700
2701 impl Step for $name {
2702 type Output = ();
2703 const IS_HOST: bool = true;
2704
2705 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2706 run.path($path)
2707 }
2708
2709 fn is_default_step(_builder: &Builder<'_>) -> bool {
2710 const { $default }
2711 }
2712
2713 fn make_run(run: RunConfig<'_>) {
2714 run.builder.ensure($name {
2715 test_compiler: run.builder.compiler(run.builder.top_stage, run.target),
2716 });
2717 }
2718
2719 fn run(self, builder: &Builder<'_>) {
2720 $(
2721 for submodule in $submodules {
2722 builder.require_submodule(submodule, None);
2723 }
2724 )*
2725
2726 let dependencies = vec![];
2727 $(
2728 let mut dependencies = dependencies;
2729 for dep in $dependencies {
2730 dependencies.push(dep);
2731 }
2732 )?
2733
2734 builder.ensure(BookTest {
2735 test_compiler: self.test_compiler,
2736 path: PathBuf::from($path),
2737 name: $book_name,
2738 is_ext_doc: !$default,
2739 dependencies,
2740 });
2741 }
2742 }
2743 )+
2744 }
2745}
2746
2747test_book!(
2748 Nomicon, "src/doc/nomicon", "nomicon", default=false, submodules=["src/doc/nomicon"];
2749 Reference, "src/doc/reference", "reference", default=false, submodules=["src/doc/reference"];
2750 RustdocBook, "src/doc/rustdoc", "rustdoc", default=true;
2751 RustcBook, "src/doc/rustc", "rustc", default=true;
2752 RustByExample, "src/doc/rust-by-example", "rust-by-example", default=false, submodules=["src/doc/rust-by-example"];
2753 EmbeddedBook, "src/doc/embedded-book", "embedded-book", default=false, submodules=["src/doc/embedded-book"];
2754 TheBook, "src/doc/book", "book", default=false, submodules=["src/doc/book"], dependencies=["src/doc/book/packages/trpl"];
2755 UnstableBook, "src/doc/unstable-book", "unstable-book", default=true;
2756 EditionGuide, "src/doc/edition-guide", "edition-guide", default=false, submodules=["src/doc/edition-guide"];
2757);
2758
2759#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2760pub struct ErrorIndex {
2761 compilers: RustcPrivateCompilers,
2762}
2763
2764impl Step for ErrorIndex {
2765 type Output = ();
2766 const IS_HOST: bool = true;
2767
2768 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2769 run.path("src/tools/error_index_generator").alias("error-index")
2772 }
2773
2774 fn is_default_step(_builder: &Builder<'_>) -> bool {
2775 true
2776 }
2777
2778 fn make_run(run: RunConfig<'_>) {
2779 let compilers = RustcPrivateCompilers::new(
2783 run.builder,
2784 run.builder.top_stage,
2785 run.builder.config.host_target,
2786 );
2787 run.builder.ensure(ErrorIndex { compilers });
2788 }
2789
2790 fn run(self, builder: &Builder<'_>) {
2797 let target_compiler = self.compilers.target_compiler();
2799
2800 let dir = testdir(builder, target_compiler.host);
2801 t!(fs::create_dir_all(&dir));
2802 let output = dir.join("error-index.md");
2803
2804 let mut tool = tool::ErrorIndex::command(builder, self.compilers);
2805 tool.arg("markdown").arg(&output);
2806
2807 let guard = builder.msg_test("error-index", target_compiler.host, target_compiler.stage);
2808 let _time = helpers::timeit(builder);
2809 tool.run_capture(builder);
2810 drop(guard);
2811 builder.std(target_compiler, target_compiler.host);
2814 markdown_test(builder, target_compiler, &output);
2815 }
2816}
2817
2818fn markdown_test(builder: &Builder<'_>, compiler: Compiler, markdown: &Path) -> bool {
2819 if let Ok(contents) = fs::read_to_string(markdown)
2820 && !contents.contains("```")
2821 {
2822 return true;
2823 }
2824
2825 builder.do_if_verbose(|| println!("doc tests for: {}", markdown.display()));
2826 let mut cmd = builder.rustdoc_cmd(compiler);
2827 builder.add_rust_test_threads(&mut cmd);
2828 cmd.arg("-Z");
2830 cmd.arg("unstable-options");
2831 cmd.arg("--test");
2832 cmd.arg(markdown);
2833 cmd.env("RUSTC_BOOTSTRAP", "1");
2834
2835 let test_args = builder.config.test_args().join(" ");
2836 cmd.arg("--test-args").arg(test_args);
2837
2838 cmd = cmd.delay_failure();
2839 if !builder.config.verbose_tests {
2840 cmd.run_capture(builder).is_success()
2841 } else {
2842 cmd.run(builder)
2843 }
2844}
2845
2846#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2851pub struct CrateLibrustc {
2852 build_compiler: Compiler,
2854 target: TargetSelection,
2855 crates: Vec<String>,
2856}
2857
2858impl Step for CrateLibrustc {
2859 type Output = ();
2860 const IS_HOST: bool = true;
2861
2862 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2863 run.crate_or_deps("rustc-main").path("compiler")
2864 }
2865
2866 fn is_default_step(_builder: &Builder<'_>) -> bool {
2867 true
2868 }
2869
2870 fn make_run(run: RunConfig<'_>) {
2871 let builder = run.builder;
2872 let host = run.build_triple();
2873 let build_compiler = builder.compiler(builder.top_stage - 1, host);
2874 let crates = run.make_run_crates(Alias::Compiler);
2875
2876 builder.ensure(CrateLibrustc { build_compiler, target: run.target, crates });
2877 }
2878
2879 fn run(self, builder: &Builder<'_>) {
2880 builder.std(self.build_compiler, self.target);
2881
2882 builder.ensure(Crate {
2884 build_compiler: self.build_compiler,
2885 target: self.target,
2886 mode: Mode::Rustc,
2887 crates: self.crates,
2888 });
2889 }
2890
2891 fn metadata(&self) -> Option<StepMetadata> {
2892 Some(StepMetadata::test("CrateLibrustc", self.target).built_by(self.build_compiler))
2893 }
2894}
2895
2896fn run_cargo_test<'a>(
2900 cargo: builder::Cargo,
2901 libtest_args: &[&str],
2902 crates: &[String],
2903 description: impl Into<Option<&'a str>>,
2904 target: TargetSelection,
2905 builder: &Builder<'_>,
2906) -> bool {
2907 let compiler = cargo.compiler();
2908 let stage = match cargo.mode() {
2909 Mode::Std => compiler.stage,
2910 _ => compiler.stage + 1,
2911 };
2912
2913 let mut cargo = prepare_cargo_test(cargo, libtest_args, crates, target, builder);
2914 let _time = helpers::timeit(builder);
2915
2916 let _group = description.into().and_then(|what| builder.msg_test(what, target, stage));
2917
2918 #[cfg(feature = "build-metrics")]
2919 builder.metrics.begin_test_suite(
2920 build_helper::metrics::TestSuiteMetadata::CargoPackage {
2921 crates: crates.iter().map(|c| c.to_string()).collect(),
2922 target: target.triple.to_string(),
2923 host: compiler.host.triple.to_string(),
2924 stage: compiler.stage,
2925 },
2926 builder,
2927 );
2928 add_flags_and_try_run_tests(builder, &mut cargo)
2929}
2930
2931fn prepare_cargo_test(
2933 cargo: builder::Cargo,
2934 libtest_args: &[&str],
2935 crates: &[String],
2936 target: TargetSelection,
2937 builder: &Builder<'_>,
2938) -> BootstrapCommand {
2939 let compiler = cargo.compiler();
2940 let mut cargo: BootstrapCommand = cargo.into();
2941
2942 if builder.config.cmd.bless() && !cargo.get_envs().any(|v| v.0 == "RUSTC_BLESS") {
2946 cargo.env("RUSTC_BLESS", "Gesundheit");
2947 }
2948
2949 if builder.kind == Kind::Test && !builder.fail_fast {
2953 cargo.arg("--no-fail-fast");
2954 }
2955
2956 if builder.config.json_output {
2957 cargo.arg("--message-format=json");
2958 }
2959
2960 match builder.doc_tests {
2961 DocTests::Only => {
2962 cargo.arg("--doc");
2963 }
2964 DocTests::No => {
2965 cargo.args(["--bins", "--examples", "--tests", "--benches"]);
2966 }
2967 DocTests::Yes => {}
2968 }
2969
2970 for krate in crates {
2971 cargo.arg("-p").arg(krate);
2972 }
2973
2974 cargo.arg("--").args(builder.config.test_args()).args(libtest_args);
2975 if !builder.config.verbose_tests {
2976 cargo.arg("--quiet");
2977 }
2978
2979 if builder.kind != Kind::Miri {
2988 let mut dylib_paths = builder.rustc_lib_paths(compiler);
2989 dylib_paths.push(builder.sysroot_target_libdir(compiler, target));
2990 helpers::add_dylib_path(dylib_paths, &mut cargo);
2991 }
2992
2993 if builder.remote_tested(target) {
2994 cargo.env(
2995 format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)),
2996 format!("{} run 0", builder.tool_exe(Tool::RemoteTestClient).display()),
2997 );
2998 } else if let Some(tool) = builder.runner(target) {
2999 cargo.env(format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)), tool);
3000 }
3001
3002 cargo
3003}
3004
3005#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3013pub struct Crate {
3014 build_compiler: Compiler,
3016 target: TargetSelection,
3017 mode: Mode,
3018 crates: Vec<String>,
3019}
3020
3021impl Step for Crate {
3022 type Output = ();
3023
3024 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3025 run.crate_or_deps("sysroot").crate_or_deps("coretests").crate_or_deps("alloctests")
3026 }
3027
3028 fn is_default_step(_builder: &Builder<'_>) -> bool {
3029 true
3030 }
3031
3032 fn make_run(run: RunConfig<'_>) {
3033 let builder = run.builder;
3034 let host = run.build_triple();
3035 let build_compiler = builder.compiler(builder.top_stage, host);
3036 let crates = run
3037 .paths
3038 .iter()
3039 .map(|p| builder.crate_paths[&p.assert_single_path().path].clone())
3040 .collect();
3041
3042 builder.ensure(Crate { build_compiler, target: run.target, mode: Mode::Std, crates });
3043 }
3044
3045 fn run(self, builder: &Builder<'_>) {
3054 let build_compiler = self.build_compiler;
3055 let target = self.target;
3056 let mode = self.mode;
3057
3058 builder.ensure(Std::new(build_compiler, build_compiler.host).force_recompile(true));
3061
3062 let mut cargo = if builder.kind == Kind::Miri {
3063 if builder.top_stage == 0 {
3064 eprintln!("ERROR: `x.py miri` requires stage 1 or higher");
3065 std::process::exit(1);
3066 }
3067
3068 let mut cargo = builder::Cargo::new(
3071 builder,
3072 build_compiler,
3073 mode,
3074 SourceType::InTree,
3075 target,
3076 Kind::MiriTest,
3077 );
3078 cargo.env("MIRI_REPLACE_LIBRS_IF_NOT_TEST", "1");
3090 cargo.rustflag("-Zforce-unstable-if-unmarked");
3094 cargo
3095 } else {
3096 if !builder.config.is_host_target(target) {
3098 builder.ensure(compile::Std::new(build_compiler, target).force_recompile(true));
3099 builder.ensure(RemoteCopyLibs { build_compiler, target });
3100 }
3101
3102 builder::Cargo::new(
3104 builder,
3105 build_compiler,
3106 mode,
3107 SourceType::InTree,
3108 target,
3109 builder.kind,
3110 )
3111 };
3112
3113 match mode {
3114 Mode::Std => {
3115 if builder.kind == Kind::Miri {
3116 cargo
3122 .arg("--manifest-path")
3123 .arg(builder.src.join("library/sysroot/Cargo.toml"));
3124 } else {
3125 compile::std_cargo(builder, target, &mut cargo, &[]);
3126 }
3127 }
3128 Mode::Rustc => {
3129 compile::rustc_cargo(builder, &mut cargo, target, &build_compiler, &self.crates);
3130 }
3131 _ => panic!("can only test libraries"),
3132 };
3133
3134 let mut crates = self.crates.clone();
3135 if crates.iter().any(|crate_| crate_ == "core") {
3140 crates.push("coretests".to_owned());
3141 }
3142 if crates.iter().any(|crate_| crate_ == "alloc") {
3143 crates.push("alloctests".to_owned());
3144 }
3145
3146 run_cargo_test(cargo, &[], &crates, &*crate_description(&self.crates), target, builder);
3147 }
3148}
3149
3150#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3153pub struct CrateRustdoc {
3154 host: TargetSelection,
3155}
3156
3157impl Step for CrateRustdoc {
3158 type Output = ();
3159 const IS_HOST: bool = true;
3160
3161 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3162 run.path("src/librustdoc").path("src/tools/rustdoc")
3163 }
3164
3165 fn is_default_step(_builder: &Builder<'_>) -> bool {
3166 true
3167 }
3168
3169 fn make_run(run: RunConfig<'_>) {
3170 let builder = run.builder;
3171
3172 builder.ensure(CrateRustdoc { host: run.target });
3173 }
3174
3175 fn run(self, builder: &Builder<'_>) {
3176 let target = self.host;
3177
3178 let compiler = if builder.download_rustc() {
3179 builder.compiler(builder.top_stage, target)
3180 } else {
3181 builder.compiler_for(builder.top_stage, target, target)
3186 };
3187 builder.std(compiler, target);
3192 builder.ensure(compile::Rustc::new(compiler, target));
3193
3194 let mut cargo = tool::prepare_tool_cargo(
3195 builder,
3196 compiler,
3197 Mode::ToolRustcPrivate,
3198 target,
3199 builder.kind,
3200 "src/tools/rustdoc",
3201 SourceType::InTree,
3202 &[],
3203 );
3204 if self.host.contains("musl") {
3205 cargo.arg("'-Ctarget-feature=-crt-static'");
3206 }
3207
3208 let libdir = if builder.download_rustc() {
3235 builder.rustc_libdir(compiler)
3236 } else {
3237 builder.sysroot_target_libdir(compiler, target).to_path_buf()
3238 };
3239 let mut dylib_path = dylib_path();
3240 dylib_path.insert(0, PathBuf::from(&*libdir));
3241 cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());
3242
3243 run_cargo_test(cargo, &[], &["rustdoc:0.0.0".to_string()], "rustdoc", target, builder);
3244 }
3245}
3246
3247#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3248pub struct CrateRustdocJsonTypes {
3249 build_compiler: Compiler,
3250 target: TargetSelection,
3251}
3252
3253impl Step for CrateRustdocJsonTypes {
3254 type Output = ();
3255 const IS_HOST: bool = true;
3256
3257 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3258 run.path("src/rustdoc-json-types")
3259 }
3260
3261 fn is_default_step(_builder: &Builder<'_>) -> bool {
3262 true
3263 }
3264
3265 fn make_run(run: RunConfig<'_>) {
3266 let builder = run.builder;
3267
3268 builder.ensure(CrateRustdocJsonTypes {
3269 build_compiler: get_tool_target_compiler(
3270 builder,
3271 ToolTargetBuildMode::Build(run.target),
3272 ),
3273 target: run.target,
3274 });
3275 }
3276
3277 fn run(self, builder: &Builder<'_>) {
3278 let target = self.target;
3279
3280 let cargo = tool::prepare_tool_cargo(
3281 builder,
3282 self.build_compiler,
3283 Mode::ToolTarget,
3284 target,
3285 builder.kind,
3286 "src/rustdoc-json-types",
3287 SourceType::InTree,
3288 &[],
3289 );
3290
3291 let libtest_args = if target.contains("musl") {
3293 ["'-Ctarget-feature=-crt-static'"].as_slice()
3294 } else {
3295 &[]
3296 };
3297
3298 run_cargo_test(
3299 cargo,
3300 libtest_args,
3301 &["rustdoc-json-types".to_string()],
3302 "rustdoc-json-types",
3303 target,
3304 builder,
3305 );
3306 }
3307}
3308
3309#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3319pub struct RemoteCopyLibs {
3320 build_compiler: Compiler,
3321 target: TargetSelection,
3322}
3323
3324impl Step for RemoteCopyLibs {
3325 type Output = ();
3326
3327 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3328 run.never()
3329 }
3330
3331 fn run(self, builder: &Builder<'_>) {
3332 let build_compiler = self.build_compiler;
3333 let target = self.target;
3334 if !builder.remote_tested(target) {
3335 return;
3336 }
3337
3338 builder.std(build_compiler, target);
3339
3340 builder.info(&format!("REMOTE copy libs to emulator ({target})"));
3341
3342 let remote_test_server = builder.ensure(tool::RemoteTestServer { build_compiler, target });
3343
3344 let tool = builder.tool_exe(Tool::RemoteTestClient);
3346 let mut cmd = command(&tool);
3347 cmd.arg("spawn-emulator")
3348 .arg(target.triple)
3349 .arg(&remote_test_server.tool_path)
3350 .arg(builder.tempdir());
3351 if let Some(rootfs) = builder.qemu_rootfs(target) {
3352 cmd.arg(rootfs);
3353 }
3354 cmd.run(builder);
3355
3356 for f in t!(builder.sysroot_target_libdir(build_compiler, target).read_dir()) {
3358 let f = t!(f);
3359 if helpers::is_dylib(&f.path()) {
3360 command(&tool).arg("push").arg(f.path()).run(builder);
3361 }
3362 }
3363 }
3364}
3365
3366#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3367pub struct Distcheck;
3368
3369impl Step for Distcheck {
3370 type Output = ();
3371
3372 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3373 run.alias("distcheck")
3374 }
3375
3376 fn make_run(run: RunConfig<'_>) {
3377 run.builder.ensure(Distcheck);
3378 }
3379
3380 fn run(self, builder: &Builder<'_>) {
3390 let root_dir = std::env::temp_dir().join("distcheck");
3393
3394 distcheck_plain_source_tarball(builder, &root_dir.join("distcheck-rustc-src"));
3395 distcheck_rust_src(builder, &root_dir.join("distcheck-rust-src"));
3396 distcheck_rustc_dev(builder, &root_dir.join("distcheck-rustc-dev"));
3397 }
3398}
3399
3400fn distcheck_plain_source_tarball(builder: &Builder<'_>, plain_src_dir: &Path) {
3402 builder.info("Distcheck plain source tarball");
3403 let plain_src_tarball = builder.ensure(dist::PlainSourceTarball);
3404 builder.clear_dir(plain_src_dir);
3405
3406 let configure_args: Vec<String> = std::env::var("DISTCHECK_CONFIGURE_ARGS")
3407 .map(|args| args.split(" ").map(|s| s.to_string()).collect::<Vec<String>>())
3408 .unwrap_or_default();
3409
3410 command("tar")
3411 .arg("-xf")
3412 .arg(plain_src_tarball.tarball())
3413 .arg("--strip-components=1")
3414 .current_dir(plain_src_dir)
3415 .run(builder);
3416 command("./configure")
3417 .arg("--set")
3418 .arg("rust.omit-git-hash=false")
3419 .args(&configure_args)
3420 .arg("--enable-vendor")
3421 .current_dir(plain_src_dir)
3422 .run(builder);
3423 command(helpers::make(&builder.config.host_target.triple))
3424 .arg("check")
3425 .env("GITHUB_ACTIONS", "0")
3428 .current_dir(plain_src_dir)
3429 .run(builder);
3430 builder.remove_dir(plain_src_dir);
3432}
3433
3434fn distcheck_rust_src(builder: &Builder<'_>, src_dir: &Path) {
3436 builder.info("Distcheck rust-src");
3437 let src_tarball = builder.ensure(dist::Src);
3438 builder.clear_dir(src_dir);
3439
3440 command("tar")
3441 .arg("-xf")
3442 .arg(src_tarball.tarball())
3443 .arg("--strip-components=1")
3444 .current_dir(src_dir)
3445 .run(builder);
3446
3447 let toml = src_dir.join("rust-src/lib/rustlib/src/rust/library/std/Cargo.toml");
3448 command(&builder.initial_cargo)
3449 .env("RUSTC_BOOTSTRAP", "1")
3452 .arg("generate-lockfile")
3453 .arg("--manifest-path")
3454 .arg(&toml)
3455 .current_dir(src_dir)
3456 .run(builder);
3457 builder.remove_dir(src_dir);
3459}
3460
3461fn distcheck_rustc_dev(builder: &Builder<'_>, dir: &Path) {
3463 builder.info("Distcheck rustc-dev");
3464 let tarball = builder.ensure(dist::RustcDev::new(builder, builder.host_target)).unwrap();
3465 builder.clear_dir(dir);
3466
3467 command("tar")
3468 .arg("-xf")
3469 .arg(tarball.tarball())
3470 .arg("--strip-components=1")
3471 .current_dir(dir)
3472 .run(builder);
3473
3474 command(&builder.initial_cargo)
3475 .arg("metadata")
3476 .arg("--manifest-path")
3477 .arg("rustc-dev/lib/rustlib/rustc-src/rust/compiler/rustc/Cargo.toml")
3478 .env("RUSTC_BOOTSTRAP", "1")
3479 .env("RUSTC", &builder.initial_rustc)
3481 .current_dir(dir)
3482 .run(builder);
3483 builder.remove_dir(dir);
3485}
3486
3487#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3489pub(crate) struct BootstrapPy;
3490
3491impl Step for BootstrapPy {
3492 type Output = ();
3493 const IS_HOST: bool = true;
3494
3495 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3496 run.alias("bootstrap-py")
3497 }
3498
3499 fn is_default_step(builder: &Builder<'_>) -> bool {
3500 builder.config.is_running_on_ci
3504 }
3505
3506 fn make_run(run: RunConfig<'_>) {
3507 run.builder.ensure(BootstrapPy)
3508 }
3509
3510 fn run(self, builder: &Builder<'_>) -> Self::Output {
3511 let mut check_bootstrap = command(
3512 builder.config.python.as_ref().expect("python is required for running bootstrap tests"),
3513 );
3514 check_bootstrap
3515 .args(["-m", "unittest", "bootstrap_test.py"])
3516 .args(builder.config.test_args())
3518 .env("BUILD_DIR", &builder.out)
3519 .env("BUILD_PLATFORM", builder.build.host_target.triple)
3520 .env("BOOTSTRAP_TEST_RUSTC_BIN", &builder.initial_rustc)
3521 .env("BOOTSTRAP_TEST_CARGO_BIN", &builder.initial_cargo)
3522 .current_dir(builder.src.join("src/bootstrap/"));
3523 check_bootstrap.delay_failure().run(builder);
3524 }
3525}
3526
3527#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3528pub struct Bootstrap;
3529
3530impl Step for Bootstrap {
3531 type Output = ();
3532 const IS_HOST: bool = true;
3533
3534 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3535 run.path("src/bootstrap")
3536 }
3537
3538 fn is_default_step(builder: &Builder<'_>) -> bool {
3539 builder.config.is_running_on_ci
3543 }
3544
3545 fn run(self, builder: &Builder<'_>) {
3547 let host = builder.config.host_target;
3548 let build_compiler = builder.compiler(0, host);
3549
3550 builder.build.require_submodule("src/tools/cargo", None);
3552
3553 let mut cargo = tool::prepare_tool_cargo(
3554 builder,
3555 build_compiler,
3556 Mode::ToolBootstrap,
3557 host,
3558 Kind::Test,
3559 "src/bootstrap",
3560 SourceType::InTree,
3561 &[],
3562 );
3563
3564 cargo.release_build(false);
3565
3566 cargo
3567 .rustflag("-Cdebuginfo=2")
3568 .env("CARGO_TARGET_DIR", builder.out.join("bootstrap"))
3569 .env("INSTA_WORKSPACE_ROOT", &builder.src)
3571 .env("RUSTC_BOOTSTRAP", "1");
3572
3573 if builder.config.cmd.bless() {
3574 cargo.env("INSTA_UPDATE", "always");
3578 }
3579
3580 run_cargo_test(cargo, &[], &[], None, host, builder);
3581 }
3582
3583 fn make_run(run: RunConfig<'_>) {
3584 run.builder.ensure(Bootstrap);
3585 }
3586}
3587
3588fn get_compiler_to_test(builder: &Builder<'_>, target: TargetSelection) -> Compiler {
3589 builder.compiler(builder.top_stage, target)
3590}
3591
3592#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3595pub struct TierCheck {
3596 test_compiler: Compiler,
3597}
3598
3599impl Step for TierCheck {
3600 type Output = ();
3601 const IS_HOST: bool = true;
3602
3603 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3604 run.path("src/tools/tier-check")
3605 }
3606
3607 fn is_default_step(_builder: &Builder<'_>) -> bool {
3608 true
3609 }
3610
3611 fn make_run(run: RunConfig<'_>) {
3612 run.builder
3613 .ensure(TierCheck { test_compiler: get_compiler_to_test(run.builder, run.target) });
3614 }
3615
3616 fn run(self, builder: &Builder<'_>) {
3617 let tool_build_compiler = builder.compiler(0, builder.host_target);
3618
3619 let mut cargo = tool::prepare_tool_cargo(
3620 builder,
3621 tool_build_compiler,
3622 Mode::ToolBootstrap,
3623 tool_build_compiler.host,
3624 Kind::Run,
3625 "src/tools/tier-check",
3626 SourceType::InTree,
3627 &[],
3628 );
3629 cargo.arg(builder.src.join("src/doc/rustc/src/platform-support.md"));
3630 cargo.arg(builder.rustc(self.test_compiler));
3631
3632 let _guard = builder.msg_test(
3633 "platform support check",
3634 self.test_compiler.host,
3635 self.test_compiler.stage,
3636 );
3637 BootstrapCommand::from(cargo).delay_failure().run(builder);
3638 }
3639
3640 fn metadata(&self) -> Option<StepMetadata> {
3641 Some(StepMetadata::test("tier-check", self.test_compiler.host))
3642 }
3643}
3644
3645#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3646pub struct LintDocs {
3647 build_compiler: Compiler,
3648 target: TargetSelection,
3649}
3650
3651impl Step for LintDocs {
3652 type Output = ();
3653 const IS_HOST: bool = true;
3654
3655 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3656 run.path("src/tools/lint-docs")
3657 }
3658
3659 fn is_default_step(builder: &Builder<'_>) -> bool {
3660 builder.top_stage >= 2
3663 }
3664
3665 fn make_run(run: RunConfig<'_>) {
3666 if run.builder.top_stage < 2 {
3667 eprintln!("WARNING: lint-docs tests might not work below stage 2");
3668 }
3669
3670 run.builder.ensure(LintDocs {
3671 build_compiler: prepare_doc_compiler(
3672 run.builder,
3673 run.builder.config.host_target,
3674 run.builder.top_stage,
3675 ),
3676 target: run.target,
3677 });
3678 }
3679
3680 fn run(self, builder: &Builder<'_>) {
3683 builder.ensure(crate::core::build_steps::doc::RustcBook::validate(
3684 self.build_compiler,
3685 self.target,
3686 ));
3687 }
3688
3689 fn metadata(&self) -> Option<StepMetadata> {
3690 Some(StepMetadata::test("lint-docs", self.target).built_by(self.build_compiler))
3691 }
3692}
3693
3694#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3695pub struct RustInstaller;
3696
3697impl Step for RustInstaller {
3698 type Output = ();
3699 const IS_HOST: bool = true;
3700
3701 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3702 run.path("src/tools/rust-installer")
3703 }
3704
3705 fn is_default_step(_builder: &Builder<'_>) -> bool {
3706 true
3707 }
3708
3709 fn make_run(run: RunConfig<'_>) {
3710 run.builder.ensure(Self);
3711 }
3712
3713 fn run(self, builder: &Builder<'_>) {
3715 let bootstrap_host = builder.config.host_target;
3716 let build_compiler = builder.compiler(0, bootstrap_host);
3717 let cargo = tool::prepare_tool_cargo(
3718 builder,
3719 build_compiler,
3720 Mode::ToolBootstrap,
3721 bootstrap_host,
3722 Kind::Test,
3723 "src/tools/rust-installer",
3724 SourceType::InTree,
3725 &[],
3726 );
3727
3728 let _guard = builder.msg_test("rust-installer", bootstrap_host, 1);
3729 run_cargo_test(cargo, &[], &[], None, bootstrap_host, builder);
3730
3731 if bootstrap_host != "x86_64-unknown-linux-gnu" {
3735 return;
3736 }
3737
3738 let mut cmd = command(builder.src.join("src/tools/rust-installer/test.sh"));
3739 let tmpdir = testdir(builder, build_compiler.host).join("rust-installer");
3740 let _ = std::fs::remove_dir_all(&tmpdir);
3741 let _ = std::fs::create_dir_all(&tmpdir);
3742 cmd.current_dir(&tmpdir);
3743 cmd.env("CARGO_TARGET_DIR", tmpdir.join("cargo-target"));
3744 cmd.env("CARGO", &builder.initial_cargo);
3745 cmd.env("RUSTC", &builder.initial_rustc);
3746 cmd.env("TMP_DIR", &tmpdir);
3747 cmd.delay_failure().run(builder);
3748 }
3749}
3750
3751#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3752pub struct TestHelpers {
3753 pub target: TargetSelection,
3754}
3755
3756impl Step for TestHelpers {
3757 type Output = ();
3758
3759 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3760 run.path("tests/auxiliary/rust_test_helpers.c")
3761 }
3762
3763 fn make_run(run: RunConfig<'_>) {
3764 run.builder.ensure(TestHelpers { target: run.target })
3765 }
3766
3767 fn run(self, builder: &Builder<'_>) {
3770 if builder.config.dry_run() {
3771 return;
3772 }
3773 let target = if self.target == "x86_64-fortanix-unknown-sgx" {
3777 TargetSelection::from_user("x86_64-unknown-linux-gnu")
3778 } else {
3779 self.target
3780 };
3781 let dst = builder.test_helpers_out(target);
3782 let src = builder.src.join("tests/auxiliary/rust_test_helpers.c");
3783 if up_to_date(&src, &dst.join("librust_test_helpers.a")) {
3784 return;
3785 }
3786
3787 let _guard = builder.msg_unstaged(Kind::Build, "test helpers", target);
3788 t!(fs::create_dir_all(&dst));
3789 let mut cfg = cc::Build::new();
3790
3791 if !target.is_msvc() {
3795 if let Some(ar) = builder.ar(target) {
3796 cfg.archiver(ar);
3797 }
3798 cfg.compiler(builder.cc(target));
3799 }
3800 cfg.cargo_metadata(false)
3801 .out_dir(&dst)
3802 .target(&target.triple)
3803 .host(&builder.config.host_target.triple)
3804 .opt_level(0)
3805 .warnings(false)
3806 .debug(false)
3807 .file(builder.src.join("tests/auxiliary/rust_test_helpers.c"))
3808 .compile("rust_test_helpers");
3809 }
3810}
3811
3812#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3813pub struct CodegenCranelift {
3814 compilers: RustcPrivateCompilers,
3815 target: TargetSelection,
3816}
3817
3818impl Step for CodegenCranelift {
3819 type Output = ();
3820 const IS_HOST: bool = true;
3821
3822 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3823 run.path("compiler/rustc_codegen_cranelift")
3824 }
3825
3826 fn is_default_step(_builder: &Builder<'_>) -> bool {
3827 true
3828 }
3829
3830 fn make_run(run: RunConfig<'_>) {
3831 let builder = run.builder;
3832 let host = run.build_triple();
3833 let compilers = RustcPrivateCompilers::new(run.builder, run.builder.top_stage, host);
3834
3835 if builder.doc_tests == DocTests::Only {
3836 return;
3837 }
3838
3839 if builder.download_rustc() {
3840 builder.info("CI rustc uses the default codegen backend. skipping");
3841 return;
3842 }
3843
3844 if !target_supports_cranelift_backend(run.target) {
3845 builder.info("target not supported by rustc_codegen_cranelift. skipping");
3846 return;
3847 }
3848
3849 if builder.remote_tested(run.target) {
3850 builder.info("remote testing is not supported by rustc_codegen_cranelift. skipping");
3851 return;
3852 }
3853
3854 if !builder
3855 .config
3856 .enabled_codegen_backends(run.target)
3857 .contains(&CodegenBackendKind::Cranelift)
3858 {
3859 builder.info("cranelift not in rust.codegen-backends. skipping");
3860 return;
3861 }
3862
3863 builder.ensure(CodegenCranelift { compilers, target: run.target });
3864 }
3865
3866 fn run(self, builder: &Builder<'_>) {
3867 let compilers = self.compilers;
3868 let build_compiler = compilers.build_compiler();
3869
3870 let target_compiler = compilers.target_compiler();
3873 let target = self.target;
3874
3875 builder.std(target_compiler, target);
3876
3877 let mut cargo = builder::Cargo::new(
3878 builder,
3879 target_compiler,
3880 Mode::Codegen, SourceType::InTree,
3882 target,
3883 Kind::Run,
3884 );
3885
3886 cargo.current_dir(&builder.src.join("compiler/rustc_codegen_cranelift"));
3887 cargo
3888 .arg("--manifest-path")
3889 .arg(builder.src.join("compiler/rustc_codegen_cranelift/build_system/Cargo.toml"));
3890 compile::rustc_cargo_env(builder, &mut cargo, target);
3891
3892 cargo.env("CARGO_BUILD_INCREMENTAL", "false");
3894
3895 let _guard = builder.msg_test(
3896 "rustc_codegen_cranelift",
3897 target_compiler.host,
3898 target_compiler.stage,
3899 );
3900
3901 let download_dir = builder.out.join("cg_clif_download");
3903
3904 cargo
3905 .arg("--")
3906 .arg("test")
3907 .arg("--download-dir")
3908 .arg(&download_dir)
3909 .arg("--out-dir")
3910 .arg(builder.stage_out(build_compiler, Mode::Codegen).join("cg_clif"))
3911 .arg("--no-unstable-features")
3912 .arg("--use-backend")
3913 .arg("cranelift")
3914 .arg("--sysroot")
3916 .arg("llvm")
3917 .arg("--skip-test")
3920 .arg("testsuite.extended_sysroot");
3921
3922 cargo.into_cmd().run(builder);
3923 }
3924
3925 fn metadata(&self) -> Option<StepMetadata> {
3926 Some(
3927 StepMetadata::test("rustc_codegen_cranelift", self.target)
3928 .built_by(self.compilers.build_compiler()),
3929 )
3930 }
3931}
3932
3933#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3934pub struct CodegenGCC {
3935 compilers: RustcPrivateCompilers,
3936 target: TargetSelection,
3937}
3938
3939impl Step for CodegenGCC {
3940 type Output = ();
3941 const IS_HOST: bool = true;
3942
3943 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3944 run.path("compiler/rustc_codegen_gcc")
3945 }
3946
3947 fn is_default_step(_builder: &Builder<'_>) -> bool {
3948 true
3949 }
3950
3951 fn make_run(run: RunConfig<'_>) {
3952 let builder = run.builder;
3953 let host = run.build_triple();
3954 let compilers = RustcPrivateCompilers::new(run.builder, run.builder.top_stage, host);
3955
3956 if builder.doc_tests == DocTests::Only {
3957 return;
3958 }
3959
3960 if builder.download_rustc() {
3961 builder.info("CI rustc uses the default codegen backend. skipping");
3962 return;
3963 }
3964
3965 let triple = run.target.triple;
3966 let target_supported =
3967 if triple.contains("linux") { triple.contains("x86_64") } else { false };
3968 if !target_supported {
3969 builder.info("target not supported by rustc_codegen_gcc. skipping");
3970 return;
3971 }
3972
3973 if builder.remote_tested(run.target) {
3974 builder.info("remote testing is not supported by rustc_codegen_gcc. skipping");
3975 return;
3976 }
3977
3978 if !builder.config.enabled_codegen_backends(run.target).contains(&CodegenBackendKind::Gcc) {
3979 builder.info("gcc not in rust.codegen-backends. skipping");
3980 return;
3981 }
3982
3983 builder.ensure(CodegenGCC { compilers, target: run.target });
3984 }
3985
3986 fn run(self, builder: &Builder<'_>) {
3987 let compilers = self.compilers;
3988 let target = self.target;
3989
3990 let gcc = builder.ensure(Gcc { target_pair: GccTargetPair::for_native_build(target) });
3991
3992 builder.ensure(
3993 compile::Std::new(compilers.build_compiler(), target)
3994 .extra_rust_args(&["-Csymbol-mangling-version=v0", "-Cpanic=abort"]),
3995 );
3996
3997 let _guard = builder.msg_test(
3998 "rustc_codegen_gcc",
3999 compilers.target(),
4000 compilers.target_compiler().stage,
4001 );
4002
4003 let mut cargo = builder::Cargo::new(
4004 builder,
4005 compilers.build_compiler(),
4006 Mode::Codegen, SourceType::InTree,
4008 target,
4009 Kind::Run,
4010 );
4011
4012 cargo.current_dir(&builder.src.join("compiler/rustc_codegen_gcc"));
4013 cargo
4014 .arg("--manifest-path")
4015 .arg(builder.src.join("compiler/rustc_codegen_gcc/build_system/Cargo.toml"));
4016 compile::rustc_cargo_env(builder, &mut cargo, target);
4017 add_cg_gcc_cargo_flags(&mut cargo, &gcc);
4018
4019 cargo.env("CARGO_BUILD_INCREMENTAL", "false");
4021 cargo.rustflag("-Cpanic=abort");
4022
4023 cargo
4024 .env("CG_RUSTFLAGS", "-Alinker-messages")
4026 .arg("--")
4027 .arg("test")
4028 .arg("--use-backend")
4029 .arg("gcc")
4030 .arg("--gcc-path")
4031 .arg(gcc.libgccjit().parent().unwrap())
4032 .arg("--out-dir")
4033 .arg(builder.stage_out(compilers.build_compiler(), Mode::Codegen).join("cg_gcc"))
4034 .arg("--release")
4035 .arg("--mini-tests")
4036 .arg("--std-tests");
4037
4038 cargo.args(builder.config.test_args());
4039
4040 cargo.into_cmd().run(builder);
4041 }
4042
4043 fn metadata(&self) -> Option<StepMetadata> {
4044 Some(
4045 StepMetadata::test("rustc_codegen_gcc", self.target)
4046 .built_by(self.compilers.build_compiler()),
4047 )
4048 }
4049}
4050
4051#[derive(Debug, Clone, PartialEq, Eq, Hash)]
4056pub struct TestFloatParse {
4057 build_compiler: Compiler,
4066 target: TargetSelection,
4068}
4069
4070impl Step for TestFloatParse {
4071 type Output = ();
4072 const IS_HOST: bool = true;
4073
4074 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
4075 run.path("src/tools/test-float-parse")
4076 }
4077
4078 fn is_default_step(_builder: &Builder<'_>) -> bool {
4079 true
4080 }
4081
4082 fn make_run(run: RunConfig<'_>) {
4083 run.builder.ensure(Self {
4084 build_compiler: get_compiler_to_test(run.builder, run.target),
4085 target: run.target,
4086 });
4087 }
4088
4089 fn run(self, builder: &Builder<'_>) {
4090 let build_compiler = self.build_compiler;
4091 let target = self.target;
4092
4093 builder.std(build_compiler, target);
4095 builder.std(build_compiler, builder.host_target);
4096
4097 let mut cargo_test = tool::prepare_tool_cargo(
4099 builder,
4100 build_compiler,
4101 Mode::ToolStd,
4102 target,
4103 Kind::Test,
4104 "src/tools/test-float-parse",
4105 SourceType::InTree,
4106 &[],
4107 );
4108 cargo_test.allow_features(TEST_FLOAT_PARSE_ALLOW_FEATURES);
4109
4110 run_cargo_test(cargo_test, &[], &[], "test-float-parse", target, builder);
4111
4112 let mut cargo_run = tool::prepare_tool_cargo(
4114 builder,
4115 build_compiler,
4116 Mode::ToolStd,
4117 target,
4118 Kind::Run,
4119 "src/tools/test-float-parse",
4120 SourceType::InTree,
4121 &[],
4122 );
4123 cargo_run.allow_features(TEST_FLOAT_PARSE_ALLOW_FEATURES);
4124
4125 if !matches!(env::var("FLOAT_PARSE_TESTS_NO_SKIP_HUGE").as_deref(), Ok("1") | Ok("true")) {
4126 cargo_run.args(["--", "--skip-huge"]);
4127 }
4128
4129 cargo_run.into_cmd().run(builder);
4130 }
4131}
4132
4133#[derive(Debug, Clone, Hash, PartialEq, Eq)]
4137pub struct CollectLicenseMetadata;
4138
4139impl Step for CollectLicenseMetadata {
4140 type Output = PathBuf;
4141 const IS_HOST: bool = true;
4142
4143 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
4144 run.path("src/tools/collect-license-metadata")
4145 }
4146
4147 fn make_run(run: RunConfig<'_>) {
4148 run.builder.ensure(CollectLicenseMetadata);
4149 }
4150
4151 fn run(self, builder: &Builder<'_>) -> Self::Output {
4152 let Some(reuse) = &builder.config.reuse else {
4153 panic!("REUSE is required to collect the license metadata");
4154 };
4155
4156 let dest = builder.src.join("license-metadata.json");
4157
4158 let mut cmd = builder.tool_cmd(Tool::CollectLicenseMetadata);
4159 cmd.env("REUSE_EXE", reuse);
4160 cmd.env("DEST", &dest);
4161 cmd.env("ONLY_CHECK", "1");
4162 cmd.run(builder);
4163
4164 dest
4165 }
4166}
4167
4168#[derive(Debug, Clone, PartialEq, Eq, Hash)]
4169pub struct RemoteTestClientTests {
4170 host: TargetSelection,
4171}
4172
4173impl Step for RemoteTestClientTests {
4174 type Output = ();
4175 const IS_HOST: bool = true;
4176
4177 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
4178 run.path("src/tools/remote-test-client")
4179 }
4180
4181 fn is_default_step(_builder: &Builder<'_>) -> bool {
4182 true
4183 }
4184
4185 fn make_run(run: RunConfig<'_>) {
4186 run.builder.ensure(Self { host: run.target });
4187 }
4188
4189 fn run(self, builder: &Builder<'_>) {
4190 let bootstrap_host = builder.config.host_target;
4191 let compiler = builder.compiler(0, bootstrap_host);
4192
4193 let cargo = tool::prepare_tool_cargo(
4194 builder,
4195 compiler,
4196 Mode::ToolBootstrap,
4197 bootstrap_host,
4198 Kind::Test,
4199 "src/tools/remote-test-client",
4200 SourceType::InTree,
4201 &[],
4202 );
4203
4204 run_cargo_test(cargo, &[], &[], "remote-test-client", bootstrap_host, builder);
4205 }
4206}