1use std::collections::HashSet;
10use std::env::split_paths;
11use std::ffi::{OsStr, OsString};
12use std::path::{Path, PathBuf};
13use std::process::Command;
14use std::{env, fs, iter};
15
16use build_helper::git::get_closest_upstream_commit;
17
18use crate::core::backend::CodegenBackendKind;
19use crate::core::build_steps::compile::{ArtifactKeepMode, Std, run_cargo};
20use crate::core::build_steps::doc::{DocumentationFormat, prepare_doc_compiler};
21use crate::core::build_steps::format::InternalRustfmt;
22use crate::core::build_steps::gcc::{Gcc, GccTargetPair, add_cg_gcc_cargo_flags};
23use crate::core::build_steps::llvm::get_llvm_version;
24use crate::core::build_steps::run::{get_completion_paths, get_help_path};
25use crate::core::build_steps::synthetic_targets::MirOptPanicAbortSyntheticTarget;
26use crate::core::build_steps::test::compiletest::CompiletestMode;
27use crate::core::build_steps::test::failed_tests::{RecordFailedTests, SetupFailedTestsFile};
28use crate::core::build_steps::tool::{
29 self, RustcPrivateCompilers, SourceType, TEST_FLOAT_PARSE_ALLOW_FEATURES, Tool,
30 ToolTargetBuildMode, get_tool_target_compiler,
31};
32use crate::core::build_steps::toolstate::ToolState;
33use crate::core::build_steps::{compile, dist, llvm};
34use crate::core::builder::{
35 self, Alias, Builder, CommandLineStep, Kind, RunConfig, ShouldRun, Step, StepMetadata,
36 crate_description,
37};
38use crate::core::compiler::Compiler;
39use crate::core::config::TargetSelection;
40use crate::core::config::flags::{Subcommand, get_completion, top_level_help};
41use crate::core::session::{CLang, Mode};
42use crate::core::{android, debuggers};
43use crate::utils::build_stamp::{self, BuildStamp};
44use crate::utils::exec::{BootstrapCommand, command};
45use crate::utils::helpers::{
46 self, LldThreads, TestFilterCategory, add_dylib_path, add_rustdoc_cargo_linker_args,
47 dylib_path, dylib_path_var, envify, linker_args, linker_flags, t,
48 target_supports_cranelift_backend, up_to_date,
49};
50use crate::utils::render_tests::{add_flags_and_try_run_tests, try_run_tests};
51mod compiletest;
52pub mod failed_tests;
53
54#[derive(PartialEq, Eq, Copy, Clone, Debug)]
55pub enum TestTarget {
56 Default,
58 AllTargets,
60 DocOnly,
62 Tests,
64}
65
66impl TestTarget {
67 pub(crate) fn runs_doctests(&self) -> bool {
68 matches!(self, TestTarget::DocOnly | TestTarget::Default)
69 }
70}
71
72#[derive(Debug, Clone, PartialEq, Eq, Hash)]
74pub struct CrateBootstrap {
75 path: PathBuf,
76 host: TargetSelection,
77}
78
79impl CommandLineStep for CrateBootstrap {
80 type Output = ();
81 const IS_HOST: bool = true;
82
83 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
84 run.path("src/tools/jsondoclint")
89 .path("src/tools/replace-version-placeholder")
90 .path("src/tools/coverage-dump")
91 .alias("tidyselftest")
94 }
95
96 fn is_default_step(_builder: &Builder<'_>) -> bool {
97 true
98 }
99
100 fn make_run(run: RunConfig<'_>) {
101 for path in run.paths {
104 let path = path.assert_single_path().path.clone();
105 run.builder.ensure(CrateBootstrap { host: run.target, path });
106 }
107 }
108
109 fn run(self, builder: &Builder<'_>) {
110 let bootstrap_host = builder.config.host_target;
111 let compiler = builder.compiler(0, bootstrap_host);
112 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
113 let mut path = self.path.to_str().unwrap();
114
115 if path == "tidyselftest" {
117 path = "src/tools/tidy";
118 }
119
120 let cargo = tool::prepare_tool_cargo(
121 builder,
122 compiler,
123 Mode::ToolBootstrap,
124 bootstrap_host,
125 Kind::Test,
126 path,
127 SourceType::InTree,
128 &[],
129 );
130
131 let crate_name = path.rsplit_once('/').unwrap().1;
132 run_cargo_test(cargo, &[], &[], crate_name, bootstrap_host, builder, record_failed_tests);
133 }
134
135 fn metadata(&self) -> Option<StepMetadata> {
136 Some(
137 StepMetadata::test("crate-bootstrap", self.host)
138 .with_metadata(self.path.as_path().to_string_lossy().to_string()),
139 )
140 }
141}
142
143#[derive(Debug, Clone, PartialEq, Eq, Hash)]
144pub struct Linkcheck {
145 host: TargetSelection,
146}
147
148impl CommandLineStep for Linkcheck {
149 type Output = ();
150 const IS_HOST: bool = true;
151
152 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
153 run.path("src/tools/linkchecker")
154 }
155
156 fn is_default_step(builder: &Builder<'_>) -> bool {
157 builder.config.docs
158 }
159
160 fn make_run(run: RunConfig<'_>) {
161 run.builder.ensure(Linkcheck { host: run.target });
162 }
163
164 fn run(self, builder: &Builder<'_>) {
169 let host = self.host;
170 let hosts = &builder.hosts;
171 let targets = &builder.targets;
172
173 if (hosts != targets) && !hosts.is_empty() && !targets.is_empty() {
178 panic!(
179 "Linkcheck currently does not support builds with different hosts and targets.
180You can skip linkcheck with --skip src/tools/linkchecker"
181 );
182 }
183
184 builder.info(&format!("Linkcheck ({host})"));
185
186 let bootstrap_host = builder.config.host_target;
188 let compiler = builder.compiler(0, bootstrap_host);
189 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
190
191 let cargo = tool::prepare_tool_cargo(
192 builder,
193 compiler,
194 Mode::ToolBootstrap,
195 bootstrap_host,
196 Kind::Test,
197 "src/tools/linkchecker",
198 SourceType::InTree,
199 &[],
200 );
201 run_cargo_test(
202 cargo,
203 &[],
204 &[],
205 "linkchecker self tests",
206 bootstrap_host,
207 builder,
208 record_failed_tests,
209 );
210
211 if !builder.test_target.runs_doctests() {
212 return;
213 }
214
215 builder.run_default_doc_steps();
217
218 let linkchecker = builder.tool_cmd(Tool::Linkchecker);
220
221 let _guard = builder.msg_test("Linkcheck", bootstrap_host, 1);
223 let _time = helpers::timeit(builder);
224 linkchecker.delay_failure().arg(builder.out.join(host).join("doc")).run(builder);
225 }
226
227 fn metadata(&self) -> Option<StepMetadata> {
228 Some(StepMetadata::test("link-check", self.host))
229 }
230}
231
232fn check_if_tidy_is_installed(builder: &Builder<'_>) -> bool {
233 command("tidy")
234 .allow_failure()
235 .arg("--version")
236 .cached()
238 .run_capture_stdout(builder)
239 .is_success()
240}
241
242#[derive(Debug, Clone, PartialEq, Eq, Hash)]
243pub struct HtmlCheck {
244 target: TargetSelection,
245}
246
247impl CommandLineStep for HtmlCheck {
248 type Output = ();
249 const IS_HOST: bool = true;
250
251 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
252 run.path("src/tools/html-checker")
253 }
254
255 fn is_default_step(builder: &Builder<'_>) -> bool {
256 check_if_tidy_is_installed(builder)
257 }
258
259 fn make_run(run: RunConfig<'_>) {
260 run.builder.ensure(HtmlCheck { target: run.target });
261 }
262
263 fn run(self, builder: &Builder<'_>) {
264 if !check_if_tidy_is_installed(builder) {
265 eprintln!("not running HTML-check tool because `tidy` is missing");
266 eprintln!(
267 "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."
268 );
269 panic!("Cannot run html-check tests");
270 }
271 builder.run_default_doc_steps();
273 builder.ensure(crate::core::build_steps::doc::Rustc::for_stage(
274 builder,
275 builder.top_stage,
276 self.target,
277 ));
278
279 builder
280 .tool_cmd(Tool::HtmlChecker)
281 .delay_failure()
282 .arg(builder.doc_out(self.target))
283 .run(builder);
284 }
285
286 fn metadata(&self) -> Option<StepMetadata> {
287 Some(StepMetadata::test("html-check", self.target))
288 }
289}
290
291#[derive(Debug, Clone, PartialEq, Eq, Hash)]
295pub struct Cargotest {
296 build_compiler: Compiler,
297 host: TargetSelection,
298}
299
300impl CommandLineStep for Cargotest {
301 type Output = ();
302 const IS_HOST: bool = true;
303
304 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
305 run.path("src/tools/cargotest")
306 }
307
308 fn make_run(run: RunConfig<'_>) {
309 if run.builder.top_stage == 0 {
310 eprintln!(
311 "ERROR: running cargotest with stage 0 is currently unsupported. Use at least stage 1."
312 );
313 helpers::exit_process(1);
314 }
315 run.builder.ensure(Cargotest {
319 build_compiler: run.builder.compiler(run.builder.top_stage - 1, run.target),
320 host: run.target,
321 });
322 }
323
324 fn run(self, builder: &Builder<'_>) {
329 let cargo =
339 builder.ensure(tool::Cargo::from_build_compiler(self.build_compiler, self.host));
340 let tested_compiler = builder.compiler(self.build_compiler.stage + 1, self.host);
341 builder.std(tested_compiler, self.host);
342
343 let out_dir = builder.out.join("ct");
347 t!(fs::create_dir_all(&out_dir));
348
349 let _time = helpers::timeit(builder);
350 let mut cmd = builder.tool_cmd(Tool::CargoTest);
351 cmd.arg(&cargo.tool_path)
352 .arg(&out_dir)
353 .args(builder.config.test_args())
354 .env("RUSTC", builder.rustc(tested_compiler))
355 .env("RUSTDOC", builder.rustdoc_for_compiler(tested_compiler));
356 add_rustdoc_cargo_linker_args(&mut cmd, builder, tested_compiler.host, LldThreads::No);
357 cmd.delay_failure().run(builder);
358 }
359
360 fn metadata(&self) -> Option<StepMetadata> {
361 Some(StepMetadata::test("cargotest", self.host).stage(self.build_compiler.stage + 1))
362 }
363}
364
365#[derive(Debug, Clone, PartialEq, Eq, Hash)]
368pub struct Cargo {
369 build_compiler: Compiler,
370 host: TargetSelection,
371}
372
373impl Cargo {
374 const CRATE_PATH: &str = "src/tools/cargo";
375}
376
377impl CommandLineStep for Cargo {
378 type Output = ();
379 const IS_HOST: bool = true;
380
381 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
382 run.path(Self::CRATE_PATH)
383 }
384
385 fn make_run(run: RunConfig<'_>) {
386 run.builder.ensure(Cargo {
387 build_compiler: get_tool_target_compiler(
388 run.builder,
389 ToolTargetBuildMode::Build(run.target),
390 ),
391 host: run.target,
392 });
393 }
394
395 fn run(self, builder: &Builder<'_>) {
397 builder.ensure(tool::Cargo::from_build_compiler(self.build_compiler, self.host));
401 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
402
403 let tested_compiler = builder.compiler(self.build_compiler.stage + 1, self.host);
404 builder.std(tested_compiler, self.host);
405 builder.rustdoc_for_compiler(tested_compiler);
409
410 let cargo = tool::prepare_tool_cargo(
411 builder,
412 self.build_compiler,
413 Mode::ToolTarget,
414 self.host,
415 Kind::Test,
416 Self::CRATE_PATH,
417 SourceType::Submodule,
418 &[],
419 );
420
421 let mut cargo = prepare_cargo_test(cargo, &[], &[], self.host, builder);
423
424 cargo.env("CFG_DISABLE_CROSS_TESTS", "1");
427 cargo.env("CARGO_TEST_DISABLE_NIGHTLY", "1");
430
431 cargo.env("PATH", bin_path_for_cargo(builder, tested_compiler));
435
436 let mut existing_dylib_paths = cargo
441 .get_envs()
442 .find(|(k, _)| *k == OsStr::new(dylib_path_var()))
443 .and_then(|(_, v)| v)
444 .map(|value| split_paths(value).collect::<Vec<PathBuf>>())
445 .unwrap_or_default();
446 existing_dylib_paths.insert(0, builder.rustc_libdir(tested_compiler));
447 add_dylib_path(existing_dylib_paths, &mut cargo);
448
449 cargo.env("CARGO_RUSTC_CURRENT_DIR", builder.src.display().to_string());
453
454 #[cfg(feature = "build-metrics")]
455 builder.metrics.begin_test_suite(
456 build_helper::metrics::TestSuiteMetadata::CargoPackage {
457 crates: vec!["cargo".into()],
458 target: self.host.triple.to_string(),
459 host: self.host.triple.to_string(),
460 stage: self.build_compiler.stage + 1,
461 },
462 builder,
463 );
464
465 let _time = helpers::timeit(builder);
466 add_flags_and_try_run_tests(builder, &mut cargo, record_failed_tests);
467 }
468
469 fn metadata(&self) -> Option<StepMetadata> {
470 Some(StepMetadata::test("cargo", self.host).built_by(self.build_compiler))
471 }
472}
473
474#[derive(Debug, Clone, PartialEq, Eq, Hash)]
475pub struct RustAnalyzer {
476 compilers: RustcPrivateCompilers,
477}
478
479impl CommandLineStep for RustAnalyzer {
480 type Output = ();
481 const IS_HOST: bool = true;
482
483 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
484 run.path("src/tools/rust-analyzer")
485 }
486
487 fn is_default_step(_builder: &Builder<'_>) -> bool {
488 true
489 }
490
491 fn make_run(run: RunConfig<'_>) {
492 run.builder.ensure(Self {
493 compilers: RustcPrivateCompilers::new(
494 run.builder,
495 run.builder.top_stage,
496 run.builder.host_target,
497 ),
498 });
499 }
500
501 fn run(self, builder: &Builder<'_>) {
503 let build_compiler = self.compilers.build_compiler();
504 let target = self.compilers.target();
505 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
506
507 if target.starts_with("i686") {
517 return;
518 }
519
520 let suite = "src/tools/rust-analyzer";
521 let mut cargo = tool::prepare_tool_cargo(
522 builder,
523 build_compiler,
524 Mode::ToolRustcPrivate,
525 target,
526 Kind::Test,
527 suite,
528 SourceType::InTree,
529 &["in-rust-tree".to_owned()],
530 );
531 cargo.allow_features(tool::RustAnalyzer::ALLOW_FEATURES);
532
533 cargo.env("SKIP_SLOW_TESTS", "1");
540
541 cargo.arg("--workspace");
547 cargo.arg("--exclude=xtask");
548
549 if build_compiler.stage == 0 {
550 cargo.arg("--exclude=proc-macro-srv");
553 cargo.arg("--exclude=proc-macro-srv-cli");
554 }
555
556 let mut skip_tests = vec![];
557
558 skip_tests.extend_from_slice(&[
566 "tests::smoke_test_real_sysroot_cargo",
569 "check_code_formatting",
572 ]);
573
574 let skip_tests = skip_tests.iter().map(|name| format!("--skip={name}")).collect::<Vec<_>>();
575 let skip_tests = skip_tests.iter().map(|s| s.as_str()).collect::<Vec<_>>();
576
577 cargo.add_rustc_lib_path(builder);
578 run_cargo_test(
579 cargo,
580 skip_tests.as_slice(),
581 &[],
582 "rust-analyzer",
583 target,
584 builder,
585 record_failed_tests,
586 );
587 }
588
589 fn metadata(&self) -> Option<StepMetadata> {
590 Some(
591 StepMetadata::test("rust-analyzer", self.compilers.target())
592 .built_by(self.compilers.build_compiler()),
593 )
594 }
595}
596
597#[derive(Debug, Clone, PartialEq, Eq, Hash)]
599pub struct Rustfmt {
600 compilers: RustcPrivateCompilers,
601}
602
603impl CommandLineStep for Rustfmt {
604 type Output = ();
605 const IS_HOST: bool = true;
606
607 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
608 run.path("src/tools/rustfmt")
609 }
610
611 fn make_run(run: RunConfig<'_>) {
612 run.builder.ensure(Rustfmt {
613 compilers: RustcPrivateCompilers::new(
614 run.builder,
615 run.builder.top_stage,
616 run.builder.host_target,
617 ),
618 });
619 }
620
621 fn run(self, builder: &Builder<'_>) {
623 let build_compiler = self.compilers.build_compiler();
624 let target = self.compilers.target();
625 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
626
627 builder.ensure(compile::Rustc::new(build_compiler, target));
631
632 let mut cargo = tool::prepare_tool_cargo(
633 builder,
634 build_compiler,
635 Mode::ToolRustcPrivate,
636 target,
637 Kind::Test,
638 "src/tools/rustfmt",
639 SourceType::InTree,
640 &[],
641 );
642
643 let dir = testdir(builder, target);
644 t!(fs::create_dir_all(&dir));
645 cargo.env("RUSTFMT_TEST_DIR", dir);
646
647 cargo.add_rustc_lib_path(builder);
648
649 run_cargo_test(cargo, &[], &[], "rustfmt", target, builder, record_failed_tests);
650 }
651
652 fn metadata(&self) -> Option<StepMetadata> {
653 Some(
654 StepMetadata::test("rustfmt", self.compilers.target())
655 .built_by(self.compilers.build_compiler()),
656 )
657 }
658}
659
660#[derive(Debug, Clone, PartialEq, Eq, Hash)]
661pub struct Miri {
662 target: TargetSelection,
663}
664
665impl Miri {
666 pub fn build_miri_sysroot(
668 builder: &Builder<'_>,
669 compiler: Compiler,
670 target: TargetSelection,
671 ) -> PathBuf {
672 let miri_sysroot = builder.out.join(compiler.host).join("miri-sysroot");
673 let mut cargo = builder::Cargo::new(
674 builder,
675 compiler,
676 Mode::Std,
677 SourceType::Submodule,
678 target,
679 Kind::MiriSetup,
680 );
681
682 cargo.env("MIRI_LIB_SRC", builder.src.join("library"));
684 cargo.env("MIRI_SYSROOT", &miri_sysroot);
686
687 let mut cargo = BootstrapCommand::from(cargo);
688 let _guard =
689 builder.msg(Kind::Build, "miri sysroot", Mode::ToolRustcPrivate, compiler, target);
690 cargo.run(builder);
691
692 cargo.arg("--print-sysroot");
698
699 builder.do_if_verbose(|| println!("running: {cargo:?}"));
700 let stdout = cargo.run_capture_stdout(builder).stdout();
701 let sysroot = stdout.trim_end();
703 builder.do_if_verbose(|| println!("`cargo miri setup --print-sysroot` said: {sysroot:?}"));
704 PathBuf::from(sysroot)
705 }
706}
707
708impl CommandLineStep for Miri {
709 type Output = ();
710
711 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
712 run.path("src/tools/miri")
713 }
714
715 fn make_run(run: RunConfig<'_>) {
716 run.builder.ensure(Miri { target: run.target });
717 }
718
719 fn run(self, builder: &Builder<'_>) {
721 let host = builder.sess.host_target;
722 let target = self.target;
723 let stage = builder.top_stage;
724 if stage == 0 {
725 eprintln!("miri cannot be tested at stage 0");
726 std::process::exit(1);
727 }
728
729 let compilers = RustcPrivateCompilers::new(builder, stage, host);
731
732 let miri = builder.ensure(tool::Miri::from_compilers(compilers));
734 builder.ensure(tool::CargoMiri::from_compilers(compilers));
736
737 let target_compiler = compilers.target_compiler();
738
739 let miri_sysroot = Miri::build_miri_sysroot(builder, target_compiler, target);
742 builder.std(target_compiler, host);
743 let host_sysroot = builder.sysroot(target_compiler);
744
745 if !builder.config.dry_run() {
748 let ui_test_dep_dir = builder
751 .stage_out(miri.build_compiler, Mode::ToolStd)
752 .join(host)
753 .join("tmp")
754 .join("miri_ui");
755 build_stamp::clear_if_dirty(builder, &ui_test_dep_dir, &miri_sysroot);
759 }
760
761 let mut cargo = tool::prepare_tool_cargo(
764 builder,
765 miri.build_compiler,
766 Mode::ToolRustcPrivate,
767 host,
768 Kind::Test,
769 "src/tools/miri",
770 SourceType::InTree,
771 &[],
772 );
773
774 cargo.add_rustc_lib_path(builder);
775
776 let mut cargo = prepare_cargo_test(cargo, &[], &[], host, builder);
779
780 cargo.env("MIRI_SYSROOT", &miri_sysroot);
782 cargo.env("MIRI_HOST_SYSROOT", &host_sysroot);
783
784 cargo.env("MIRI_TEST_TARGET", target.rustc_target_arg());
786
787 {
788 let _guard = builder.msg_test("miri", target, target_compiler.stage);
789 let _time = helpers::timeit(builder);
790 cargo.run(builder);
791 }
792 }
793}
794
795#[derive(Debug, Clone, PartialEq, Eq, Hash)]
798pub struct CargoMiri {
799 target: TargetSelection,
800}
801
802impl CommandLineStep for CargoMiri {
803 type Output = ();
804
805 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
806 run.path("src/tools/miri/cargo-miri")
807 }
808
809 fn make_run(run: RunConfig<'_>) {
810 run.builder.ensure(CargoMiri { target: run.target });
811 }
812
813 fn run(self, builder: &Builder<'_>) {
815 let host = builder.sess.host_target;
816 let target = self.target;
817 let stage = builder.top_stage;
818 if stage == 0 {
819 eprintln!("cargo-miri cannot be tested at stage 0");
820 std::process::exit(1);
821 }
822
823 let build_compiler = builder.compiler(stage, host);
825
826 let mut cargo = tool::prepare_tool_cargo(
831 builder,
832 build_compiler,
833 Mode::ToolStd, target,
835 Kind::MiriTest,
836 "src/tools/miri/test-cargo-miri",
837 SourceType::Submodule,
838 &[],
839 );
840 cargo.arg("--workspace");
842 cargo.env("MIRIFLAGS", "-Zmiri-disable-isolation");
844
845 if stage >= 2 {
848 let built_cargo = builder
849 .ensure(tool::Cargo::from_build_compiler(
850 builder.compiler(0, builder.host_target),
853 builder.host_target,
854 ))
855 .tool_path;
856 cargo.env("CARGO", built_cargo);
857 }
858
859 match builder.test_target {
862 TestTarget::AllTargets => {
863 cargo.args(["--lib", "--bins", "--examples", "--tests", "--benches"])
864 }
865 TestTarget::Default => &mut cargo,
866 TestTarget::DocOnly => cargo.arg("--doc"),
867 TestTarget::Tests => cargo.arg("--tests"),
868 };
869 cargo.arg("--").args(builder.config.test_args());
870
871 let mut cargo = BootstrapCommand::from(cargo);
873 {
874 let _guard = builder.msg_test("cargo-miri", target, stage);
875 let _time = helpers::timeit(builder);
876 cargo.run(builder);
877 }
878 }
879}
880
881#[derive(Debug, Clone, PartialEq, Eq, Hash)]
882pub struct Priroda {
883 target: TargetSelection,
884}
885
886impl CommandLineStep for Priroda {
887 type Output = ();
888
889 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
890 run.path("src/tools/miri/priroda")
891 }
892
893 fn make_run(run: RunConfig<'_>) {
894 run.builder.ensure(Priroda { target: run.target });
895 }
896
897 fn run(self, builder: &Builder<'_>) {
899 let host = builder.sess.host_target;
900 let target = self.target;
901 let stage = builder.top_stage;
902
903 let compilers = RustcPrivateCompilers::new(builder, stage, host);
905 let miri = builder.ensure(tool::Miri::from_compilers(compilers));
906 let target_compiler = compilers.target_compiler();
907
908 let miri_sysroot = Miri::build_miri_sysroot(builder, target_compiler, target);
909 builder.std(target_compiler, host);
910 let host_sysroot = builder.sysroot(target_compiler);
911
912 let mut cargo = tool::prepare_tool_cargo(
913 builder,
914 miri.build_compiler,
915 Mode::ToolRustcPrivate,
916 host,
917 Kind::Test,
918 "src/tools/miri/priroda",
919 SourceType::InTree,
920 &[],
921 );
922
923 cargo.add_rustc_lib_path(builder);
924
925 let mut cargo = prepare_cargo_test(cargo, &[], &[], host, builder);
926
927 cargo.env("MIRI_SYSROOT", &miri_sysroot);
928 cargo.env("MIRI_HOST_SYSROOT", &host_sysroot);
929 cargo.env("MIRI_TEST_TARGET", target.rustc_target_arg());
930
931 {
932 let _guard = builder.msg_test("priroda", target, target_compiler.stage);
933 let _time = helpers::timeit(builder);
934 cargo.run(builder);
935 }
936 }
937}
938
939#[derive(Debug, Clone, PartialEq, Eq, Hash)]
940pub struct CompiletestTest {
941 host: TargetSelection,
942}
943
944impl CommandLineStep for CompiletestTest {
945 type Output = ();
946
947 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
948 run.path("src/tools/compiletest")
949 }
950
951 fn make_run(run: RunConfig<'_>) {
952 run.builder.ensure(CompiletestTest { host: run.target });
953 }
954
955 fn run(self, builder: &Builder<'_>) {
957 let host = self.host;
958 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
959
960 if builder.top_stage == 0 && !builder.config.compiletest_allow_stage0 {
966 eprintln!("\
967ERROR: `--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
968NOTE: 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`."
969 );
970 helpers::exit_process(1);
971 }
972
973 let bootstrap_compiler = builder.compiler(0, host);
974 let staged_compiler = builder.compiler(builder.top_stage, host);
975
976 let mut cargo = tool::prepare_tool_cargo(
977 builder,
978 bootstrap_compiler,
979 Mode::ToolBootstrap,
980 host,
981 Kind::Test,
982 "src/tools/compiletest",
983 SourceType::InTree,
984 &[],
985 );
986
987 cargo.env("TEST_RUSTC", builder.rustc(staged_compiler));
991
992 run_cargo_test(
993 cargo,
994 &[],
995 &[],
996 "compiletest self test",
997 host,
998 builder,
999 record_failed_tests,
1000 );
1001 }
1002}
1003
1004#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1008pub struct StdarchVerify;
1009
1010impl CommandLineStep for StdarchVerify {
1011 type Output = ();
1012 const IS_HOST: bool = true;
1013
1014 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1015 run.path("library/stdarch/crates/stdarch-verify")
1016 }
1017
1018 fn is_default_step(_builder: &Builder<'_>) -> bool {
1019 true
1020 }
1021
1022 fn make_run(run: RunConfig<'_>) {
1023 let builder = run.builder;
1024 if builder.remote_tested(run.target) {
1025 builder.info("remote testing is not supported by stdarch-verify. skipping");
1026 return;
1027 }
1028 builder.ensure(StdarchVerify);
1029 }
1030
1031 fn run(self, builder: &Builder<'_>) {
1032 let host = builder.config.host_target;
1033 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
1034 let build_compiler = builder.compiler(0, host);
1035
1036 let cargo = tool::prepare_tool_cargo(
1037 builder,
1038 build_compiler,
1039 Mode::ToolBootstrap,
1040 host,
1041 Kind::Test,
1042 "library/stdarch/crates/stdarch-verify",
1043 SourceType::InTree,
1044 &[],
1045 );
1046
1047 run_cargo_test(
1048 cargo,
1049 &[],
1050 &["stdarch-verify".to_string()],
1051 Some("stdarch-verify"),
1052 host,
1053 builder,
1054 record_failed_tests,
1055 );
1056 }
1057}
1058
1059#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1069pub struct IntrinsicTest {
1070 host: TargetSelection,
1071}
1072
1073impl CommandLineStep for IntrinsicTest {
1074 type Output = ();
1075 const IS_HOST: bool = true;
1076
1077 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1078 run.alias("intrinsic-test")
1079 }
1080
1081 fn is_default_step(_builder: &Builder<'_>) -> bool {
1082 true
1083 }
1084
1085 fn make_run(run: RunConfig<'_>) {
1086 let target = run.target;
1087 let builder = run.builder;
1088
1089 let is_explicit =
1090 builder.config.paths.iter().any(|p| p.to_string_lossy() == "intrinsic-test");
1091
1092 if target.contains("x86_64-unknown-linux") && builder.config.sde.is_none() && is_explicit {
1093 panic!(
1094 "SDE is required to run intrinsic-test. Please configure `build.sde` in config.toml."
1095 );
1096 }
1097
1098 builder.ensure(IntrinsicTest { host: target });
1099 }
1100
1101 fn run(self, builder: &Builder<'_>) {
1102 let host = self.host;
1103 if cfg!(test)
1104 || (!host.contains("aarch64-unknown-linux") && !host.contains("x86_64-unknown-linux"))
1105 {
1106 builder.info(&format!("Skipping intrinsic-test, as it is not available for {host}"));
1107 return;
1108 }
1109 let Some(rustfmt_path) = builder.ensure(InternalRustfmt) else {
1112 eprintln!(
1113 "WARNING: intrinsic-test skipped because rustfmt is required but not available on this channel"
1114 );
1115 return;
1116 };
1117
1118 let (input_file, skip_file, cflags, sde_runner) = if host.contains("x86_64-unknown-linux") {
1119 let Some(sde) = &builder.config.sde else {
1120 builder.info("Skipping intrinsic-test because `build.sde` is not configured");
1121 return;
1122 };
1123
1124 let cpuid_def =
1125 builder.src.join("library/stdarch/ci/docker/x86_64-unknown-linux-gnu/cpuid.def");
1126 let sde_runner = format!(
1127 "{} -cpuid-in {} -rtm-mode full -tsx --",
1128 sde.display(),
1129 cpuid_def.display()
1130 );
1131
1132 (
1133 builder.src.join("library/stdarch/intrinsics_data/x86-intel.xml"),
1134 [
1135 builder
1136 .src
1137 .join("library/stdarch/crates/intrinsic-test/missing_x86_common.txt"),
1138 builder.src.join("library/stdarch/crates/intrinsic-test/missing_x86_gcc.txt"),
1139 ],
1140 "-I/usr/include/x86_64-linux-gnu/",
1141 Some(sde_runner),
1142 )
1143 } else if host.contains("aarch64-unknown-linux") {
1144 (
1145 builder.src.join("library/stdarch/intrinsics_data/arm_intrinsics.json"),
1146 [
1147 builder
1148 .src
1149 .join("library/stdarch/crates/intrinsic-test/missing_aarch64_common.txt"),
1150 builder
1151 .src
1152 .join("library/stdarch/crates/intrinsic-test/missing_aarch64_gcc.txt"),
1153 ],
1154 "-I/usr/aarch64-linux-gnu/include/",
1155 None,
1156 )
1157 } else {
1158 panic!("intrinsic-test only supports aarch64/x86_64 Linux, got {host}");
1159 };
1160
1161 let out_dir = builder.out.join(host).join("intrinsic-test");
1162 t!(fs::create_dir_all(&out_dir));
1163
1164 let crates_link = out_dir.join("crates");
1165 if !crates_link.exists() {
1166 t!(
1167 helpers::symlink_dir(
1168 &builder.config,
1169 &builder.src.join("library/stdarch/crates"),
1170 &crates_link
1171 ),
1172 format!("failed to symlink stdarch crates into {}", crates_link.display())
1173 );
1174 }
1175
1176 let mut cmd = builder.tool_cmd(Tool::IntrinsicTest);
1177 cmd.current_dir(&out_dir);
1178 cmd.arg(&input_file);
1179 cmd.arg("--target").arg(&*host.triple);
1180 for skip in &skip_file {
1181 cmd.arg("--skip").arg(skip);
1182 }
1183 cmd.arg("--sample-percentage").arg("100");
1184 cmd.arg("--cc-arg-style").arg("gcc");
1185 cmd.env("CC", builder.cc(host));
1186 cmd.env("CFLAGS", cflags);
1187
1188 let mut path_dirs: Vec<PathBuf> = Vec::new();
1189 if let Some(cargo_dir) = builder.initial_cargo.parent() {
1190 path_dirs.push(cargo_dir.to_path_buf());
1191 }
1192 if let Some(rustfmt_dir) = rustfmt_path.parent() {
1193 path_dirs.push(rustfmt_dir.to_path_buf());
1194 }
1195 let old_path = env::var_os("PATH").unwrap_or_default();
1196 let new_path = env::join_paths(path_dirs.into_iter().chain(env::split_paths(&old_path)))
1197 .expect("could not build PATH for intrinsic-test");
1198 cmd.env("PATH", new_path);
1199 cmd.run(builder);
1200
1201 let tested_compiler = builder.compiler(builder.top_stage, host);
1202 builder.std(tested_compiler, host);
1203 let rustc = builder.rustc(tested_compiler);
1204
1205 let manifest = out_dir.join("rust_programs/Cargo.toml");
1206 let mut cargo = command(&builder.initial_cargo);
1207 cargo.arg("test");
1208 cargo.arg("--tests");
1209 cargo.arg("--manifest-path").arg(&manifest);
1210 cargo.arg("--target").arg(&*host.triple);
1211 cargo.arg("--profile").arg("release");
1212 cargo.env("CC", builder.cc(host));
1213 cargo.env("CFLAGS", cflags);
1214 cargo.env("RUSTC", rustc);
1215 cargo.env("RUSTC_BOOTSTRAP", "1");
1216 if let Some(runner) = sde_runner {
1217 cargo.env("CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER", runner);
1218 }
1219 cargo.run(builder);
1220 }
1221
1222 fn metadata(&self) -> Option<StepMetadata> {
1223 Some(StepMetadata::test("intrinsic-test", self.host))
1224 }
1225}
1226
1227#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1231pub struct StdarchGenCheck {
1232 host: TargetSelection,
1233}
1234
1235impl CommandLineStep for StdarchGenCheck {
1236 type Output = ();
1237 const IS_HOST: bool = true;
1238
1239 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1240 run.alias("stdarch-gen-check")
1241 }
1242
1243 fn is_default_step(_builder: &Builder<'_>) -> bool {
1244 true
1245 }
1246
1247 fn make_run(run: RunConfig<'_>) {
1248 run.builder.ensure(StdarchGenCheck { host: run.target });
1249 }
1250
1251 fn run(self, builder: &Builder<'_>) {
1252 let stdarch_root = builder.src.join("library/stdarch");
1253
1254 let mode = if builder.config.cmd.bless() { "bless" } else { "check" };
1256
1257 let Some(rustfmt_path) = builder.ensure(InternalRustfmt) else {
1259 eprintln!(
1260 "WARNING: stdarch-gen-check skipped because rustfmt is required but not available on this channel"
1261 );
1262 return;
1263 };
1264
1265 let cargo_target_dir = builder.out.join("stdarch-gen-check").join("target");
1267
1268 let manifest = stdarch_root.join("Cargo.toml");
1269 let arm_spec = stdarch_root.join("crates/stdarch-gen-arm/spec");
1270 let core_arch_src = stdarch_root.join("crates/core_arch/src");
1271
1272 let run_gen = |selector: &str, pkg: &str, args: &[&OsStr]| {
1275 let mut cmd = command(&builder.initial_cargo);
1276 cmd.current_dir(&builder.src);
1280 cmd.arg("run")
1281 .arg("--manifest-path")
1282 .arg(&manifest)
1283 .arg(selector)
1284 .arg(pkg)
1285 .arg("--release")
1286 .arg("--")
1287 .args(args)
1288 .arg("--rustfmt-path")
1289 .arg(&rustfmt_path);
1290 cmd.env("RUSTC_BOOTSTRAP", "1");
1292 cmd.env("RUSTC", &builder.initial_rustc);
1293 cmd.env("CARGO_TARGET_DIR", &cargo_target_dir);
1294 cmd.env("STDARCH_GEN_MODE", mode);
1295 cmd.run(builder);
1296 };
1297
1298 run_gen("--bin", "stdarch-gen-arm", &[arm_spec.as_os_str(), core_arch_src.as_os_str()]);
1299 run_gen("-p", "stdarch-gen-loongarch", &[OsStr::new("lsx")]);
1300 run_gen("-p", "stdarch-gen-loongarch", &[OsStr::new("lasx")]);
1301 run_gen("-p", "stdarch-gen-hexagon", &[]);
1302 }
1303}
1304
1305#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1306pub struct Clippy {
1307 compilers: RustcPrivateCompilers,
1308}
1309
1310impl CommandLineStep for Clippy {
1311 type Output = ();
1312 const IS_HOST: bool = true;
1313
1314 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1315 run.suite_path("src/tools/clippy/tests").path("src/tools/clippy")
1316 }
1317
1318 fn is_default_step(_builder: &Builder<'_>) -> bool {
1319 false
1320 }
1321
1322 fn make_run(run: RunConfig<'_>) {
1323 run.builder.ensure(Clippy {
1324 compilers: RustcPrivateCompilers::new(
1325 run.builder,
1326 run.builder.top_stage,
1327 run.builder.host_target,
1328 ),
1329 });
1330 }
1331
1332 fn run(self, builder: &Builder<'_>) {
1334 let target = self.compilers.target();
1335
1336 let target_compiler = self.compilers.target_compiler();
1340 let build_compiler = self.compilers.build_compiler();
1341
1342 builder.ensure(compile::Rustc::new(build_compiler, target));
1346
1347 let mut cargo = tool::prepare_tool_cargo(
1348 builder,
1349 build_compiler,
1350 Mode::ToolRustcPrivate,
1351 target,
1352 Kind::Test,
1353 "src/tools/clippy",
1354 SourceType::InTree,
1355 &[],
1356 );
1357
1358 cargo.env("RUSTC_TEST_SUITE", builder.rustc(build_compiler));
1359 cargo.env("RUSTC_LIB_PATH", builder.rustc_libdir(build_compiler));
1360 let host_libs = builder
1361 .stage_out(build_compiler, Mode::ToolRustcPrivate)
1362 .join(builder.cargo_dir(Mode::ToolRustcPrivate));
1363 cargo.env("HOST_LIBS", host_libs);
1364
1365 builder.std(target_compiler, target);
1367 cargo.env("TEST_SYSROOT", builder.sysroot(target_compiler));
1368 cargo.env("TEST_RUSTC", builder.rustc(target_compiler));
1369 cargo.env("TEST_RUSTC_LIB", builder.rustc_libdir(target_compiler));
1370
1371 'partially_test: {
1373 let paths = &builder.config.paths[..];
1374 let mut test_names = Vec::new();
1375 for path in paths {
1376 match helpers::is_valid_test_suite_arg(path, "src/tools/clippy/tests", builder) {
1377 TestFilterCategory::Arg(path) => {
1378 test_names.push(path);
1379 }
1380 TestFilterCategory::Fullsuite => {
1381 break 'partially_test;
1383 }
1384 TestFilterCategory::Uninteresting => {}
1385 }
1386 }
1387 cargo.env("TESTNAME", test_names.join(","));
1388 }
1389
1390 cargo.add_rustc_lib_path(builder);
1391 let cargo = prepare_cargo_test(cargo, &[], &[], target, builder);
1392
1393 let _guard = builder.msg_test("clippy", target, target_compiler.stage);
1394
1395 if cargo.allow_failure().run(builder) {
1397 return;
1399 }
1400
1401 if !builder.config.cmd.bless() {
1402 helpers::exit_process(1);
1403 }
1404 }
1405
1406 fn metadata(&self) -> Option<StepMetadata> {
1407 Some(
1408 StepMetadata::test("clippy", self.compilers.target())
1409 .built_by(self.compilers.build_compiler()),
1410 )
1411 }
1412}
1413
1414fn bin_path_for_cargo(builder: &Builder<'_>, compiler: Compiler) -> OsString {
1415 let path = builder.sysroot(compiler).join("bin");
1416 let old_path = env::var_os("PATH").unwrap_or_default();
1417 env::join_paths(iter::once(path).chain(env::split_paths(&old_path))).expect("")
1418}
1419
1420#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1422pub struct RustdocTheme {
1423 test_compiler: Compiler,
1425}
1426
1427impl CommandLineStep for RustdocTheme {
1428 type Output = ();
1429 const IS_HOST: bool = true;
1430
1431 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1432 run.path("src/tools/rustdoc-themes")
1433 }
1434
1435 fn is_default_step(_builder: &Builder<'_>) -> bool {
1436 true
1437 }
1438
1439 fn make_run(run: RunConfig<'_>) {
1440 let test_compiler = run.builder.compiler(run.builder.top_stage, run.target);
1441
1442 run.builder.ensure(RustdocTheme { test_compiler });
1443 }
1444
1445 fn run(self, builder: &Builder<'_>) {
1446 let rustdoc = builder.bootstrap_out.join("rustdoc");
1447 let mut cmd = builder.tool_cmd(Tool::RustdocTheme);
1448 cmd.arg(rustdoc.to_str().unwrap())
1449 .arg(builder.src.join("src/librustdoc/html/static/css/rustdoc.css").to_str().unwrap())
1450 .env("RUSTC_STAGE", self.test_compiler.stage.to_string())
1451 .env("RUSTC_SYSROOT", builder.sysroot(self.test_compiler))
1452 .env(
1453 "RUSTDOC_LIBDIR",
1454 builder.sysroot_target_libdir(self.test_compiler, self.test_compiler.host),
1455 )
1456 .env("CFG_RELEASE_CHANNEL", &builder.config.channel)
1457 .env("RUSTDOC_REAL", builder.rustdoc_for_compiler(self.test_compiler))
1458 .env("RUSTC_BOOTSTRAP", "1");
1459 cmd.args(linker_args(builder, self.test_compiler.host, LldThreads::No));
1460
1461 cmd.delay_failure().run(builder);
1462 }
1463
1464 fn metadata(&self) -> Option<StepMetadata> {
1465 Some(
1466 StepMetadata::test("rustdoc-theme", self.test_compiler.host)
1467 .stage(self.test_compiler.stage),
1468 )
1469 }
1470}
1471
1472#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1474pub struct RustdocJSStd {
1475 build_compiler: Compiler,
1477 target: TargetSelection,
1478}
1479
1480impl CommandLineStep for RustdocJSStd {
1481 type Output = ();
1482 const IS_HOST: bool = true;
1483
1484 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1485 run.suite_path("tests/rustdoc-js-std")
1486 }
1487
1488 fn is_default_step(builder: &Builder<'_>) -> bool {
1489 builder.config.nodejs.is_some()
1490 }
1491
1492 fn make_run(run: RunConfig<'_>) {
1493 run.builder.ensure(RustdocJSStd {
1494 build_compiler: run.builder.compiler(run.builder.top_stage, run.builder.host_target),
1495 target: run.target,
1496 });
1497 }
1498
1499 fn run(self, builder: &Builder<'_>) {
1500 let nodejs =
1501 builder.config.nodejs.as_ref().expect("need nodejs to run rustdoc-js-std tests");
1502 let mut command = command(nodejs);
1503 command
1504 .arg(builder.src.join("src/tools/rustdoc-js/tester.js"))
1505 .arg("--crate-name")
1506 .arg("std")
1507 .arg("--resource-suffix")
1508 .arg(&builder.version)
1509 .arg("--doc-folder")
1510 .arg(builder.doc_out(self.target))
1511 .arg("--test-folder")
1512 .arg(builder.src.join("tests/rustdoc-js-std"));
1513
1514 let full_suite = builder.paths.iter().any(|path| {
1515 matches!(
1516 helpers::is_valid_test_suite_arg(path, "tests/rustdoc-js-std", builder),
1517 TestFilterCategory::Fullsuite
1518 )
1519 });
1520
1521 if !full_suite {
1524 for path in &builder.paths {
1525 if let TestFilterCategory::Arg(p) =
1526 helpers::is_valid_test_suite_arg(path, "tests/rustdoc-js-std", builder)
1527 {
1528 if !p.ends_with(".js") {
1529 eprintln!("A non-js file was given: `{}`", path.display());
1530 panic!("Cannot run rustdoc-js-std tests");
1531 }
1532 command.arg("--test-file").arg(path);
1533 }
1534 }
1535 }
1536
1537 builder.ensure(crate::core::build_steps::doc::Std::from_build_compiler(
1538 self.build_compiler,
1539 self.target,
1540 DocumentationFormat::Html,
1541 ));
1542 let _guard = builder.msg_test("rustdoc-js-std", self.target, self.build_compiler.stage);
1543 command.run(builder);
1544 }
1545
1546 fn metadata(&self) -> Option<StepMetadata> {
1547 Some(StepMetadata::test("rustdoc-js-std", self.target).stage(self.build_compiler.stage))
1548 }
1549}
1550
1551#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1552pub struct RustdocJSNotStd {
1553 pub target: TargetSelection,
1554 pub compiler: Compiler,
1555}
1556
1557impl CommandLineStep for RustdocJSNotStd {
1558 type Output = ();
1559 const IS_HOST: bool = true;
1560
1561 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1562 run.suite_path("tests/rustdoc-js")
1563 }
1564
1565 fn is_default_step(builder: &Builder<'_>) -> bool {
1566 builder.config.nodejs.is_some()
1567 }
1568
1569 fn make_run(run: RunConfig<'_>) {
1570 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1571 run.builder.ensure(RustdocJSNotStd { target: run.target, compiler });
1572 }
1573
1574 fn run(self, builder: &Builder<'_>) {
1575 builder.ensure(Compiletest {
1576 test_compiler: self.compiler,
1577 target: self.target,
1578 mode: CompiletestMode::RustdocJs,
1579 suite: "rustdoc-js",
1580 path: "tests/rustdoc-js",
1581 compare_mode: None,
1582 });
1583 }
1584}
1585
1586fn get_browser_ui_test_version_inner(
1587 builder: &Builder<'_>,
1588 yarn: &Path,
1589 global: bool,
1590) -> Option<String> {
1591 let mut command = command(yarn);
1592 command
1593 .arg("--cwd")
1594 .arg(&builder.sess.out)
1595 .arg("list")
1596 .arg("--parseable")
1597 .arg("--long")
1598 .arg("--depth=0");
1599 if global {
1600 command.arg("--global");
1601 }
1602 let lines = command.allow_failure().cached().run_capture(builder).stdout();
1605 lines
1606 .lines()
1607 .find_map(|l| l.split(':').nth(1)?.strip_prefix("browser-ui-test@"))
1608 .map(|v| v.to_owned())
1609}
1610
1611fn get_browser_ui_test_version(builder: &Builder<'_>) -> Option<String> {
1612 let yarn = builder.config.yarn.as_deref()?;
1613 get_browser_ui_test_version_inner(builder, yarn, false)
1614 .or_else(|| get_browser_ui_test_version_inner(builder, yarn, true))
1615}
1616
1617#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1619pub struct RustdocGUI {
1620 test_compiler: Compiler,
1622 target: TargetSelection,
1623}
1624
1625impl CommandLineStep for RustdocGUI {
1626 type Output = ();
1627 const IS_HOST: bool = true;
1628
1629 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1630 run.suite_path("tests/rustdoc-gui")
1631 }
1632
1633 fn is_default_step(builder: &Builder<'_>) -> bool {
1634 builder.config.nodejs.is_some()
1635 && builder.test_target != TestTarget::DocOnly
1636 && get_browser_ui_test_version(builder).is_some()
1637 }
1638
1639 fn make_run(run: RunConfig<'_>) {
1640 let test_compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1641 run.builder.ensure(RustdocGUI { test_compiler, target: run.target });
1642 }
1643
1644 fn run(self, builder: &Builder<'_>) {
1645 builder.std(self.test_compiler, self.target);
1646 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
1647
1648 let mut cmd = builder.tool_cmd(Tool::RustdocGUITest);
1649
1650 let out_dir = builder.out.join(self.target).join("test").join("rustdoc-gui");
1651 build_stamp::clear_if_dirty(
1652 builder,
1653 &out_dir,
1654 &builder.rustdoc_for_compiler(self.test_compiler),
1655 );
1656
1657 if let Some(src) = builder.config.src.to_str() {
1658 cmd.arg("--rust-src").arg(src);
1659 }
1660
1661 if let Some(out_dir) = out_dir.to_str() {
1662 cmd.arg("--out-dir").arg(out_dir);
1663 }
1664
1665 if let Some(initial_cargo) = builder.sess.initial_cargo.to_str() {
1666 cmd.arg("--initial-cargo").arg(initial_cargo);
1667 }
1668
1669 cmd.arg("--jobs").arg(builder.jobs().to_string());
1670
1671 cmd.env("RUSTDOC", builder.rustdoc_for_compiler(self.test_compiler))
1672 .env("RUSTC", builder.rustc(self.test_compiler));
1673
1674 add_rustdoc_cargo_linker_args(&mut cmd, builder, self.test_compiler.host, LldThreads::No);
1675
1676 let full_suite = builder.paths.iter().any(|path| {
1677 matches!(
1678 helpers::is_valid_test_suite_arg(path, "tests/rustdoc-js-std", builder),
1679 TestFilterCategory::Fullsuite
1680 )
1681 });
1682
1683 if !full_suite {
1686 for path in &builder.paths {
1687 if let TestFilterCategory::Arg(p) =
1688 helpers::is_valid_test_suite_arg(path, "tests/rustdoc-gui", builder)
1689 {
1690 if !p.ends_with(".goml") {
1691 eprintln!("A non-goml file was given: `{}`", path.display());
1692 panic!("Cannot run rustdoc-gui tests");
1693 }
1694 if let Some(name) = path.file_name().and_then(|f| f.to_str()) {
1695 cmd.arg("--goml-file").arg(name);
1696 }
1697 }
1698 }
1699 }
1700
1701 for test_arg in builder.config.test_args() {
1702 cmd.arg("--test-arg").arg(test_arg);
1703 }
1704
1705 if let Some(ref nodejs) = builder.config.nodejs {
1706 cmd.arg("--nodejs").arg(nodejs);
1707 }
1708
1709 if let Some(ref yarn) = builder.config.yarn {
1710 cmd.arg("--yarn").arg(yarn);
1711 }
1712
1713 let _time = helpers::timeit(builder);
1714 let _guard = builder.msg_test("rustdoc-gui", self.target, self.test_compiler.stage);
1715 try_run_tests(builder, &mut cmd, true, record_failed_tests);
1716 }
1717
1718 fn metadata(&self) -> Option<StepMetadata> {
1719 Some(StepMetadata::test("rustdoc-gui", self.target).stage(self.test_compiler.stage))
1720 }
1721}
1722
1723#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1728pub struct Tidy;
1729
1730impl CommandLineStep for Tidy {
1731 type Output = ();
1732 const IS_HOST: bool = true;
1733
1734 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1735 run.path("src/tools/tidy")
1736 }
1737
1738 fn is_default_step(builder: &Builder<'_>) -> bool {
1739 builder.test_target != TestTarget::DocOnly
1740 }
1741
1742 fn make_run(run: RunConfig<'_>) {
1743 run.builder.ensure(Tidy);
1744 }
1745
1746 fn run(self, builder: &Builder<'_>) {
1755 let mut cmd = builder.tool_cmd(Tool::Tidy);
1756 cmd.arg(format!("--root-path={}", builder.src.display()));
1757 cmd.arg(format!("--cargo-path={}", builder.initial_cargo.display()));
1758 cmd.arg(format!("--output-dir={}", builder.out.display()));
1759 let jobs = builder.config.jobs.unwrap_or_else(|| {
1761 8 * std::thread::available_parallelism().map_or(1, std::num::NonZeroUsize::get) as u32
1762 });
1763 cmd.arg(format!("--concurrency={jobs}"));
1764 if let Some(yarn) = &builder.config.yarn {
1766 cmd.arg(format!("--npm-path={}", yarn.display()));
1767 } else {
1768 cmd.arg("--npm-path=yarn");
1769 }
1770 if builder.is_verbose() {
1771 cmd.arg("--verbose");
1772 }
1773 if builder.config.cmd.bless() {
1774 cmd.arg("--bless");
1775 }
1776 if builder.config.is_running_on_ci() {
1777 cmd.arg("--ci=true");
1778 }
1779 if let Some(s) =
1780 builder.config.cmd.extra_checks().or(builder.config.tidy_extra_checks.as_deref())
1781 {
1782 cmd.arg(format!("--extra-checks={s}"));
1783 }
1784 let mut args = std::env::args_os();
1785 if args.any(|arg| arg == OsStr::new("--")) {
1786 cmd.arg("--");
1787 cmd.args(args);
1788 }
1789
1790 if builder.config.channel == "dev" || builder.config.channel == "nightly" {
1791 if !builder.config.json_output {
1792 builder.info("fmt check");
1793
1794 let Some(rustfmt) = builder.ensure(InternalRustfmt) else {
1797 let inferred_rustfmt_dir = builder.initial_sysroot.join("bin");
1798 eprintln!(
1799 "\
1800ERROR: no `rustfmt` binary found in {PATH}
1801INFO: `rust.channel` is currently set to \"{CHAN}\"
1802HELP: if you are testing a beta branch, set `rust.channel` to \"beta\" in the `bootstrap.toml` file
1803HELP: to skip test's attempt to check tidiness, pass `--skip src/tools/tidy` to `x.py test`",
1804 PATH = inferred_rustfmt_dir.display(),
1805 CHAN = builder.config.channel,
1806 );
1807 helpers::exit_process(1);
1808 };
1809 let all = false;
1810 crate::core::build_steps::format::format(
1811 builder,
1812 rustfmt,
1813 !builder.config.cmd.bless(),
1814 all,
1815 &[],
1816 );
1817 } else {
1818 eprintln!(
1819 "WARNING: `--json-output` is not supported on rustfmt, formatting will be skipped"
1820 );
1821 }
1822 }
1823
1824 builder.info("tidy check");
1825 let ctx = builder.as_ref();
1826 let mut cmd = cmd.delay_failure();
1827 let tidy = cmd.start(ctx);
1829
1830 builder.info("x.py completions check");
1831 let completion_paths = get_completion_paths(builder);
1832 if builder.config.cmd.bless() {
1833 builder.ensure(crate::core::build_steps::run::GenerateCompletions);
1834 } else if completion_paths
1835 .into_iter()
1836 .any(|(shell, path)| get_completion(shell, &path).is_some())
1837 {
1838 eprintln!(
1839 "x.py completions were changed; run `x.py run generate-completions` to update them"
1840 );
1841 helpers::exit_process(1);
1842 }
1843
1844 tidy.wait_for_output(ctx);
1846
1847 builder.info("x.py help check");
1848 if builder.config.cmd.bless() {
1849 builder.ensure(crate::core::build_steps::run::GenerateHelp);
1850 } else {
1851 let help_path = get_help_path(builder);
1852 let cur_help = std::fs::read_to_string(&help_path).unwrap_or_else(|err| {
1853 eprintln!("couldn't read {}: {}", help_path.display(), err);
1854 helpers::exit_process(1);
1855 });
1856 let new_help = top_level_help();
1857
1858 if new_help != cur_help {
1859 eprintln!("x.py help was changed; run `x.py run generate-help` to update it");
1860 helpers::exit_process(1);
1861 }
1862 }
1863 }
1864
1865 fn metadata(&self) -> Option<StepMetadata> {
1866 Some(StepMetadata::test("tidy", TargetSelection::default()))
1867 }
1868}
1869
1870#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1873pub struct CrateRunMakeSupport {
1874 host: TargetSelection,
1875}
1876
1877impl CommandLineStep for CrateRunMakeSupport {
1878 type Output = ();
1879 const IS_HOST: bool = true;
1880
1881 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1882 run.path("src/tools/run-make-support")
1883 }
1884
1885 fn make_run(run: RunConfig<'_>) {
1886 run.builder.ensure(CrateRunMakeSupport { host: run.target });
1887 }
1888
1889 fn run(self, builder: &Builder<'_>) {
1891 let host = self.host;
1892 let compiler = builder.compiler(0, host);
1893 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
1894
1895 let mut cargo = tool::prepare_tool_cargo(
1896 builder,
1897 compiler,
1898 Mode::ToolBootstrap,
1899 host,
1900 Kind::Test,
1901 "src/tools/run-make-support",
1902 SourceType::InTree,
1903 &[],
1904 );
1905 cargo.allow_features("test");
1906 run_cargo_test(
1907 cargo,
1908 &[],
1909 &[],
1910 "run-make-support self test",
1911 host,
1912 builder,
1913 record_failed_tests,
1914 );
1915 }
1916}
1917
1918#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1919pub struct CrateBuildHelper {
1920 host: TargetSelection,
1921}
1922
1923impl CommandLineStep for CrateBuildHelper {
1924 type Output = ();
1925 const IS_HOST: bool = true;
1926
1927 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1928 run.path("src/build_helper")
1929 }
1930
1931 fn make_run(run: RunConfig<'_>) {
1932 run.builder.ensure(CrateBuildHelper { host: run.target });
1933 }
1934
1935 fn run(self, builder: &Builder<'_>) {
1937 let host = self.host;
1938 let compiler = builder.compiler(0, host);
1939 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
1940
1941 let mut cargo = tool::prepare_tool_cargo(
1942 builder,
1943 compiler,
1944 Mode::ToolBootstrap,
1945 host,
1946 Kind::Test,
1947 "src/build_helper",
1948 SourceType::InTree,
1949 &[],
1950 );
1951 cargo.allow_features("test");
1952 run_cargo_test(
1953 cargo,
1954 &[],
1955 &[],
1956 "build_helper self test",
1957 host,
1958 builder,
1959 record_failed_tests,
1960 );
1961 }
1962}
1963
1964fn testdir(builder: &Builder<'_>, host: TargetSelection) -> PathBuf {
1965 builder.out.join(host).join("test")
1966}
1967
1968macro_rules! test {
1970 (
1971 $( #[$attr:meta] )* $name:ident {
1973 path: $path:expr,
1974 mode: $mode:expr,
1975 suite: $suite:expr,
1976 default: $default:expr
1977 $( , IS_HOST: $IS_HOST:expr )? $( , compare_mode: $compare_mode:expr )? $( , )? }
1981 ) => {
1982 $( #[$attr] )*
1983 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
1984 pub struct $name {
1985 test_compiler: Compiler,
1986 target: TargetSelection,
1987 }
1988
1989 impl CommandLineStep for $name {
1990 type Output = ();
1991 const IS_HOST: bool = (const {
1992 #[allow(unused_assignments, unused_mut)]
1993 let mut value = false;
1994 $( value = $IS_HOST; )?
1995 value
1996 });
1997
1998 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1999 run.suite_path($path)
2000 }
2001
2002 fn is_default_step(_builder: &Builder<'_>) -> bool {
2003 const { $default }
2004 }
2005
2006 fn make_run(run: RunConfig<'_>) {
2007 let test_compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
2008
2009 run.builder.ensure($name { test_compiler, target: run.target });
2010 }
2011
2012 fn run(self, builder: &Builder<'_>) {
2013 builder.ensure(Compiletest {
2014 test_compiler: self.test_compiler,
2015 target: self.target,
2016 mode: const { $mode },
2017 suite: $suite,
2018 path: $path,
2019 compare_mode: (const {
2020 #[allow(unused_assignments, unused_mut)]
2021 let mut value = None;
2022 $( value = $compare_mode; )?
2023 value
2024 }),
2025 })
2026 }
2027 }
2028 };
2029}
2030
2031test!(Ui { path: "tests/ui", mode: CompiletestMode::Ui, suite: "ui", default: true });
2032
2033test!(Crashes {
2034 path: "tests/crashes",
2035 mode: CompiletestMode::Crashes,
2036 suite: "crashes",
2037 default: true,
2038});
2039
2040test!(CodegenLlvm {
2041 path: "tests/codegen-llvm",
2042 mode: CompiletestMode::Codegen,
2043 suite: "codegen-llvm",
2044 default: true
2045});
2046
2047test!(CodegenUnits {
2048 path: "tests/codegen-units",
2049 mode: CompiletestMode::CodegenUnits,
2050 suite: "codegen-units",
2051 default: true,
2052});
2053
2054test!(Incremental {
2055 path: "tests/incremental",
2056 mode: CompiletestMode::Incremental,
2057 suite: "incremental",
2058 default: true,
2059});
2060
2061test!(Debuginfo {
2062 path: "tests/debuginfo",
2063 mode: CompiletestMode::Debuginfo,
2064 suite: "debuginfo",
2065 default: true,
2066 compare_mode: Some("split-dwarf"),
2067});
2068
2069test!(UiFullDeps {
2070 path: "tests/ui-fulldeps",
2071 mode: CompiletestMode::Ui,
2072 suite: "ui-fulldeps",
2073 default: true,
2074 IS_HOST: true,
2075});
2076
2077test!(RustdocHtml {
2078 path: "tests/rustdoc-html",
2079 mode: CompiletestMode::RustdocHtml,
2080 suite: "rustdoc-html",
2081 default: true,
2082 IS_HOST: true,
2083});
2084test!(RustdocUi {
2085 path: "tests/rustdoc-ui",
2086 mode: CompiletestMode::Ui,
2087 suite: "rustdoc-ui",
2088 default: true,
2089 IS_HOST: true,
2090});
2091
2092test!(RustdocJson {
2093 path: "tests/rustdoc-json",
2094 mode: CompiletestMode::RustdocJson,
2095 suite: "rustdoc-json",
2096 default: true,
2097 IS_HOST: true,
2098});
2099
2100test!(Pretty {
2101 path: "tests/pretty",
2102 mode: CompiletestMode::Pretty,
2103 suite: "pretty",
2104 default: true,
2105 IS_HOST: true,
2106});
2107
2108test!(RunMake {
2109 path: "tests/run-make",
2110 mode: CompiletestMode::RunMake,
2111 suite: "run-make",
2112 default: true,
2113});
2114test!(RunMakeCargo {
2115 path: "tests/run-make-cargo",
2116 mode: CompiletestMode::RunMake,
2117 suite: "run-make-cargo",
2118 default: true
2119});
2120test!(BuildStd {
2121 path: "tests/build-std",
2122 mode: CompiletestMode::RunMake,
2123 suite: "build-std",
2124 default: false
2125});
2126
2127test!(AssemblyGcc {
2128 path: "tests/assembly-gcc",
2129 mode: CompiletestMode::Assembly,
2130 suite: "assembly-gcc",
2131 default: true
2132});
2133test!(AssemblyLlvm {
2134 path: "tests/assembly-llvm",
2135 mode: CompiletestMode::Assembly,
2136 suite: "assembly-llvm",
2137 default: true
2138});
2139
2140#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2143pub struct Coverage {
2144 pub compiler: Compiler,
2145 pub target: TargetSelection,
2146 pub(crate) mode: CompiletestMode,
2147}
2148
2149impl Coverage {
2150 const PATH: &'static str = "tests/coverage";
2151 const SUITE: &'static str = "coverage";
2152 const ALL_MODES: &[CompiletestMode] =
2153 &[CompiletestMode::CoverageMap, CompiletestMode::CoverageRun];
2154
2155 fn new(run: &RunConfig<'_>, mode: CompiletestMode) -> Self {
2156 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
2157 let target = run.target;
2158 Coverage { compiler, target, mode }
2159 }
2160}
2161
2162impl CommandLineStep for Coverage {
2163 type Output = ();
2164 const IS_HOST: bool = false;
2166
2167 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2168 run.suite_path(Coverage::PATH)
2175 }
2176
2177 fn is_default_step(_builder: &Builder<'_>) -> bool {
2178 true
2179 }
2180
2181 fn make_run(run: RunConfig<'_>) {
2182 for &mode in Coverage::ALL_MODES {
2186 if !run.builder.config.skip.iter().any(|skip| skip == Path::new(mode.as_str())) {
2187 run.builder.ensure(Coverage::new(&run, mode));
2188 }
2189 }
2190 }
2191
2192 fn run(self, builder: &Builder<'_>) {
2193 let Self { compiler, target, mode } = self;
2194 builder.ensure(Compiletest {
2197 test_compiler: compiler,
2198 target,
2199 mode,
2200 suite: Self::SUITE,
2201 path: Self::PATH,
2202 compare_mode: None,
2203 });
2204 }
2205}
2206
2207#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2215pub enum CoverageModeAlias {}
2216
2217impl CommandLineStep for CoverageModeAlias {
2218 type Output = ();
2219
2220 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2221 Coverage::ALL_MODES.iter().fold(run, |run, mode| run.alias(mode.as_str()))
2226 }
2227
2228 fn is_default_step(_builder: &Builder<'_>) -> bool {
2229 false
2230 }
2231
2232 fn make_run(run: RunConfig<'_>) {
2233 for path in &run.paths {
2234 let single_path = &path.assert_single_path().path;
2235 for &mode in Coverage::ALL_MODES {
2236 if single_path == Path::new(mode.as_str()) {
2237 run.builder.ensure(Coverage::new(&run, mode));
2240 }
2241 }
2242 }
2243 }
2244
2245 fn run(self, _builder: &Builder<'_>) {
2246 unreachable!("never instantiated; `make_run` creates a Coverage step instead");
2247 }
2248}
2249
2250test!(CoverageRunRustdoc {
2251 path: "tests/coverage-run-rustdoc",
2252 mode: CompiletestMode::CoverageRun,
2253 suite: "coverage-run-rustdoc",
2254 default: true,
2255 IS_HOST: true,
2256});
2257
2258#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2260pub struct MirOpt {
2261 pub compiler: Compiler,
2262 pub target: TargetSelection,
2263}
2264
2265impl CommandLineStep for MirOpt {
2266 type Output = ();
2267
2268 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2269 run.suite_path("tests/mir-opt")
2270 }
2271
2272 fn is_default_step(_builder: &Builder<'_>) -> bool {
2273 true
2274 }
2275
2276 fn make_run(run: RunConfig<'_>) {
2277 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
2278 run.builder.ensure(MirOpt { compiler, target: run.target });
2279 }
2280
2281 fn run(self, builder: &Builder<'_>) {
2282 let run = |target| {
2283 builder.ensure(Compiletest {
2284 test_compiler: self.compiler,
2285 target,
2286 mode: CompiletestMode::MirOpt,
2287 suite: "mir-opt",
2288 path: "tests/mir-opt",
2289 compare_mode: None,
2290 })
2291 };
2292
2293 run(self.target);
2294
2295 if builder.config.cmd.bless() {
2298 for target in ["aarch64-unknown-linux-gnu", "i686-pc-windows-msvc"] {
2304 run(TargetSelection::from_user(target));
2305 }
2306
2307 for target in ["x86_64-apple-darwin", "i686-unknown-linux-musl"] {
2308 let target = TargetSelection::from_user(target);
2309 let panic_abort_target = builder.ensure(MirOptPanicAbortSyntheticTarget {
2310 compiler: self.compiler,
2311 base: target,
2312 });
2313 run(panic_abort_target);
2314 }
2315 }
2316 }
2317}
2318
2319#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2325struct Compiletest {
2326 test_compiler: Compiler,
2328 target: TargetSelection,
2329 mode: CompiletestMode,
2330 suite: &'static str,
2331 path: &'static str,
2332 compare_mode: Option<&'static str>,
2333}
2334
2335impl Step for Compiletest {
2336 type Output = ();
2337
2338 fn run(self, builder: &Builder<'_>) {
2339 if builder.test_target == TestTarget::DocOnly {
2340 return;
2341 }
2342
2343 if builder.top_stage == 0 && !builder.config.compiletest_allow_stage0 {
2344 eprintln!("\
2345ERROR: `--stage 0` runs compiletest on the stage0 (precompiled) compiler, not your local changes, and will almost always cause tests to fail
2346HELP: to test the compiler or standard library, omit the stage or explicitly use `--stage 1` instead
2347NOTE: 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`."
2348 );
2349 helpers::exit_process(1);
2350 }
2351
2352 let mut test_compiler = self.test_compiler;
2353 let target = self.target;
2354 let mode = self.mode;
2355 let suite = self.suite;
2356 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
2357
2358 let suite_path = self.path;
2360
2361 if !builder.config.codegen_tests && mode == CompiletestMode::Codegen {
2363 return;
2364 }
2365
2366 let query_compiler;
2373 let (stage, stage_id) = if suite == "ui-fulldeps" && test_compiler.stage == 1 {
2374 builder.info("Warning: running ui-fulldeps tests in stage 1 might cause failures");
2375
2376 query_compiler = Some(test_compiler);
2379 let build = builder.sess.host_target;
2383 test_compiler = builder.compiler(test_compiler.stage - 1, build);
2384 let test_stage = test_compiler.stage + 1;
2385 (test_stage, format!("stage{test_stage}-{build}"))
2386 } else {
2387 query_compiler = None;
2388 let stage = test_compiler.stage;
2389 (stage, format!("stage{stage}-{target}"))
2390 };
2391
2392 if suite.ends_with("fulldeps") {
2393 builder.ensure(compile::Rustc::new(test_compiler, target));
2394 }
2395
2396 if builder.config.wasm_proc_macros {
2398 builder.ensure(compile::Std::new(
2399 test_compiler,
2400 TargetSelection::from_user("wasm32-wasip2"),
2401 ));
2402 }
2403
2404 if suite == "debuginfo" {
2405 builder.ensure(dist::DebuggerScripts {
2406 sysroot: builder.sysroot(test_compiler).to_path_buf(),
2407 target,
2408 });
2409 }
2410
2411 if suite == "mir-opt" {
2413 builder.ensure(
2414 compile::Std::new(test_compiler, test_compiler.host).is_for_mir_opt_tests(true),
2415 );
2416 } else {
2417 builder.std(test_compiler, test_compiler.host);
2418 }
2419
2420 let mut cmd = builder.tool_cmd(Tool::Compiletest);
2421
2422 if mode == CompiletestMode::RunMake {
2423 let output = builder.tool(Tool::RunMakeSupport);
2426 let find = |extension: &str| -> Option<&PathBuf> {
2427 output.artifacts.iter().find_map(|p| {
2428 let filename = p.file_name()?.to_str()?;
2433 if !filename.starts_with("librun_make_support") {
2434 return None;
2435 }
2436
2437 if extension == p.extension()? { Some(p) } else { None }
2438 })
2439 };
2440 if !builder.config.dry_run() {
2441 let rlib =
2442 find("rlib").expect(".rlib not found when compiling librun_make_support");
2443 cmd.arg("--run-make-support-rlib").arg(rlib);
2444
2445 if let Some(rmeta) = find("rmeta") {
2447 cmd.arg("--run-make-support-rmeta").arg(rmeta);
2448 }
2449 }
2450 }
2451
2452 if suite == "mir-opt" {
2453 builder.ensure(compile::Std::new(test_compiler, target).is_for_mir_opt_tests(true));
2454 } else {
2455 builder.std(test_compiler, target);
2456 }
2457
2458 builder.ensure(RemoteCopyLibs { build_compiler: test_compiler, target });
2459
2460 cmd.arg("--stage").arg(stage.to_string());
2464 cmd.arg("--stage-id").arg(stage_id);
2465
2466 cmd.arg("--compile-lib-path").arg(builder.rustc_libdir(test_compiler));
2467 cmd.arg("--run-lib-path").arg(builder.sysroot_target_libdir(test_compiler, target));
2468 cmd.arg("--rustc-path").arg(builder.rustc(test_compiler));
2469 if let Some(query_compiler) = query_compiler {
2470 cmd.arg("--query-rustc-path").arg(builder.rustc(query_compiler));
2471 cmd.arg("--query-rustc-lib-path").arg(builder.rustc_libdir(query_compiler));
2472 }
2473
2474 cmd.arg("--minicore-path")
2477 .arg(builder.src.join("tests").join("auxiliary").join("minicore.rs"));
2478
2479 let is_rustdoc = suite == "rustdoc-ui" || suite == "rustdoc-js";
2480
2481 if builder.config.wasm_proc_macros {
2482 cmd.arg("--wasm-proc-macros");
2483 }
2484
2485 if mode == CompiletestMode::RunMake {
2500 let stage0_rustc_path = builder.compiler(0, test_compiler.host);
2503 cmd.arg("--stage0-rustc-path").arg(builder.rustc(stage0_rustc_path));
2504
2505 if matches!(suite, "run-make-cargo" | "build-std") {
2506 let cargo_path = if test_compiler.stage == 0 {
2507 builder.initial_cargo.clone()
2509 } else {
2510 builder
2511 .ensure(tool::Cargo::from_build_compiler(
2512 builder.compiler(test_compiler.stage - 1, test_compiler.host),
2513 test_compiler.host,
2514 ))
2515 .tool_path
2516 };
2517
2518 cmd.arg("--cargo-path").arg(cargo_path);
2519 }
2520 }
2521
2522 if matches!(
2524 mode,
2525 CompiletestMode::RunMake
2526 | CompiletestMode::RustdocHtml
2527 | CompiletestMode::RustdocJs
2528 | CompiletestMode::RustdocJson
2529 ) || matches!(suite, "rustdoc-ui" | "coverage-run-rustdoc")
2530 {
2531 cmd.arg("--rustdoc-path").arg(builder.rustdoc_for_compiler(test_compiler));
2532 }
2533
2534 if mode == CompiletestMode::RustdocJson {
2535 let json_compiler = builder.compiler(0, builder.host_target);
2537 cmd.arg("--jsondocck-path")
2538 .arg(builder.ensure(tool::JsonDocCk { compiler: json_compiler, target }).tool_path);
2539 cmd.arg("--jsondoclint-path").arg(
2540 builder.ensure(tool::JsonDocLint { compiler: json_compiler, target }).tool_path,
2541 );
2542 }
2543
2544 if matches!(mode, CompiletestMode::CoverageMap | CompiletestMode::CoverageRun) {
2545 let coverage_dump = builder.tool_exe(Tool::CoverageDump);
2546 cmd.arg("--coverage-dump-path").arg(coverage_dump);
2547 }
2548
2549 cmd.arg("--src-root").arg(&builder.src);
2550 cmd.arg("--src-test-suite-root").arg(builder.src.join("tests").join(suite));
2551
2552 cmd.arg("--build-root").arg(&builder.out);
2556 cmd.arg("--build-test-suite-root").arg(testdir(builder, test_compiler.host).join(suite));
2557
2558 let sysroot = if builder.top_stage == 0 {
2563 builder.initial_sysroot.clone()
2564 } else {
2565 builder.sysroot(test_compiler)
2566 };
2567
2568 cmd.arg("--sysroot-base").arg(sysroot);
2569
2570 cmd.arg("--suite").arg(suite);
2571 cmd.arg("--mode").arg(mode.as_str());
2572 cmd.arg("--target").arg(target.rustc_target_arg());
2573 cmd.arg("--host").arg(&*test_compiler.host.triple);
2574
2575 let filecheck = builder.ensure(llvm::FileCheck { target: builder.config.host_target });
2576 cmd.arg("--llvm-filecheck").arg(filecheck);
2577
2578 if let Some(codegen_backend) = builder.config.cmd.test_codegen_backend() {
2579 if !builder
2580 .config
2581 .enabled_codegen_backends(test_compiler.host)
2582 .contains(codegen_backend)
2583 {
2584 eprintln!(
2585 "\
2586ERROR: No configured backend named `{name}`
2587HELP: You can add it into `bootstrap.toml` in `rust.codegen-backends = [{name:?}]`",
2588 name = codegen_backend.name(),
2589 );
2590 helpers::exit_process(1);
2591 }
2592
2593 if let CodegenBackendKind::Gcc = codegen_backend
2594 && builder.config.rustc_debug_assertions
2595 {
2596 eprintln!(
2597 r#"WARNING: Running tests with the GCC codegen backend while rustc debug assertions are enabled. This might lead to test failures.
2598Please disable assertions with `rust.debug-assertions = false`.
2599 "#
2600 );
2601 }
2602
2603 cmd.arg("--override-codegen-backend").arg(codegen_backend.name());
2606 cmd.arg("--default-codegen-backend").arg(codegen_backend.name());
2609 } else {
2610 cmd.arg("--default-codegen-backend")
2613 .arg(builder.config.default_codegen_backend(test_compiler.host).name());
2614 }
2615 if builder.config.cmd.bypass_ignore_backends() {
2616 cmd.arg("--bypass-ignore-backends");
2617 }
2618
2619 if builder.sess.config.llvm_enzyme {
2620 cmd.arg("--has-enzyme");
2621 }
2622
2623 if builder.sess.config.llvm_offload {
2624 cmd.arg("--has-offload");
2625 }
2626
2627 if builder.config.cmd.bless() {
2628 cmd.arg("--bless");
2629 }
2630
2631 if builder.config.cmd.force_rerun() {
2632 cmd.arg("--force-rerun");
2633 }
2634
2635 if builder.config.cmd.no_capture() {
2636 cmd.arg("--no-capture");
2637 }
2638
2639 let compare_mode =
2640 builder.config.cmd.compare_mode().or_else(|| {
2641 if builder.config.test_compare_mode { self.compare_mode } else { None }
2642 });
2643
2644 if let Some(ref pass) = builder.config.cmd.pass() {
2645 cmd.arg("--pass");
2646 cmd.arg(pass);
2647 }
2648
2649 if let Some(ref run) = builder.config.cmd.run() {
2650 cmd.arg("--run");
2651 cmd.arg(run);
2652 }
2653
2654 if let Some(ref nodejs) = builder.config.nodejs {
2655 cmd.arg("--nodejs").arg(nodejs);
2656 } else if mode == CompiletestMode::RustdocJs {
2657 panic!("need nodejs to run rustdoc-js suite");
2658 }
2659 if builder.config.rust_optimize_tests {
2660 cmd.arg("--optimize-tests");
2661 }
2662 if !builder.config.docs_minification {
2663 cmd.arg("--disable-minification");
2664 }
2665 if builder.config.rust_randomize_layout {
2666 cmd.arg("--rust-randomized-layout");
2667 }
2668 if builder.config.cmd.only_modified() {
2669 cmd.arg("--only-modified");
2670 }
2671 if let Some(compiletest_diff_tool) = &builder.config.compiletest_diff_tool {
2672 cmd.arg("--compiletest-diff-tool").arg(compiletest_diff_tool);
2673 }
2674
2675 let mut flags = if is_rustdoc { Vec::new() } else { vec!["-Crpath".to_string()] };
2676 flags.push(format!(
2677 "-Cdebuginfo={}",
2678 if mode == CompiletestMode::Codegen {
2679 if builder.config.rust_debuginfo_level_tests
2682 != crate::core::config::DebuginfoLevel::None
2683 {
2684 println!(
2685 "NOTE: ignoring `rust.debuginfo-level-tests={}` for codegen tests",
2686 builder.config.rust_debuginfo_level_tests
2687 );
2688 }
2689 crate::core::config::DebuginfoLevel::None
2690 } else {
2691 builder.config.rust_debuginfo_level_tests
2692 }
2693 ));
2694 flags.extend(builder.config.cmd.compiletest_rustc_args().iter().map(|s| s.to_string()));
2695
2696 if suite != "mir-opt" {
2697 if let Some(linker) = builder.linker(target) {
2698 cmd.arg("--target-linker").arg(linker);
2699 }
2700 if let Some(linker) = builder.linker(test_compiler.host) {
2701 cmd.arg("--host-linker").arg(linker);
2702 }
2703 }
2704
2705 if suite == "ui-fulldeps" && target.ends_with("darwin") {
2707 flags.push("-Alinker_messages".into());
2708 }
2709
2710 let mut hostflags = flags.clone();
2711 hostflags.extend(linker_flags(builder, test_compiler.host, LldThreads::No));
2712
2713 let mut targetflags = flags;
2714
2715 if suite == "ui" || suite == "incremental" {
2717 let host_test_helpers = builder.ensure(TestHelpers { target: test_compiler.host });
2718 let target_helpers = builder.ensure(TestHelpers { target });
2719 hostflags.push(format!("-Lnative={}", host_test_helpers.display()));
2720 targetflags.push(format!("-Lnative={}", target_helpers.display()));
2721 if target.is_pauthtest() {
2722 targetflags.push(format!("-Clink-arg=-Wl,-rpath,{}", target_helpers.display()));
2725 }
2726 }
2727
2728 for flag in hostflags {
2729 cmd.arg("--host-rustcflags").arg(flag);
2730 }
2731 for flag in targetflags {
2732 cmd.arg("--target-rustcflags").arg(flag);
2733 }
2734 if target.is_synthetic() {
2735 cmd.arg("--target-rustcflags").arg("-Zunstable-options");
2736 }
2737
2738 cmd.arg("--python").arg(
2739 builder.config.python.as_ref().expect("python is required for running rustdoc tests"),
2740 );
2741
2742 let android = android::discover_android(builder, target);
2744 if let Some(android::Android { adb_path, adb_test_dir, android_cross_path }) = &android {
2745 cmd.arg("--adb-path").arg(adb_path);
2746 cmd.arg("--adb-test-dir").arg(adb_test_dir);
2747 cmd.arg("--android-cross-path").arg(android_cross_path);
2748 }
2749
2750 if mode == CompiletestMode::Debuginfo {
2751 if let Some(debuggers::Cdb { cdb }) = debuggers::discover_cdb(target) {
2752 cmd.arg("--cdb").arg(cdb);
2753 }
2754
2755 if let Some(debuggers::Gdb { gdb }) = debuggers::discover_gdb(builder, android.as_ref())
2756 {
2757 cmd.arg("--gdb").arg(gdb);
2758 }
2759
2760 if let Some(debuggers::Lldb { lldb_exe, lldb_version }) =
2761 debuggers::discover_lldb(builder)
2762 {
2763 cmd.arg("--lldb").arg(lldb_exe);
2764 cmd.arg("--lldb-version").arg(lldb_version);
2765 }
2766 }
2767
2768 if helpers::forcing_clang_based_tests() {
2769 let llvm = builder.ensure(llvm::Llvm { target });
2770 let clang_exe = llvm.root_dir().join("bin").join("clang");
2771 cmd.arg("--run-clang-based-tests-with").arg(clang_exe);
2772 }
2773
2774 for exclude in &builder.config.skip {
2775 cmd.arg("--skip");
2776 cmd.arg(exclude);
2777 }
2778
2779 let mut paths = match &builder.config.cmd {
2781 Subcommand::Test { .. } => &builder.config.paths[..],
2782 _ => &[],
2783 };
2784
2785 let mut paths_v;
2788 if mode == CompiletestMode::RustdocJs {
2789 paths_v = paths.to_vec();
2790 for p in &mut paths_v {
2791 if let Some(ext) = p.extension()
2792 && ext == "js"
2793 {
2794 p.set_extension("rs");
2795 }
2796 }
2797 paths = &paths_v;
2798 }
2799
2800 let mut test_args = Vec::new();
2802 for p in paths {
2803 match helpers::is_valid_test_suite_arg(p, suite_path, builder) {
2804 TestFilterCategory::Fullsuite => {
2805 test_args.clear();
2810 break;
2811 }
2812 TestFilterCategory::Arg(a) => test_args.push(a),
2813 TestFilterCategory::Uninteresting => {}
2814 }
2815 }
2816
2817 test_args.append(&mut builder.config.test_args());
2818
2819 if cfg!(windows) {
2822 let test_args_win: Vec<String> =
2823 test_args.iter().map(|s| s.replace('/', "\\")).collect();
2824 cmd.args(&test_args_win);
2825 } else {
2826 cmd.args(&test_args);
2827 }
2828
2829 if builder.is_verbose() {
2830 cmd.arg("--verbose");
2831 }
2832
2833 if builder.config.cmd.verbose_run_make_subprocess_output() {
2834 cmd.arg("--verbose-run-make-subprocess-output");
2835 }
2836
2837 if builder.config.rustc_debug_assertions {
2838 cmd.arg("--with-rustc-debug-assertions");
2839 }
2840
2841 if builder.config.std_debug_assertions {
2842 cmd.arg("--with-std-debug-assertions");
2843 }
2844
2845 if builder.config.rust_remap_debuginfo {
2846 cmd.arg("--with-std-remap-debuginfo");
2847 }
2848
2849 cmd.arg("--jobs").arg(builder.jobs().to_string());
2850
2851 let mut llvm_components_passed = false;
2852 let mut copts_passed = false;
2853 if builder.config.llvm_enabled(test_compiler.host) {
2854 let llvm_output = builder.ensure(llvm::Llvm { target: builder.config.host_target });
2855 if !builder.config.dry_run() {
2856 let llvm_version = get_llvm_version(builder, llvm_output.llvm_config());
2857 let llvm_components = command(llvm_output.llvm_config())
2858 .cached()
2859 .arg("--components")
2860 .run_capture_stdout(builder)
2861 .stdout();
2862 cmd.arg("--llvm-version")
2864 .arg(llvm_version.trim())
2865 .arg("--llvm-components")
2866 .arg(llvm_components.trim());
2867 llvm_components_passed = true;
2868 }
2869 if !builder.config.is_rust_llvm(&llvm_output, target) {
2870 cmd.arg("--system-llvm");
2871 }
2872
2873 if !builder.config.dry_run() && suite.ends_with("fulldeps") {
2878 let llvm_libdir = command(llvm_output.llvm_config())
2879 .cached()
2880 .arg("--libdir")
2881 .run_capture_stdout(builder)
2882 .stdout();
2883 let link_llvm = if target.is_msvc() {
2884 format!("-Clink-arg=-LIBPATH:{llvm_libdir}")
2885 } else {
2886 format!("-Clink-arg=-L{llvm_libdir}")
2887 };
2888 cmd.arg("--host-rustcflags").arg(link_llvm);
2889 }
2890
2891 if !builder.config.dry_run()
2892 && matches!(mode, CompiletestMode::RunMake | CompiletestMode::CoverageRun)
2893 {
2894 let llvm_bin_path = llvm_output
2899 .llvm_config()
2900 .parent()
2901 .expect("Expected llvm-config to be contained in directory");
2902 assert!(llvm_bin_path.is_dir());
2903 cmd.arg("--llvm-bin-dir").arg(llvm_bin_path);
2904 }
2905
2906 if !builder.config.dry_run() && mode == CompiletestMode::RunMake {
2907 if builder.config.lld_enabled {
2909 let lld_install_root =
2910 builder.ensure(llvm::Lld { target: builder.config.host_target });
2911
2912 let lld_bin_path = lld_install_root.join("bin");
2913
2914 let old_path = env::var_os("PATH").unwrap_or_default();
2915 let new_path = env::join_paths(
2916 std::iter::once(lld_bin_path).chain(env::split_paths(&old_path)),
2917 )
2918 .expect("Could not add LLD bin path to PATH");
2919 cmd.env("PATH", new_path);
2920 }
2921 }
2922 }
2923
2924 if !builder.config.dry_run() && mode == CompiletestMode::RunMake {
2927 let mut cflags = builder.cc_handled_cflags(target, CLang::C);
2928 cflags.extend(builder.cc_unhandled_cflags(target, CLang::C));
2929 let mut cxxflags = builder.cc_handled_cflags(target, CLang::Cxx);
2930 cxxflags.extend(builder.cc_unhandled_cflags(target, CLang::Cxx));
2931 cmd.arg("--cc")
2932 .arg(builder.cc(target))
2933 .arg("--cxx")
2934 .arg(builder.cxx(target).unwrap())
2935 .arg("--cflags")
2936 .arg(cflags.join(" "))
2937 .arg("--cxxflags")
2938 .arg(cxxflags.join(" "));
2939 copts_passed = true;
2940 if let Some(ar) = builder.ar(target) {
2941 cmd.arg("--ar").arg(ar);
2942 }
2943 }
2944
2945 if !llvm_components_passed {
2946 cmd.arg("--llvm-components").arg("");
2947 }
2948 if !copts_passed {
2949 cmd.arg("--cc")
2950 .arg("")
2951 .arg("--cxx")
2952 .arg("")
2953 .arg("--cflags")
2954 .arg("")
2955 .arg("--cxxflags")
2956 .arg("");
2957 }
2958
2959 if builder.remote_tested(target) {
2960 cmd.arg("--remote-test-client").arg(builder.tool_exe(Tool::RemoteTestClient));
2961 } else if let Some(tool) = builder.runner(target) {
2962 cmd.arg("--runner").arg(tool);
2963 }
2964
2965 if suite != "mir-opt" {
2966 if !builder.config.dry_run() && target.is_msvc() {
2972 for (k, v) in builder.cc[&target].env() {
2973 if k != "PATH" {
2974 cmd.env(k, v);
2975 }
2976 }
2977 }
2978 }
2979
2980 if !builder.config.dry_run()
2982 && target.contains("msvc")
2983 && builder.config.sanitizers_enabled(target)
2984 {
2985 cmd.env("ASAN_WIN_CONTINUE_ON_INTERCEPTION_FAILURE", "1");
2988 let asan_runtime_path = builder.cc[&target].path().parent().unwrap().to_path_buf();
2990 let old_path = cmd
2991 .get_envs()
2992 .find_map(|(k, v)| (k == "PATH").then_some(v))
2993 .flatten()
2994 .map_or_else(|| env::var_os("PATH").unwrap_or_default(), |v| v.to_owned());
2995 let new_path = env::join_paths(
2996 env::split_paths(&old_path).chain(std::iter::once(asan_runtime_path)),
2997 )
2998 .expect("Could not add ASAN runtime path to PATH");
2999 cmd.env("PATH", new_path);
3000 }
3001
3002 cmd.env_remove("CARGO");
3005
3006 cmd.env("RUSTC_BOOTSTRAP", "1");
3007 cmd.env("RUSTC_FORCE_RUSTC_VERSION", "compiletest");
3010 cmd.env("DOC_RUST_LANG_ORG_CHANNEL", builder.doc_rust_lang_org_channel());
3011 builder.add_rust_test_threads(&mut cmd);
3012
3013 if builder.config.sanitizers_enabled(target) {
3014 cmd.env("RUSTC_SANITIZER_SUPPORT", "1");
3015 }
3016
3017 if builder.config.profiler_enabled(target) {
3018 cmd.arg("--profiler-runtime");
3019 }
3020
3021 cmd.env("RUST_TEST_TMPDIR", builder.tempdir());
3022
3023 if builder.config.cmd.rustfix_coverage() {
3024 cmd.arg("--rustfix-coverage");
3025 }
3026
3027 cmd.arg("--channel").arg(&builder.config.channel);
3028
3029 if !builder.config.omit_git_hash {
3030 cmd.arg("--git-hash");
3031 }
3032
3033 let git_config = builder.config.git_config();
3034 cmd.arg("--nightly-branch").arg(git_config.nightly_branch);
3035 cmd.arg("--git-merge-commit-email").arg(git_config.git_merge_commit_email);
3036
3037 #[cfg(feature = "build-metrics")]
3038 builder.metrics.begin_test_suite(
3039 build_helper::metrics::TestSuiteMetadata::Compiletest {
3040 suite: suite.into(),
3041 mode: mode.to_string(),
3042 compare_mode: None,
3043 target: self.target.triple.to_string(),
3044 host: self.test_compiler.host.triple.to_string(),
3045 stage: self.test_compiler.stage,
3046 },
3047 builder,
3048 );
3049
3050 let _group = builder.msg_test(
3051 format!("with compiletest suite={suite} mode={mode}"),
3052 target,
3053 test_compiler.stage,
3054 );
3055 try_run_tests(builder, &mut cmd, false, record_failed_tests.clone());
3056
3057 if let Some(compare_mode) = compare_mode {
3058 cmd.arg("--compare-mode").arg(compare_mode);
3059
3060 #[cfg(feature = "build-metrics")]
3061 builder.metrics.begin_test_suite(
3062 build_helper::metrics::TestSuiteMetadata::Compiletest {
3063 suite: suite.into(),
3064 mode: mode.to_string(),
3065 compare_mode: Some(compare_mode.into()),
3066 target: self.target.triple.to_string(),
3067 host: self.test_compiler.host.triple.to_string(),
3068 stage: self.test_compiler.stage,
3069 },
3070 builder,
3071 );
3072
3073 builder.info(&format!(
3074 "Check compiletest suite={} mode={} compare_mode={} ({} -> {})",
3075 suite, mode, compare_mode, test_compiler.host, target
3076 ));
3077 let _time = helpers::timeit(builder);
3078 try_run_tests(builder, &mut cmd, false, record_failed_tests);
3079 }
3080 }
3081
3082 fn metadata(&self) -> Option<StepMetadata> {
3083 Some(
3084 StepMetadata::test(&format!("compiletest-{}", self.suite), self.target)
3085 .stage(self.test_compiler.stage),
3086 )
3087 }
3088}
3089
3090#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3092struct BookTest {
3093 test_compiler: Compiler,
3094 path: PathBuf,
3095 name: &'static str,
3096 is_ext_doc: bool,
3097 dependencies: Vec<&'static str>,
3098}
3099
3100impl Step for BookTest {
3101 type Output = ();
3102
3103 fn run(self, builder: &Builder<'_>) {
3104 if self.is_ext_doc {
3114 self.run_ext_doc(builder);
3115 } else {
3116 self.run_local_doc(builder);
3117 }
3118 }
3119}
3120
3121impl BookTest {
3122 fn run_ext_doc(self, builder: &Builder<'_>) {
3125 let test_compiler = self.test_compiler;
3126
3127 builder.std(test_compiler, test_compiler.host);
3128
3129 let mut rustdoc_path = builder.rustdoc_for_compiler(test_compiler);
3132 rustdoc_path.pop();
3133 let old_path = env::var_os("PATH").unwrap_or_default();
3134 let new_path = env::join_paths(iter::once(rustdoc_path).chain(env::split_paths(&old_path)))
3135 .expect("could not add rustdoc to PATH");
3136
3137 let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook);
3138 let path = builder.src.join(&self.path);
3139 rustbook_cmd.env("RUSTC_BOOTSTRAP", "1");
3141 rustbook_cmd.env("PATH", new_path).arg("test").arg(path);
3142
3143 let libs = if !self.dependencies.is_empty() {
3148 let mut lib_paths = vec![];
3149 for dep in self.dependencies {
3150 let mode = Mode::ToolRustcPrivate;
3151 let target = builder.config.host_target;
3152 let cargo = tool::prepare_tool_cargo(
3153 builder,
3154 test_compiler,
3155 mode,
3156 target,
3157 Kind::Build,
3158 dep,
3159 SourceType::Submodule,
3160 &[],
3161 );
3162
3163 let stamp = BuildStamp::new(&builder.cargo_out(test_compiler, mode, target))
3164 .with_prefix(PathBuf::from(dep).file_name().and_then(|v| v.to_str()).unwrap());
3165
3166 let output_paths = run_cargo(
3167 builder,
3168 cargo,
3169 vec![],
3170 &stamp,
3171 vec![],
3172 ArtifactKeepMode::BothRlibAndRmeta,
3173 );
3174 let directories = output_paths
3175 .into_iter()
3176 .filter_map(|p| p.parent().map(ToOwned::to_owned))
3177 .fold(HashSet::new(), |mut set, dir| {
3178 set.insert(dir);
3179 set
3180 });
3181
3182 lib_paths.extend(directories);
3183 }
3184 lib_paths
3185 } else {
3186 vec![]
3187 };
3188
3189 if !libs.is_empty() {
3190 let paths = libs
3191 .into_iter()
3192 .map(|path| path.into_os_string())
3193 .collect::<Vec<OsString>>()
3194 .join(OsStr::new(","));
3195 rustbook_cmd.args([OsString::from("--library-path"), paths]);
3196 }
3197
3198 builder.add_rust_test_threads(&mut rustbook_cmd);
3199 let _guard = builder.msg_test(
3200 format_args!("mdbook {}", self.path.display()),
3201 test_compiler.host,
3202 test_compiler.stage,
3203 );
3204 let _time = helpers::timeit(builder);
3205 let toolstate = if rustbook_cmd.delay_failure().run(builder) {
3206 ToolState::TestPass
3207 } else {
3208 ToolState::TestFail
3209 };
3210 builder.save_toolstate(self.name, toolstate);
3211 }
3212
3213 fn run_local_doc(self, builder: &Builder<'_>) {
3215 let test_compiler = self.test_compiler;
3216 let host = self.test_compiler.host;
3217
3218 builder.std(test_compiler, host);
3219
3220 let _guard = builder.msg_test(
3221 format!("book {}", self.name),
3222 test_compiler.host,
3223 test_compiler.stage,
3224 );
3225
3226 let mut stack = vec![builder.src.join(self.path)];
3229 let _time = helpers::timeit(builder);
3230 let mut files = Vec::new();
3231 while let Some(p) = stack.pop() {
3232 if p.is_dir() {
3233 stack.extend(t!(p.read_dir()).map(|p| t!(p).path()));
3234 continue;
3235 }
3236
3237 if p.extension().and_then(|s| s.to_str()) != Some("md") {
3238 continue;
3239 }
3240
3241 files.push(p);
3242 }
3243
3244 files.sort();
3245
3246 for file in files {
3247 markdown_test(builder, test_compiler, &file);
3248 }
3249 }
3250}
3251
3252macro_rules! test_book {
3253 ($(
3254 $name:ident, $path:expr, $book_name:expr,
3255 default=$default:expr
3256 $(,submodules = $submodules:expr)?
3257 $(,dependencies=$dependencies:expr)?
3258 ;
3259 )+) => {
3260 $(
3261 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
3262 pub struct $name {
3263 test_compiler: Compiler,
3264 }
3265
3266 impl CommandLineStep for $name {
3267 type Output = ();
3268 const IS_HOST: bool = true;
3269
3270 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3271 run.path($path)
3272 }
3273
3274 fn is_default_step(_builder: &Builder<'_>) -> bool {
3275 const { $default }
3276 }
3277
3278 fn make_run(run: RunConfig<'_>) {
3279 run.builder.ensure($name {
3280 test_compiler: run.builder.compiler(run.builder.top_stage, run.target),
3281 });
3282 }
3283
3284 fn run(self, builder: &Builder<'_>) {
3285 $(
3286 for submodule in $submodules {
3287 builder.require_submodule(submodule, None);
3288 }
3289 )*
3290
3291 let dependencies = vec![];
3292 $(
3293 let mut dependencies = dependencies;
3294 for dep in $dependencies {
3295 dependencies.push(dep);
3296 }
3297 )?
3298
3299 builder.ensure(BookTest {
3300 test_compiler: self.test_compiler,
3301 path: PathBuf::from($path),
3302 name: $book_name,
3303 is_ext_doc: !$default,
3304 dependencies,
3305 });
3306 }
3307 }
3308 )+
3309 }
3310}
3311
3312test_book!(
3313 Nomicon, "src/doc/nomicon", "nomicon", default=false, submodules=["src/doc/nomicon"];
3314 Reference, "src/doc/reference", "reference", default=false, submodules=["src/doc/reference"];
3315 RustdocBook, "src/doc/rustdoc", "rustdoc", default=true;
3316 RustcBook, "src/doc/rustc", "rustc", default=true;
3317 RustByExample, "src/doc/rust-by-example", "rust-by-example", default=false, submodules=["src/doc/rust-by-example"];
3318 EmbeddedBook, "src/doc/embedded-book", "embedded-book", default=false, submodules=["src/doc/embedded-book"];
3319 TheBook, "src/doc/book", "book", default=false, submodules=["src/doc/book"], dependencies=["src/doc/book/packages/trpl"];
3320 UnstableBook, "src/doc/unstable-book", "unstable-book", default=true;
3321 EditionGuide, "src/doc/edition-guide", "edition-guide", default=false, submodules=["src/doc/edition-guide"];
3322);
3323
3324#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3325pub struct ErrorIndex {
3326 compilers: RustcPrivateCompilers,
3327}
3328
3329impl CommandLineStep for ErrorIndex {
3330 type Output = ();
3331 const IS_HOST: bool = true;
3332
3333 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3334 run.path("src/tools/error_index_generator").alias("error-index")
3337 }
3338
3339 fn is_default_step(_builder: &Builder<'_>) -> bool {
3340 true
3341 }
3342
3343 fn make_run(run: RunConfig<'_>) {
3344 let compilers = RustcPrivateCompilers::new(
3348 run.builder,
3349 run.builder.top_stage,
3350 run.builder.config.host_target,
3351 );
3352 run.builder.ensure(ErrorIndex { compilers });
3353 }
3354
3355 fn run(self, builder: &Builder<'_>) {
3362 let target_compiler = self.compilers.target_compiler();
3364
3365 let dir = testdir(builder, target_compiler.host);
3366 t!(fs::create_dir_all(&dir));
3367 let output = dir.join("error-index.md");
3368
3369 let mut tool = tool::ErrorIndex::command(builder, self.compilers);
3370 tool.arg("markdown").arg(&output);
3371
3372 let guard = builder.msg_test("error-index", target_compiler.host, target_compiler.stage);
3373 let _time = helpers::timeit(builder);
3374 tool.run_capture(builder);
3375 drop(guard);
3376 builder.std(target_compiler, target_compiler.host);
3379 markdown_test(builder, target_compiler, &output);
3380 }
3381}
3382
3383fn markdown_test(builder: &Builder<'_>, compiler: Compiler, markdown: &Path) -> bool {
3384 if let Ok(contents) = fs::read_to_string(markdown)
3385 && !contents.contains("```")
3386 {
3387 return true;
3388 }
3389
3390 builder.do_if_verbose(|| println!("doc tests for: {}", markdown.display()));
3391 let mut cmd = builder.rustdoc_cmd(compiler);
3392 builder.add_rust_test_threads(&mut cmd);
3393 cmd.arg("-Znext-solver=coherence");
3396 cmd.arg("-Z");
3398 cmd.arg("unstable-options");
3399 cmd.arg("--test");
3400 cmd.arg(markdown);
3401 cmd.env("RUSTC_BOOTSTRAP", "1");
3402
3403 let test_args = builder.config.test_args().join(" ");
3404 cmd.arg("--test-args").arg(test_args);
3405
3406 cmd = cmd.delay_failure();
3407 if !builder.config.verbose_tests {
3408 cmd.run_capture(builder).is_success()
3409 } else {
3410 cmd.run(builder)
3411 }
3412}
3413
3414#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3419pub struct CrateLibrustc {
3420 build_compiler: Compiler,
3422 target: TargetSelection,
3423 crates: Vec<String>,
3424}
3425
3426impl CommandLineStep for CrateLibrustc {
3427 type Output = ();
3428 const IS_HOST: bool = true;
3429
3430 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3431 run.crate_or_deps("rustc-main").path("compiler")
3432 }
3433
3434 fn is_default_step(_builder: &Builder<'_>) -> bool {
3435 true
3436 }
3437
3438 fn make_run(run: RunConfig<'_>) {
3439 let builder = run.builder;
3440 let host = run.build_triple();
3441 let build_compiler = builder.compiler(builder.top_stage - 1, host);
3442 let crates = run.make_run_crates(Alias::Compiler);
3443
3444 builder.ensure(CrateLibrustc { build_compiler, target: run.target, crates });
3445 }
3446
3447 fn run(self, builder: &Builder<'_>) {
3448 builder.std(self.build_compiler, self.target);
3449
3450 builder.ensure(Crate {
3452 build_compiler: self.build_compiler,
3453 target: self.target,
3454 mode: Mode::Rustc,
3455 crates: self.crates,
3456 });
3457 }
3458
3459 fn metadata(&self) -> Option<StepMetadata> {
3460 Some(StepMetadata::test("CrateLibrustc", self.target).built_by(self.build_compiler))
3461 }
3462}
3463
3464fn run_cargo_test<'a>(
3468 mut cargo: builder::Cargo,
3469 libtest_args: &[&str],
3470 crates: &[String],
3471 description: impl Into<Option<&'a str>>,
3472 target: TargetSelection,
3473 builder: &Builder<'_>,
3474 record_failed_tests: RecordFailedTests,
3475) -> bool {
3476 let compiler = cargo.compiler();
3477 let stage = match cargo.mode() {
3478 Mode::Std => compiler.stage,
3479 _ => compiler.stage + 1,
3480 };
3481
3482 cargo.rustdocflag("-Znext-solver=coherence");
3485
3486 let mut cargo = prepare_cargo_test(cargo, libtest_args, crates, target, builder);
3487 let _time = helpers::timeit(builder);
3488
3489 let _group = description.into().and_then(|what| builder.msg_test(what, target, stage));
3490
3491 #[cfg(feature = "build-metrics")]
3492 builder.metrics.begin_test_suite(
3493 build_helper::metrics::TestSuiteMetadata::CargoPackage {
3494 crates: crates.iter().map(|c| c.to_string()).collect(),
3495 target: target.triple.to_string(),
3496 host: compiler.host.triple.to_string(),
3497 stage: compiler.stage,
3498 },
3499 builder,
3500 );
3501 add_flags_and_try_run_tests(builder, &mut cargo, record_failed_tests)
3502}
3503
3504fn prepare_cargo_test(
3506 cargo: builder::Cargo,
3507 libtest_args: &[&str],
3508 crates: &[String],
3509 target: TargetSelection,
3510 builder: &Builder<'_>,
3511) -> BootstrapCommand {
3512 let compiler = cargo.compiler();
3513 let mut cargo: BootstrapCommand = cargo.into();
3514
3515 if builder.config.cmd.bless() && !cargo.get_envs().any(|v| v.0 == "RUSTC_BLESS") {
3519 cargo.env("RUSTC_BLESS", "Gesundheit");
3520 }
3521
3522 if builder.kind == Kind::Test && !builder.fail_fast {
3526 cargo.arg("--no-fail-fast");
3527 }
3528
3529 if builder.config.json_output {
3530 cargo.arg("--message-format=json");
3531 }
3532
3533 match builder.test_target {
3534 TestTarget::AllTargets => cargo.args(["--bins", "--examples", "--tests", "--benches"]),
3535 TestTarget::Default => &mut cargo,
3536 TestTarget::DocOnly => cargo.arg("--doc"),
3537 TestTarget::Tests => cargo.arg("--tests"),
3538 };
3539
3540 for krate in crates {
3541 cargo.arg("-p").arg(krate);
3542 }
3543
3544 cargo.arg("--").args(builder.config.test_args()).args(libtest_args);
3545 if !builder.config.verbose_tests {
3546 cargo.arg("--quiet");
3547 }
3548
3549 if builder.kind != Kind::Miri {
3558 let mut dylib_paths = builder.rustc_lib_paths(compiler);
3559 dylib_paths.push(builder.sysroot_target_libdir(compiler, target));
3560 helpers::add_dylib_path(dylib_paths, &mut cargo);
3561 }
3562
3563 add_cargo_target_runner(&mut cargo, target, builder);
3564
3565 cargo
3566}
3567
3568fn add_cargo_target_runner(
3571 cargo: &mut BootstrapCommand,
3572 target: TargetSelection,
3573 builder: &Builder<'_>,
3574) {
3575 if builder.remote_tested(target) {
3576 cargo.env(
3577 format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)),
3578 format!("{} run 0", builder.tool_exe(Tool::RemoteTestClient).display()),
3579 );
3580 } else if let Some(tool) = builder.runner(target) {
3581 cargo.env(format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)), tool);
3582 }
3583}
3584
3585#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3593pub struct Crate {
3594 build_compiler: Compiler,
3596 target: TargetSelection,
3597 mode: Mode,
3598 crates: Vec<String>,
3599}
3600
3601impl CommandLineStep for Crate {
3602 type Output = ();
3603
3604 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3605 run.crate_or_deps("sysroot").crate_or_deps("coretests").crate_or_deps("alloctests")
3606 }
3607
3608 fn is_default_step(_builder: &Builder<'_>) -> bool {
3609 true
3610 }
3611
3612 fn make_run(run: RunConfig<'_>) {
3613 let builder = run.builder;
3614 let host = run.build_triple();
3615 let build_compiler = builder.compiler(builder.top_stage, host);
3616 let crates = run
3617 .paths
3618 .iter()
3619 .map(|p| builder.crate_paths[&p.assert_single_path().path].clone())
3620 .collect();
3621
3622 builder.ensure(Crate { build_compiler, target: run.target, mode: Mode::Std, crates });
3623 }
3624
3625 fn run(self, builder: &Builder<'_>) {
3634 let build_compiler = self.build_compiler;
3635 let target = self.target;
3636 let mode = self.mode;
3637
3638 builder.ensure(Std::new(build_compiler, build_compiler.host).force_recompile(true));
3641 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
3642
3643 let mut cargo = if builder.kind == Kind::Miri {
3644 if builder.top_stage == 0 {
3645 eprintln!("ERROR: `x.py miri` requires stage 1 or higher");
3646 std::process::exit(1);
3647 }
3648
3649 let mut cargo = builder::Cargo::new(
3652 builder,
3653 build_compiler,
3654 mode,
3655 SourceType::InTree,
3656 target,
3657 Kind::MiriTest,
3658 );
3659 cargo.env("MIRI_REPLACE_LIBRS_IF_NOT_TEST", "1");
3671 cargo.rustflag("-Zforce-unstable-if-unmarked");
3675 cargo.env(
3680 "MIRIFLAGS",
3681 format!(
3682 "{} -Zmiri-env-forward=RUSTC_BOOTSTRAP",
3683 env::var("MIRIFLAGS").unwrap_or_default()
3684 ),
3685 );
3686 cargo
3687 } else {
3688 if !builder.config.is_host_target(target) {
3690 builder.ensure(compile::Std::new(build_compiler, target).force_recompile(true));
3691 builder.ensure(RemoteCopyLibs { build_compiler, target });
3692 }
3693
3694 builder::Cargo::new(
3696 builder,
3697 build_compiler,
3698 mode,
3699 SourceType::InTree,
3700 target,
3701 builder.kind,
3702 )
3703 };
3704
3705 match mode {
3706 Mode::Std => {
3707 if builder.kind == Kind::Miri {
3708 cargo
3714 .arg("--manifest-path")
3715 .arg(builder.src.join("library/sysroot/Cargo.toml"));
3716 } else {
3717 compile::std_cargo(builder, target, &mut cargo, &[]);
3718 }
3719 }
3720 Mode::Rustc => {
3721 compile::rustc_cargo(builder, &mut cargo, target, &build_compiler, &self.crates);
3722 }
3723 _ => panic!("can only test libraries"),
3724 };
3725
3726 let mut crates = self.crates.clone();
3727 if crates.iter().any(|crate_| crate_ == "core") {
3732 crates.push("coretests".to_owned());
3733 }
3734 if crates.iter().any(|crate_| crate_ == "alloc") {
3735 crates.push("alloctests".to_owned());
3736 };
3737 let mut description = crate_description(&self.crates);
3738 if builder.kind == Kind::Miri {
3739 if !description.is_empty() {
3740 description.push(' ');
3741 }
3742 description.push_str("in Miri");
3743 }
3744 run_cargo_test(cargo, &[], &crates, &*description, target, builder, record_failed_tests);
3745 }
3746}
3747
3748#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3751pub struct CrateRustdoc {
3752 host: TargetSelection,
3753}
3754
3755impl CommandLineStep for CrateRustdoc {
3756 type Output = ();
3757 const IS_HOST: bool = true;
3758
3759 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3760 run.multi_path(&["src/librustdoc", "src/tools/rustdoc"])
3761 }
3762
3763 fn is_default_step(_builder: &Builder<'_>) -> bool {
3764 true
3765 }
3766
3767 fn make_run(run: RunConfig<'_>) {
3768 let builder = run.builder;
3769
3770 builder.ensure(CrateRustdoc { host: run.target });
3771 }
3772
3773 fn run(self, builder: &Builder<'_>) {
3774 let target = self.host;
3775 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
3776
3777 let compiler = if builder.download_rustc() {
3778 builder.compiler(builder.top_stage, target)
3779 } else {
3780 builder.compiler_for(builder.top_stage, target, target)
3785 };
3786 builder.std(compiler, target);
3791 builder.ensure(compile::Rustc::new(compiler, target));
3792
3793 let mut cargo = tool::prepare_tool_cargo(
3794 builder,
3795 compiler,
3796 Mode::ToolRustcPrivate,
3797 target,
3798 builder.kind,
3799 "src/tools/rustdoc",
3800 SourceType::InTree,
3801 &[],
3802 );
3803 if self.host.contains("musl") {
3804 cargo.arg("'-Ctarget-feature=-crt-static'");
3805 }
3806
3807 let libdir = if builder.download_rustc() {
3834 builder.rustc_libdir(compiler)
3835 } else {
3836 builder.sysroot_target_libdir(compiler, target).to_path_buf()
3837 };
3838 let mut dylib_path = dylib_path();
3839 dylib_path.insert(0, PathBuf::from(&*libdir));
3840 cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());
3841
3842 run_cargo_test(
3843 cargo,
3844 &[],
3845 &["rustdoc:0.0.0".to_string()],
3846 "rustdoc",
3847 target,
3848 builder,
3849 record_failed_tests,
3850 );
3851 }
3852}
3853
3854#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3855pub struct CrateRustdocJsonTypes {
3856 build_compiler: Compiler,
3857 target: TargetSelection,
3858}
3859
3860impl CommandLineStep for CrateRustdocJsonTypes {
3861 type Output = ();
3862 const IS_HOST: bool = true;
3863
3864 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3865 run.path("src/rustdoc-json-types")
3866 }
3867
3868 fn is_default_step(_builder: &Builder<'_>) -> bool {
3869 true
3870 }
3871
3872 fn make_run(run: RunConfig<'_>) {
3873 let builder = run.builder;
3874
3875 builder.ensure(CrateRustdocJsonTypes {
3876 build_compiler: get_tool_target_compiler(
3877 builder,
3878 ToolTargetBuildMode::Build(run.target),
3879 ),
3880 target: run.target,
3881 });
3882 }
3883
3884 fn run(self, builder: &Builder<'_>) {
3885 let target = self.target;
3886 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
3887
3888 let cargo = tool::prepare_tool_cargo(
3889 builder,
3890 self.build_compiler,
3891 Mode::ToolTarget,
3892 target,
3893 builder.kind,
3894 "src/rustdoc-json-types",
3895 SourceType::InTree,
3896 &["rkyv_0_8".to_owned()],
3897 );
3898
3899 let libtest_args = if target.contains("musl") {
3901 ["'-Ctarget-feature=-crt-static'"].as_slice()
3902 } else {
3903 &[]
3904 };
3905
3906 run_cargo_test(
3907 cargo,
3908 libtest_args,
3909 &["rustdoc-json-types".to_string()],
3910 "rustdoc-json-types",
3911 target,
3912 builder,
3913 record_failed_tests,
3914 );
3915 }
3916}
3917
3918#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3928pub struct RemoteCopyLibs {
3929 build_compiler: Compiler,
3930 target: TargetSelection,
3931}
3932
3933impl Step for RemoteCopyLibs {
3934 type Output = ();
3935
3936 fn run(self, builder: &Builder<'_>) {
3937 let build_compiler = self.build_compiler;
3938 let target = self.target;
3939 if !builder.remote_tested(target) {
3940 return;
3941 }
3942
3943 builder.std(build_compiler, target);
3944
3945 builder.info(&format!("REMOTE copy libs to emulator ({target})"));
3946
3947 let remote_test_server = builder.ensure(tool::RemoteTestServer { build_compiler, target });
3948
3949 let tool = builder.tool_exe(Tool::RemoteTestClient);
3951 let mut cmd = command(&tool);
3952 cmd.arg("spawn-emulator")
3953 .arg(target.triple)
3954 .arg(&remote_test_server.tool_path)
3955 .arg(builder.tempdir());
3956 if let Some(rootfs) = builder.qemu_rootfs(target) {
3957 cmd.arg(rootfs);
3958 }
3959 cmd.run(builder);
3960
3961 for f in t!(builder.sysroot_target_libdir(build_compiler, target).read_dir()) {
3963 let f = t!(f);
3964 if helpers::is_dylib(&f.path()) {
3965 command(&tool).arg("push").arg(f.path()).run(builder);
3966 }
3967 }
3968 }
3969}
3970
3971#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3972pub struct Distcheck;
3973
3974impl CommandLineStep for Distcheck {
3975 type Output = ();
3976
3977 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3978 run.alias("distcheck")
3979 }
3980
3981 fn make_run(run: RunConfig<'_>) {
3982 run.builder.ensure(Distcheck);
3983 }
3984
3985 fn run(self, builder: &Builder<'_>) {
3995 let root_dir = std::env::temp_dir().join("distcheck");
3998
3999 distcheck_plain_source_tarball(builder, &root_dir.join("distcheck-rustc-src"));
4000 distcheck_rust_src(builder, &root_dir.join("distcheck-rust-src"));
4001 distcheck_rustc_dev(builder, &root_dir.join("distcheck-rustc-dev"));
4002 }
4003}
4004
4005fn distcheck_plain_source_tarball(builder: &Builder<'_>, plain_src_dir: &Path) {
4007 builder.info("Distcheck plain source tarball");
4008 let plain_src_tarball = builder.ensure(dist::PlainSourceTarball);
4009 builder.clear_dir(plain_src_dir);
4010
4011 let configure_args: Vec<String> = std::env::var("DISTCHECK_CONFIGURE_ARGS")
4012 .map(|args| args.split(" ").map(|s| s.to_string()).collect::<Vec<String>>())
4013 .unwrap_or_default();
4014
4015 command("tar")
4016 .arg("-xf")
4017 .arg(plain_src_tarball.tarball())
4018 .arg("--strip-components=1")
4019 .current_dir(plain_src_dir)
4020 .run(builder);
4021 command("./configure")
4022 .arg("--set")
4023 .arg("rust.omit-git-hash=false")
4024 .arg("--set")
4025 .arg("rust.remap-debuginfo=false")
4026 .args(&configure_args)
4027 .arg("--enable-vendor")
4028 .current_dir(plain_src_dir)
4029 .run(builder);
4030 command(helpers::make(&builder.config.host_target.triple))
4031 .arg("check")
4032 .env("GITHUB_ACTIONS", "0")
4035 .current_dir(plain_src_dir)
4036 .run(builder);
4037 builder.remove_dir(plain_src_dir);
4039}
4040
4041fn distcheck_rust_src(builder: &Builder<'_>, src_dir: &Path) {
4043 builder.info("Distcheck rust-src");
4044 let src_tarball = builder.ensure(dist::Src);
4045 builder.clear_dir(src_dir);
4046
4047 command("tar")
4048 .arg("-xf")
4049 .arg(src_tarball.tarball())
4050 .arg("--strip-components=1")
4051 .current_dir(src_dir)
4052 .run(builder);
4053
4054 let toml = src_dir.join("rust-src/lib/rustlib/src/rust/library/std/Cargo.toml");
4055 command(&builder.initial_cargo)
4056 .env("RUSTC_BOOTSTRAP", "1")
4059 .arg("generate-lockfile")
4060 .arg("--manifest-path")
4061 .arg(&toml)
4062 .current_dir(src_dir)
4063 .run(builder);
4064 builder.remove_dir(src_dir);
4066}
4067
4068fn distcheck_rustc_dev(builder: &Builder<'_>, dir: &Path) {
4070 builder.info("Distcheck rustc-dev");
4071 let tarball = builder.ensure(dist::RustcDev::new(builder, builder.host_target)).unwrap();
4072 builder.clear_dir(dir);
4073
4074 command("tar")
4075 .arg("-xf")
4076 .arg(tarball.tarball())
4077 .arg("--strip-components=1")
4078 .current_dir(dir)
4079 .run(builder);
4080
4081 command(&builder.initial_cargo)
4082 .arg("metadata")
4083 .arg("--manifest-path")
4084 .arg("rustc-dev/lib/rustlib/rustc-src/rust/compiler/rustc/Cargo.toml")
4085 .env("RUSTC_BOOTSTRAP", "1")
4086 .env("RUSTC", &builder.initial_rustc)
4088 .current_dir(dir)
4089 .run(builder);
4090 builder.remove_dir(dir);
4092}
4093
4094#[derive(Debug, Clone, PartialEq, Eq, Hash)]
4096pub(crate) struct BootstrapPy;
4097
4098impl CommandLineStep for BootstrapPy {
4099 type Output = ();
4100 const IS_HOST: bool = true;
4101
4102 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
4103 run.alias("bootstrap-py")
4104 }
4105
4106 fn is_default_step(builder: &Builder<'_>) -> bool {
4107 builder.config.is_running_on_ci()
4111 }
4112
4113 fn make_run(run: RunConfig<'_>) {
4114 run.builder.ensure(BootstrapPy)
4115 }
4116
4117 fn run(self, builder: &Builder<'_>) -> Self::Output {
4118 let mut check_bootstrap = command(
4119 builder.config.python.as_ref().expect("python is required for running bootstrap tests"),
4120 );
4121 check_bootstrap
4122 .args(["-m", "unittest", "bootstrap_test.py"])
4123 .args(builder.config.test_args())
4125 .env("BUILD_DIR", &builder.out)
4126 .env("BUILD_PLATFORM", builder.sess.host_target.triple)
4127 .env("BOOTSTRAP_TEST_RUSTC_BIN", &builder.initial_rustc)
4128 .env("BOOTSTRAP_TEST_CARGO_BIN", &builder.initial_cargo)
4129 .current_dir(builder.src.join("src/bootstrap/"));
4130 check_bootstrap.delay_failure().run(builder);
4131 }
4132}
4133
4134#[derive(Debug, Clone, PartialEq, Eq, Hash)]
4135pub struct Bootstrap;
4136
4137impl CommandLineStep for Bootstrap {
4138 type Output = ();
4139 const IS_HOST: bool = true;
4140
4141 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
4142 run.path("src/bootstrap")
4143 }
4144
4145 fn is_default_step(builder: &Builder<'_>) -> bool {
4146 builder.config.is_running_on_ci()
4150 }
4151
4152 fn run(self, builder: &Builder<'_>) {
4154 let host = builder.config.host_target;
4155 let build_compiler = builder.compiler(0, host);
4156 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
4157
4158 builder.sess.require_submodule("src/tools/cargo", None);
4160
4161 let mut cargo = tool::prepare_tool_cargo(
4162 builder,
4163 build_compiler,
4164 Mode::ToolBootstrap,
4165 host,
4166 Kind::Test,
4167 "src/bootstrap",
4168 SourceType::InTree,
4169 &[],
4170 );
4171
4172 cargo.release_build(false);
4173
4174 cargo
4175 .rustflag("-Cdebuginfo=2")
4176 .env("CARGO_TARGET_DIR", builder.out.join("bootstrap"))
4177 .env("INSTA_WORKSPACE_ROOT", &builder.src)
4179 .env("RUSTC_BOOTSTRAP", "1");
4180
4181 if builder.config.cmd.bless() {
4182 cargo.env("INSTA_UPDATE", "always");
4186 }
4187
4188 run_cargo_test(cargo, &[], &[], None, host, builder, record_failed_tests);
4189 }
4190
4191 fn make_run(run: RunConfig<'_>) {
4192 run.builder.ensure(Bootstrap);
4193 }
4194}
4195
4196fn get_compiler_to_test(builder: &Builder<'_>, target: TargetSelection) -> Compiler {
4197 builder.compiler(builder.top_stage, target)
4198}
4199
4200#[derive(Debug, Clone, PartialEq, Eq, Hash)]
4203pub struct TierCheck {
4204 test_compiler: Compiler,
4205}
4206
4207impl CommandLineStep for TierCheck {
4208 type Output = ();
4209 const IS_HOST: bool = true;
4210
4211 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
4212 run.path("src/tools/tier-check")
4213 }
4214
4215 fn is_default_step(_builder: &Builder<'_>) -> bool {
4216 true
4217 }
4218
4219 fn make_run(run: RunConfig<'_>) {
4220 run.builder
4221 .ensure(TierCheck { test_compiler: get_compiler_to_test(run.builder, run.target) });
4222 }
4223
4224 fn run(self, builder: &Builder<'_>) {
4225 let tool_build_compiler = builder.compiler(0, builder.host_target);
4226
4227 let mut cargo = tool::prepare_tool_cargo(
4228 builder,
4229 tool_build_compiler,
4230 Mode::ToolBootstrap,
4231 tool_build_compiler.host,
4232 Kind::Run,
4233 "src/tools/tier-check",
4234 SourceType::InTree,
4235 &[],
4236 );
4237 cargo.arg(builder.src.join("src/doc/rustc/src/platform-support.md"));
4238 cargo.arg(builder.rustc(self.test_compiler));
4239
4240 let _guard = builder.msg_test(
4241 "platform support check",
4242 self.test_compiler.host,
4243 self.test_compiler.stage,
4244 );
4245 BootstrapCommand::from(cargo).delay_failure().run(builder);
4246 }
4247
4248 fn metadata(&self) -> Option<StepMetadata> {
4249 Some(StepMetadata::test("tier-check", self.test_compiler.host))
4250 }
4251}
4252
4253#[derive(Debug, Clone, PartialEq, Eq, Hash)]
4254pub struct LintDocs {
4255 build_compiler: Compiler,
4256 target: TargetSelection,
4257}
4258
4259impl CommandLineStep for LintDocs {
4260 type Output = ();
4261 const IS_HOST: bool = true;
4262
4263 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
4264 run.path("src/tools/lint-docs")
4265 }
4266
4267 fn is_default_step(builder: &Builder<'_>) -> bool {
4268 builder.top_stage >= 2
4271 }
4272
4273 fn make_run(run: RunConfig<'_>) {
4274 if run.builder.top_stage < 2 {
4275 eprintln!("WARNING: lint-docs tests might not work below stage 2");
4276 }
4277
4278 run.builder.ensure(LintDocs {
4279 build_compiler: prepare_doc_compiler(
4280 run.builder,
4281 run.builder.config.host_target,
4282 run.builder.top_stage,
4283 ),
4284 target: run.target,
4285 });
4286 }
4287
4288 fn run(self, builder: &Builder<'_>) {
4291 builder.ensure(crate::core::build_steps::doc::RustcBook::validate(
4292 self.build_compiler,
4293 self.target,
4294 ));
4295 }
4296
4297 fn metadata(&self) -> Option<StepMetadata> {
4298 Some(StepMetadata::test("lint-docs", self.target).built_by(self.build_compiler))
4299 }
4300}
4301
4302#[derive(Debug, Clone, PartialEq, Eq, Hash)]
4303pub struct RustInstaller;
4304
4305impl CommandLineStep for RustInstaller {
4306 type Output = ();
4307 const IS_HOST: bool = true;
4308
4309 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
4310 run.path("src/tools/rust-installer")
4311 }
4312
4313 fn is_default_step(_builder: &Builder<'_>) -> bool {
4314 true
4315 }
4316
4317 fn make_run(run: RunConfig<'_>) {
4318 run.builder.ensure(Self);
4319 }
4320
4321 fn run(self, builder: &Builder<'_>) {
4323 let bootstrap_host = builder.config.host_target;
4324 let build_compiler = builder.compiler(0, bootstrap_host);
4325 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
4326 let cargo = tool::prepare_tool_cargo(
4327 builder,
4328 build_compiler,
4329 Mode::ToolBootstrap,
4330 bootstrap_host,
4331 Kind::Test,
4332 "src/tools/rust-installer",
4333 SourceType::InTree,
4334 &[],
4335 );
4336
4337 let _guard = builder.msg_test("rust-installer", bootstrap_host, 1);
4338 run_cargo_test(cargo, &[], &[], None, bootstrap_host, builder, record_failed_tests);
4339
4340 if bootstrap_host != "x86_64-unknown-linux-gnu" {
4344 return;
4345 }
4346
4347 let mut cmd = command(builder.src.join("src/tools/rust-installer/test.sh"));
4348 let tmpdir = testdir(builder, build_compiler.host).join("rust-installer");
4349 let _ = std::fs::remove_dir_all(&tmpdir);
4350 let _ = std::fs::create_dir_all(&tmpdir);
4351 cmd.current_dir(&tmpdir);
4352 cmd.env("CARGO_TARGET_DIR", tmpdir.join("cargo-target"));
4353 cmd.env("CARGO", &builder.initial_cargo);
4354 cmd.env("RUSTC", &builder.initial_rustc);
4355 cmd.env("TMP_DIR", &tmpdir);
4356 cmd.delay_failure().run(builder);
4357 }
4358}
4359
4360#[derive(Debug, Clone, PartialEq, Eq, Hash)]
4364pub struct TestHelpers {
4365 pub target: TargetSelection,
4366}
4367
4368impl CommandLineStep for TestHelpers {
4369 type Output = PathBuf;
4370
4371 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
4372 run.path("tests/auxiliary/rust_test_helpers.c")
4373 }
4374
4375 fn make_run(run: RunConfig<'_>) {
4376 run.builder.ensure(TestHelpers { target: run.target });
4377 }
4378
4379 fn run(self, builder: &Builder<'_>) -> Self::Output {
4382 let target = if self.target == "x86_64-fortanix-unknown-sgx" {
4386 TargetSelection::from_user("x86_64-unknown-linux-gnu")
4387 } else {
4388 self.target
4389 };
4390 let dst = builder.native_dir(target).join("rust-test-helpers");
4391 if builder.config.dry_run() {
4392 return dst;
4393 }
4394
4395 let src = builder.src.join("tests/auxiliary/rust_test_helpers.c");
4396 let _guard = builder.msg_unstaged(Kind::Build, "test helpers", target);
4397 t!(fs::create_dir_all(&dst));
4398
4399 if !up_to_date(&src, &dst.join("librust_test_helpers.a")) {
4400 let mut cfg = cc::Build::new();
4401
4402 if !target.is_msvc() {
4406 if let Some(ar) = builder.ar(target) {
4407 cfg.archiver(ar);
4408 }
4409 cfg.compiler(builder.cc(target));
4410 }
4411 cfg.cargo_metadata(false)
4412 .out_dir(&dst)
4413 .target(&target.triple)
4414 .host(&builder.config.host_target.triple)
4415 .opt_level(0)
4416 .warnings(false)
4417 .debug(false)
4418 .file(builder.src.join("tests/auxiliary/rust_test_helpers.c"))
4419 .compile("rust_test_helpers");
4420 }
4421 if target.is_pauthtest() {
4422 let so = dst.join("librust_test_helpers.so");
4423 if up_to_date(&src, &so) {
4424 return dst;
4425 }
4426
4427 let status = Command::new(builder.cc(target))
4428 .arg("-target")
4429 .arg(target.triple)
4430 .arg("-march=armv8.3-a+pauth")
4431 .arg("-fPIC")
4432 .arg("-shared")
4433 .arg("-O0") .arg("-o")
4435 .arg(&so)
4436 .arg(&src)
4437 .status()
4438 .unwrap_or_else(|_| panic!("Failed to run clang for {} toolchain", target.triple));
4439
4440 if !status.success() {
4441 panic!("Linking of librust_test_helpers.so failed (target: {})", target.triple);
4442 }
4443 }
4444 dst
4445 }
4446}
4447
4448#[derive(Debug, Clone, PartialEq, Eq, Hash)]
4449pub struct CodegenCranelift {
4450 compilers: RustcPrivateCompilers,
4451 target: TargetSelection,
4452}
4453
4454impl CommandLineStep for CodegenCranelift {
4455 type Output = ();
4456 const IS_HOST: bool = true;
4457
4458 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
4459 run.path("compiler/rustc_codegen_cranelift")
4460 }
4461
4462 fn is_default_step(_builder: &Builder<'_>) -> bool {
4463 true
4464 }
4465
4466 fn make_run(run: RunConfig<'_>) {
4467 let builder = run.builder;
4468 let host = run.build_triple();
4469 let compilers = RustcPrivateCompilers::new(run.builder, run.builder.top_stage, host);
4470
4471 if builder.test_target == TestTarget::DocOnly {
4472 return;
4473 }
4474
4475 if builder.download_rustc() {
4476 builder.info("CI rustc uses the default codegen backend. skipping");
4477 return;
4478 }
4479
4480 if !target_supports_cranelift_backend(run.target) {
4481 builder.info("target not supported by rustc_codegen_cranelift. skipping");
4482 return;
4483 }
4484
4485 if builder.remote_tested(run.target) {
4486 builder.info("remote testing is not supported by rustc_codegen_cranelift. skipping");
4487 return;
4488 }
4489
4490 if !builder
4491 .config
4492 .enabled_codegen_backends(run.target)
4493 .contains(&CodegenBackendKind::Cranelift)
4494 {
4495 builder.info("cranelift not in rust.codegen-backends. skipping");
4496 return;
4497 }
4498
4499 builder.ensure(CodegenCranelift { compilers, target: run.target });
4500 }
4501
4502 fn run(self, builder: &Builder<'_>) {
4503 let compilers = self.compilers;
4504 let build_compiler = compilers.build_compiler();
4505
4506 let target_compiler = compilers.target_compiler();
4509 let target = self.target;
4510
4511 builder.std(target_compiler, target);
4512
4513 let mut cargo = builder::Cargo::new(
4514 builder,
4515 target_compiler,
4516 Mode::Codegen, SourceType::InTree,
4518 target,
4519 Kind::Run,
4520 );
4521
4522 cargo.current_dir(&builder.src.join("compiler/rustc_codegen_cranelift"));
4523 cargo
4524 .arg("--manifest-path")
4525 .arg(builder.src.join("compiler/rustc_codegen_cranelift/build_system/Cargo.toml"));
4526
4527 cargo.env("CARGO_BUILD_INCREMENTAL", "false");
4529
4530 let _guard = builder.msg_test(
4531 "rustc_codegen_cranelift",
4532 target_compiler.host,
4533 target_compiler.stage,
4534 );
4535
4536 let download_dir = builder.out.join("cg_clif_download");
4538
4539 cargo
4540 .arg("--")
4541 .arg("test")
4542 .arg("--download-dir")
4543 .arg(&download_dir)
4544 .arg("--out-dir")
4545 .arg(builder.stage_out(build_compiler, Mode::Codegen).join("cg_clif"))
4546 .arg("--no-unstable-features")
4547 .arg("--use-backend")
4548 .arg("cranelift")
4549 .arg("--sysroot")
4551 .arg("llvm")
4552 .arg("--skip-test")
4555 .arg("testsuite.extended_sysroot");
4556
4557 cargo.into_cmd().run(builder);
4558 }
4559
4560 fn metadata(&self) -> Option<StepMetadata> {
4561 Some(
4562 StepMetadata::test("rustc_codegen_cranelift", self.target)
4563 .built_by(self.compilers.build_compiler()),
4564 )
4565 }
4566}
4567
4568#[derive(Debug, Clone, PartialEq, Eq, Hash)]
4569pub struct CodegenGCC {
4570 compilers: RustcPrivateCompilers,
4571 target: TargetSelection,
4572}
4573
4574impl CommandLineStep for CodegenGCC {
4575 type Output = ();
4576 const IS_HOST: bool = true;
4577
4578 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
4579 run.path("compiler/rustc_codegen_gcc")
4580 }
4581
4582 fn is_default_step(_builder: &Builder<'_>) -> bool {
4583 true
4584 }
4585
4586 fn make_run(run: RunConfig<'_>) {
4587 let builder = run.builder;
4588 let host = run.build_triple();
4589 let compilers = RustcPrivateCompilers::new(run.builder, run.builder.top_stage, host);
4590
4591 if builder.test_target == TestTarget::DocOnly {
4592 return;
4593 }
4594
4595 if builder.download_rustc() {
4596 builder.info("CI rustc uses the default codegen backend. skipping");
4597 return;
4598 }
4599
4600 if builder.remote_tested(run.target) {
4601 builder.info("remote testing is not supported by rustc_codegen_gcc. skipping");
4602 return;
4603 }
4604
4605 if !builder.config.enabled_codegen_backends(run.target).contains(&CodegenBackendKind::Gcc) {
4606 builder.info("gcc not in rust.codegen-backends. skipping");
4607 return;
4608 }
4609
4610 builder.ensure(CodegenGCC { compilers, target: run.target });
4611 }
4612
4613 fn run(self, builder: &Builder<'_>) {
4614 let compilers = self.compilers;
4615 let target = self.target;
4616
4617 let gcc = builder.ensure(Gcc { target_pair: GccTargetPair::for_native_build(target) });
4618
4619 if builder.config.rustc_debug_assertions {
4620 eprintln!(
4621 "WARNING: cg_gcc tests will likely fail when debug assertions are enabled for rustc"
4622 );
4623 }
4624
4625 let target_compiler = compilers.target_compiler();
4628
4629 builder.ensure(
4630 compile::Std::new(target_compiler, target)
4631 .extra_rust_args(&["-Csymbol-mangling-version=v0", "-Cpanic=abort"]),
4632 );
4633
4634 let _guard = builder.msg_test("rustc_codegen_gcc", target, target_compiler.stage);
4635 let mut cargo = builder::Cargo::new(
4636 builder,
4637 target_compiler,
4638 Mode::Codegen, SourceType::InTree,
4640 target,
4641 Kind::Run,
4642 );
4643
4644 cargo.current_dir(&builder.src.join("compiler/rustc_codegen_gcc"));
4645 cargo
4646 .arg("--manifest-path")
4647 .arg(builder.src.join("compiler/rustc_codegen_gcc/build_system/Cargo.toml"));
4648 add_cg_gcc_cargo_flags(&mut cargo, &gcc);
4649
4650 cargo.env("CARGO_BUILD_INCREMENTAL", "false");
4652 cargo.rustflag("-Cpanic=abort");
4653
4654 cargo
4655 .env("CG_RUSTFLAGS", "-Alinker-messages")
4657 .arg("--")
4658 .arg("test")
4659 .arg("--use-backend")
4660 .arg("gcc")
4661 .arg("--gcc-path")
4662 .arg(gcc.libgccjit().parent().unwrap())
4663 .arg("--out-dir")
4664 .arg(builder.stage_out(compilers.build_compiler(), Mode::Codegen).join("cg_gcc"))
4665 .arg("--release")
4666 .arg("--mini-tests")
4667 .arg("--std-tests");
4668
4669 cargo.args(builder.config.test_args());
4670
4671 cargo.into_cmd().run(builder);
4672 }
4673
4674 fn metadata(&self) -> Option<StepMetadata> {
4675 Some(
4676 StepMetadata::test("rustc_codegen_gcc", self.target)
4677 .built_by(self.compilers.build_compiler()),
4678 )
4679 }
4680}
4681
4682#[derive(Debug, Clone, PartialEq, Eq, Hash)]
4687pub struct TestFloatParse {
4688 build_compiler: Compiler,
4697 target: TargetSelection,
4699}
4700
4701impl CommandLineStep for TestFloatParse {
4702 type Output = ();
4703 const IS_HOST: bool = false;
4704
4705 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
4706 run.path("src/tools/test-float-parse")
4707 }
4708
4709 fn is_default_step(_builder: &Builder<'_>) -> bool {
4710 true
4711 }
4712
4713 fn make_run(run: RunConfig<'_>) {
4714 let builder = run.builder;
4715
4716 if run.target != run.build_triple() && !builder.was_invoked_explicitly::<Self>(Kind::Test) {
4718 return;
4719 }
4720
4721 builder.ensure(Self {
4722 build_compiler: builder.compiler(builder.top_stage, run.build_triple()),
4723 target: run.target,
4724 });
4725 }
4726
4727 fn run(self, builder: &Builder<'_>) {
4728 let build_compiler = self.build_compiler;
4729 let target = self.target;
4730
4731 builder.std(build_compiler, target);
4733 builder.std(build_compiler, builder.host_target);
4734 builder.ensure(RemoteCopyLibs { build_compiler, target });
4736 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
4737
4738 let mut cargo_test = tool::prepare_tool_cargo(
4740 builder,
4741 build_compiler,
4742 Mode::ToolStd,
4743 target,
4744 Kind::Test,
4745 "src/tools/test-float-parse",
4746 SourceType::InTree,
4747 &[],
4748 );
4749 cargo_test.allow_features(TEST_FLOAT_PARSE_ALLOW_FEATURES);
4750
4751 run_cargo_test(
4752 cargo_test,
4753 &[],
4754 &[],
4755 "test-float-parse",
4756 target,
4757 builder,
4758 record_failed_tests,
4759 );
4760
4761 let mut cargo_run = tool::prepare_tool_cargo(
4763 builder,
4764 build_compiler,
4765 Mode::ToolStd,
4766 target,
4767 Kind::Run,
4768 "src/tools/test-float-parse",
4769 SourceType::InTree,
4770 &[],
4771 );
4772 cargo_run.allow_features(TEST_FLOAT_PARSE_ALLOW_FEATURES);
4773
4774 if !matches!(env::var("FLOAT_PARSE_TESTS_NO_SKIP_HUGE").as_deref(), Ok("1") | Ok("true")) {
4775 cargo_run.args(["--", "--skip-huge"]);
4776 }
4777
4778 let mut cargo_run = cargo_run.into_cmd();
4779 add_cargo_target_runner(&mut cargo_run, target, builder);
4780 cargo_run.run(builder);
4781 }
4782
4783 fn metadata(&self) -> Option<StepMetadata> {
4784 Some(StepMetadata::test("test-float-parse", self.target))
4785 }
4786}
4787
4788#[derive(Debug, Clone, Hash, PartialEq, Eq)]
4792pub struct CollectLicenseMetadata;
4793
4794impl CommandLineStep for CollectLicenseMetadata {
4795 type Output = PathBuf;
4796 const IS_HOST: bool = true;
4797
4798 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
4799 run.path("src/tools/collect-license-metadata")
4800 }
4801
4802 fn make_run(run: RunConfig<'_>) {
4803 run.builder.ensure(CollectLicenseMetadata);
4804 }
4805
4806 fn run(self, builder: &Builder<'_>) -> Self::Output {
4807 let Some(reuse) = &builder.config.reuse else {
4808 panic!("REUSE is required to collect the license metadata");
4809 };
4810
4811 let dest = builder.src.join("license-metadata.json");
4812
4813 let mut cmd = builder.tool_cmd(Tool::CollectLicenseMetadata);
4814 cmd.env("REUSE_EXE", reuse);
4815 cmd.env("DEST", &dest);
4816 cmd.env("ONLY_CHECK", "1");
4817 cmd.run(builder);
4818
4819 dest
4820 }
4821}
4822
4823#[derive(Debug, Clone, PartialEq, Eq, Hash)]
4824pub struct RemoteTestClientTests {
4825 host: TargetSelection,
4826}
4827
4828impl CommandLineStep for RemoteTestClientTests {
4829 type Output = ();
4830 const IS_HOST: bool = true;
4831
4832 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
4833 run.path("src/tools/remote-test-client")
4834 }
4835
4836 fn is_default_step(_builder: &Builder<'_>) -> bool {
4837 true
4838 }
4839
4840 fn make_run(run: RunConfig<'_>) {
4841 run.builder.ensure(Self { host: run.target });
4842 }
4843
4844 fn run(self, builder: &Builder<'_>) {
4845 let bootstrap_host = builder.config.host_target;
4846 let compiler = builder.compiler(0, bootstrap_host);
4847 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
4848
4849 let cargo = tool::prepare_tool_cargo(
4850 builder,
4851 compiler,
4852 Mode::ToolBootstrap,
4853 bootstrap_host,
4854 Kind::Test,
4855 "src/tools/remote-test-client",
4856 SourceType::InTree,
4857 &[],
4858 );
4859
4860 run_cargo_test(
4861 cargo,
4862 &[],
4863 &[],
4864 "remote-test-client",
4865 bootstrap_host,
4866 builder,
4867 record_failed_tests,
4868 );
4869 }
4870}
4871
4872fn check_if_cargo_semver_checks_is_installed(builder: &Builder<'_>) -> bool {
4873 command(&builder.initial_cargo)
4874 .allow_failure()
4875 .arg("semver-checks")
4876 .arg("--version")
4877 .cached()
4879 .run_capture_stdout(builder)
4880 .is_success()
4881}
4882
4883#[derive(Debug, Clone, PartialEq, Eq, Hash)]
4894pub struct StdSemverCheck {
4895 build_compiler: Compiler,
4896 target: TargetSelection,
4897 commit: String,
4899}
4900
4901impl CommandLineStep for StdSemverCheck {
4902 type Output = ();
4903
4904 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
4905 run.alias("std-semver-check")
4906 }
4907
4908 fn make_run(run: RunConfig<'_>) {
4909 if !check_if_cargo_semver_checks_is_installed(run.builder) {
4910 panic!("cargo-semver-checks was not found, please install it");
4911 }
4912
4913 let baseline_commit =
4914 run.builder.config.stdlib_semver_baseline.clone().unwrap_or_else(|| {
4915 match get_closest_upstream_commit(
4916 Some(&run.builder.config.src),
4917 &run.builder.config.git_config(),
4918 run.builder.config.ci_env,
4919 ) {
4920 Ok(Some(commit)) => commit,
4921 Ok(None) => {
4922 panic!("No baseline parent commit found for std-semver-check");
4923 }
4924 Err(error) => {
4925 panic!("Cannot get baseline parent commit for std-semver-check: {error:?}");
4926 }
4927 }
4928 });
4929
4930 run.builder.ensure(Self {
4931 build_compiler: run.builder.compiler_for_std(run.builder.top_stage),
4932 target: run.target,
4933 commit: baseline_commit,
4934 });
4935 }
4936
4937 fn run(self, builder: &Builder<'_>) {
4938 const STDLIB_SEMVER_CHECK_STAMP_PATH: &str = "src/bootstrap/stdlib-semver-check-stamp";
4939
4940 if builder.config.ci_env.is_running_in_ci()
4941 && builder.config.has_changes_from_upstream(&[STDLIB_SEMVER_CHECK_STAMP_PATH])
4942 {
4943 builder.info(&format!("Skipping stdlib semver check, because {STDLIB_SEMVER_CHECK_STAMP_PATH} was modified."));
4944 return;
4945 }
4946
4947 let Some(docs_dir) = builder.config.download_std_json_docs(self.target, &self.commit)
4948 else {
4949 return;
4950 };
4951
4952 let directory = builder.ensure(crate::core::build_steps::doc::Std::from_build_compiler(
4953 self.build_compiler,
4954 self.target,
4955 DocumentationFormat::Json,
4956 ));
4957 let baseline_dir = docs_dir.join("share").join("doc").join("rust").join("json");
4958
4959 for library in ["core", "alloc", "std"] {
4960 println!("Checking semver compatibility of {library}");
4961 let mut cmd = command(&builder.initial_cargo);
4962 cmd.arg("semver-checks")
4963 .arg("-Z")
4964 .arg("unstable-options")
4965 .arg("--stability-aware")
4966 .arg("--release-type")
4967 .arg("minor")
4968 .arg("--current-rustdoc")
4969 .arg(directory.join(format!("{library}.json")))
4970 .arg("--baseline-rustdoc")
4971 .arg(baseline_dir.join(format!("{library}.json")));
4972
4973 let res = cmd.allow_failure().run_capture(builder);
4975 match res.status() {
4976 Some(status) if status.success() => {
4977 println!("{}\n{}", res.stdout(), res.stderr());
4978 }
4979 Some(status) if status.code() == Some(101) => {
4982 eprintln!(
4983 "cargo-semver-checks was unable to process {library} (this is not a fatal error)\n{}\n{}",
4984 res.stderr(),
4985 res.stdout()
4986 );
4987 }
4988 Some(status) if status.code() == Some(100) => {
4990 let error = format!(
4991 "cargo-semver-checks found semver breakage in {library}\n{}\n{}",
4992 res.stderr(),
4993 res.stdout()
4994 );
4995 if builder.fail_fast {
4996 eprintln!("{error}");
4997 helpers::exit_process(1);
4998 } else {
4999 builder.config.exec_ctx().add_to_delay_failure(error);
5000 }
5001 }
5002 _ => {
5003 eprintln!("cargo-semver-checks failed.\n{}\n{}", res.stderr(), res.stdout());
5004 helpers::exit_process(1);
5005 }
5006 }
5007 }
5008 }
5009}