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::build_steps::compile::{ArtifactKeepMode, Std, run_cargo};
19use crate::core::build_steps::doc::{DocumentationFormat, prepare_doc_compiler};
20use crate::core::build_steps::format::InternalRustfmt;
21use crate::core::build_steps::gcc::{Gcc, GccTargetPair, add_cg_gcc_cargo_flags};
22use crate::core::build_steps::llvm::get_llvm_version;
23use crate::core::build_steps::run::{get_completion_paths, get_help_path};
24use crate::core::build_steps::synthetic_targets::MirOptPanicAbortSyntheticTarget;
25use crate::core::build_steps::test::compiletest::CompiletestMode;
26use crate::core::build_steps::test::failed_tests::{RecordFailedTests, SetupFailedTestsFile};
27use crate::core::build_steps::tool::{
28 self, RustcPrivateCompilers, SourceType, TEST_FLOAT_PARSE_ALLOW_FEATURES, Tool,
29 ToolTargetBuildMode, get_tool_target_compiler,
30};
31use crate::core::build_steps::toolstate::ToolState;
32use crate::core::build_steps::{compile, dist, llvm};
33use crate::core::builder::{
34 self, Alias, Builder, CommandLineStep, Compiler, Kind, RunConfig, ShouldRun, Step,
35 StepMetadata, crate_description,
36};
37use crate::core::config::TargetSelection;
38use crate::core::config::flags::{Subcommand, get_completion, top_level_help};
39use crate::core::{android, debuggers};
40use crate::utils::build_stamp::{self, BuildStamp};
41use crate::utils::exec::{BootstrapCommand, command};
42use crate::utils::helpers::{
43 self, LldThreads, TestFilterCategory, add_dylib_path, add_rustdoc_cargo_linker_args,
44 dylib_path, dylib_path_var, linker_args, linker_flags, t, target_supports_cranelift_backend,
45 up_to_date,
46};
47use crate::utils::render_tests::{add_flags_and_try_run_tests, try_run_tests};
48use crate::{CLang, CodegenBackendKind, GitRepo, Mode, TestTarget, envify, exit};
49
50mod compiletest;
51pub mod failed_tests;
52
53#[derive(Debug, Clone, PartialEq, Eq, Hash)]
55pub struct CrateBootstrap {
56 path: PathBuf,
57 host: TargetSelection,
58}
59
60impl CommandLineStep for CrateBootstrap {
61 type Output = ();
62 const IS_HOST: bool = true;
63
64 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
65 run.path("src/tools/jsondoclint")
70 .path("src/tools/replace-version-placeholder")
71 .path("src/tools/coverage-dump")
72 .alias("tidyselftest")
75 }
76
77 fn is_default_step(_builder: &Builder<'_>) -> bool {
78 true
79 }
80
81 fn make_run(run: RunConfig<'_>) {
82 for path in run.paths {
85 let path = path.assert_single_path().path.clone();
86 run.builder.ensure(CrateBootstrap { host: run.target, path });
87 }
88 }
89
90 fn run(self, builder: &Builder<'_>) {
91 let bootstrap_host = builder.config.host_target;
92 let compiler = builder.compiler(0, bootstrap_host);
93 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
94 let mut path = self.path.to_str().unwrap();
95
96 if path == "tidyselftest" {
98 path = "src/tools/tidy";
99 }
100
101 let cargo = tool::prepare_tool_cargo(
102 builder,
103 compiler,
104 Mode::ToolBootstrap,
105 bootstrap_host,
106 Kind::Test,
107 path,
108 SourceType::InTree,
109 &[],
110 );
111
112 let crate_name = path.rsplit_once('/').unwrap().1;
113 run_cargo_test(cargo, &[], &[], crate_name, bootstrap_host, builder, record_failed_tests);
114 }
115
116 fn metadata(&self) -> Option<StepMetadata> {
117 Some(
118 StepMetadata::test("crate-bootstrap", self.host)
119 .with_metadata(self.path.as_path().to_string_lossy().to_string()),
120 )
121 }
122}
123
124#[derive(Debug, Clone, PartialEq, Eq, Hash)]
125pub struct Linkcheck {
126 host: TargetSelection,
127}
128
129impl CommandLineStep for Linkcheck {
130 type Output = ();
131 const IS_HOST: bool = true;
132
133 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
134 run.path("src/tools/linkchecker")
135 }
136
137 fn is_default_step(builder: &Builder<'_>) -> bool {
138 builder.config.docs
139 }
140
141 fn make_run(run: RunConfig<'_>) {
142 run.builder.ensure(Linkcheck { host: run.target });
143 }
144
145 fn run(self, builder: &Builder<'_>) {
150 let host = self.host;
151 let hosts = &builder.hosts;
152 let targets = &builder.targets;
153
154 if (hosts != targets) && !hosts.is_empty() && !targets.is_empty() {
159 panic!(
160 "Linkcheck currently does not support builds with different hosts and targets.
161You can skip linkcheck with --skip src/tools/linkchecker"
162 );
163 }
164
165 builder.info(&format!("Linkcheck ({host})"));
166
167 let bootstrap_host = builder.config.host_target;
169 let compiler = builder.compiler(0, bootstrap_host);
170 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
171
172 let cargo = tool::prepare_tool_cargo(
173 builder,
174 compiler,
175 Mode::ToolBootstrap,
176 bootstrap_host,
177 Kind::Test,
178 "src/tools/linkchecker",
179 SourceType::InTree,
180 &[],
181 );
182 run_cargo_test(
183 cargo,
184 &[],
185 &[],
186 "linkchecker self tests",
187 bootstrap_host,
188 builder,
189 record_failed_tests,
190 );
191
192 if !builder.test_target.runs_doctests() {
193 return;
194 }
195
196 builder.run_default_doc_steps();
198
199 let linkchecker = builder.tool_cmd(Tool::Linkchecker);
201
202 let _guard = builder.msg_test("Linkcheck", bootstrap_host, 1);
204 let _time = helpers::timeit(builder);
205 linkchecker.delay_failure().arg(builder.out.join(host).join("doc")).run(builder);
206 }
207
208 fn metadata(&self) -> Option<StepMetadata> {
209 Some(StepMetadata::test("link-check", self.host))
210 }
211}
212
213fn check_if_tidy_is_installed(builder: &Builder<'_>) -> bool {
214 command("tidy")
215 .allow_failure()
216 .arg("--version")
217 .cached()
219 .run_capture_stdout(builder)
220 .is_success()
221}
222
223#[derive(Debug, Clone, PartialEq, Eq, Hash)]
224pub struct HtmlCheck {
225 target: TargetSelection,
226}
227
228impl CommandLineStep for HtmlCheck {
229 type Output = ();
230 const IS_HOST: bool = true;
231
232 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
233 run.path("src/tools/html-checker")
234 }
235
236 fn is_default_step(builder: &Builder<'_>) -> bool {
237 check_if_tidy_is_installed(builder)
238 }
239
240 fn make_run(run: RunConfig<'_>) {
241 run.builder.ensure(HtmlCheck { target: run.target });
242 }
243
244 fn run(self, builder: &Builder<'_>) {
245 if !check_if_tidy_is_installed(builder) {
246 eprintln!("not running HTML-check tool because `tidy` is missing");
247 eprintln!(
248 "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."
249 );
250 panic!("Cannot run html-check tests");
251 }
252 builder.run_default_doc_steps();
254 builder.ensure(crate::core::build_steps::doc::Rustc::for_stage(
255 builder,
256 builder.top_stage,
257 self.target,
258 ));
259
260 builder
261 .tool_cmd(Tool::HtmlChecker)
262 .delay_failure()
263 .arg(builder.doc_out(self.target))
264 .run(builder);
265 }
266
267 fn metadata(&self) -> Option<StepMetadata> {
268 Some(StepMetadata::test("html-check", self.target))
269 }
270}
271
272#[derive(Debug, Clone, PartialEq, Eq, Hash)]
276pub struct Cargotest {
277 build_compiler: Compiler,
278 host: TargetSelection,
279}
280
281impl CommandLineStep for Cargotest {
282 type Output = ();
283 const IS_HOST: bool = true;
284
285 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
286 run.path("src/tools/cargotest")
287 }
288
289 fn make_run(run: RunConfig<'_>) {
290 if run.builder.top_stage == 0 {
291 eprintln!(
292 "ERROR: running cargotest with stage 0 is currently unsupported. Use at least stage 1."
293 );
294 exit!(1);
295 }
296 run.builder.ensure(Cargotest {
300 build_compiler: run.builder.compiler(run.builder.top_stage - 1, run.target),
301 host: run.target,
302 });
303 }
304
305 fn run(self, builder: &Builder<'_>) {
310 let cargo =
320 builder.ensure(tool::Cargo::from_build_compiler(self.build_compiler, self.host));
321 let tested_compiler = builder.compiler(self.build_compiler.stage + 1, self.host);
322 builder.std(tested_compiler, self.host);
323
324 let out_dir = builder.out.join("ct");
328 t!(fs::create_dir_all(&out_dir));
329
330 let _time = helpers::timeit(builder);
331 let mut cmd = builder.tool_cmd(Tool::CargoTest);
332 cmd.arg(&cargo.tool_path)
333 .arg(&out_dir)
334 .args(builder.config.test_args())
335 .env("RUSTC", builder.rustc(tested_compiler))
336 .env("RUSTDOC", builder.rustdoc_for_compiler(tested_compiler));
337 add_rustdoc_cargo_linker_args(&mut cmd, builder, tested_compiler.host, LldThreads::No);
338 cmd.delay_failure().run(builder);
339 }
340
341 fn metadata(&self) -> Option<StepMetadata> {
342 Some(StepMetadata::test("cargotest", self.host).stage(self.build_compiler.stage + 1))
343 }
344}
345
346#[derive(Debug, Clone, PartialEq, Eq, Hash)]
349pub struct Cargo {
350 build_compiler: Compiler,
351 host: TargetSelection,
352}
353
354impl Cargo {
355 const CRATE_PATH: &str = "src/tools/cargo";
356}
357
358impl CommandLineStep for Cargo {
359 type Output = ();
360 const IS_HOST: bool = true;
361
362 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
363 run.path(Self::CRATE_PATH)
364 }
365
366 fn make_run(run: RunConfig<'_>) {
367 run.builder.ensure(Cargo {
368 build_compiler: get_tool_target_compiler(
369 run.builder,
370 ToolTargetBuildMode::Build(run.target),
371 ),
372 host: run.target,
373 });
374 }
375
376 fn run(self, builder: &Builder<'_>) {
378 builder.ensure(tool::Cargo::from_build_compiler(self.build_compiler, self.host));
382 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
383
384 let tested_compiler = builder.compiler(self.build_compiler.stage + 1, self.host);
385 builder.std(tested_compiler, self.host);
386 builder.rustdoc_for_compiler(tested_compiler);
390
391 let cargo = tool::prepare_tool_cargo(
392 builder,
393 self.build_compiler,
394 Mode::ToolTarget,
395 self.host,
396 Kind::Test,
397 Self::CRATE_PATH,
398 SourceType::Submodule,
399 &[],
400 );
401
402 let mut cargo = prepare_cargo_test(cargo, &[], &[], self.host, builder);
404
405 cargo.env("CFG_DISABLE_CROSS_TESTS", "1");
408 cargo.env("CARGO_TEST_DISABLE_NIGHTLY", "1");
411
412 cargo.env("PATH", bin_path_for_cargo(builder, tested_compiler));
416
417 let mut existing_dylib_paths = cargo
422 .get_envs()
423 .find(|(k, _)| *k == OsStr::new(dylib_path_var()))
424 .and_then(|(_, v)| v)
425 .map(|value| split_paths(value).collect::<Vec<PathBuf>>())
426 .unwrap_or_default();
427 existing_dylib_paths.insert(0, builder.rustc_libdir(tested_compiler));
428 add_dylib_path(existing_dylib_paths, &mut cargo);
429
430 cargo.env("CARGO_RUSTC_CURRENT_DIR", builder.src.display().to_string());
434
435 #[cfg(feature = "build-metrics")]
436 builder.metrics.begin_test_suite(
437 build_helper::metrics::TestSuiteMetadata::CargoPackage {
438 crates: vec!["cargo".into()],
439 target: self.host.triple.to_string(),
440 host: self.host.triple.to_string(),
441 stage: self.build_compiler.stage + 1,
442 },
443 builder,
444 );
445
446 let _time = helpers::timeit(builder);
447 add_flags_and_try_run_tests(builder, &mut cargo, record_failed_tests);
448 }
449
450 fn metadata(&self) -> Option<StepMetadata> {
451 Some(StepMetadata::test("cargo", self.host).built_by(self.build_compiler))
452 }
453}
454
455#[derive(Debug, Clone, PartialEq, Eq, Hash)]
456pub struct RustAnalyzer {
457 compilers: RustcPrivateCompilers,
458}
459
460impl CommandLineStep for RustAnalyzer {
461 type Output = ();
462 const IS_HOST: bool = true;
463
464 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
465 run.path("src/tools/rust-analyzer")
466 }
467
468 fn is_default_step(_builder: &Builder<'_>) -> bool {
469 true
470 }
471
472 fn make_run(run: RunConfig<'_>) {
473 run.builder.ensure(Self {
474 compilers: RustcPrivateCompilers::new(
475 run.builder,
476 run.builder.top_stage,
477 run.builder.host_target,
478 ),
479 });
480 }
481
482 fn run(self, builder: &Builder<'_>) {
484 let build_compiler = self.compilers.build_compiler();
485 let target = self.compilers.target();
486 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
487
488 if target.starts_with("i686") {
498 return;
499 }
500
501 let suite = "src/tools/rust-analyzer";
502 let mut cargo = tool::prepare_tool_cargo(
503 builder,
504 build_compiler,
505 Mode::ToolRustcPrivate,
506 target,
507 Kind::Test,
508 suite,
509 SourceType::InTree,
510 &["in-rust-tree".to_owned()],
511 );
512 cargo.allow_features(tool::RustAnalyzer::ALLOW_FEATURES);
513
514 cargo.env("SKIP_SLOW_TESTS", "1");
521
522 cargo.arg("--workspace");
528 cargo.arg("--exclude=xtask");
529
530 if build_compiler.stage == 0 {
531 cargo.arg("--exclude=proc-macro-srv");
534 cargo.arg("--exclude=proc-macro-srv-cli");
535 }
536
537 let mut skip_tests = vec![];
538
539 skip_tests.extend_from_slice(&[
547 "tests::smoke_test_real_sysroot_cargo",
550 "check_code_formatting",
553 ]);
554
555 let skip_tests = skip_tests.iter().map(|name| format!("--skip={name}")).collect::<Vec<_>>();
556 let skip_tests = skip_tests.iter().map(|s| s.as_str()).collect::<Vec<_>>();
557
558 cargo.add_rustc_lib_path(builder);
559 run_cargo_test(
560 cargo,
561 skip_tests.as_slice(),
562 &[],
563 "rust-analyzer",
564 target,
565 builder,
566 record_failed_tests,
567 );
568 }
569
570 fn metadata(&self) -> Option<StepMetadata> {
571 Some(
572 StepMetadata::test("rust-analyzer", self.compilers.target())
573 .built_by(self.compilers.build_compiler()),
574 )
575 }
576}
577
578#[derive(Debug, Clone, PartialEq, Eq, Hash)]
580pub struct Rustfmt {
581 compilers: RustcPrivateCompilers,
582}
583
584impl CommandLineStep for Rustfmt {
585 type Output = ();
586 const IS_HOST: bool = true;
587
588 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
589 run.path("src/tools/rustfmt")
590 }
591
592 fn make_run(run: RunConfig<'_>) {
593 run.builder.ensure(Rustfmt {
594 compilers: RustcPrivateCompilers::new(
595 run.builder,
596 run.builder.top_stage,
597 run.builder.host_target,
598 ),
599 });
600 }
601
602 fn run(self, builder: &Builder<'_>) {
604 let build_compiler = self.compilers.build_compiler();
605 let target = self.compilers.target();
606 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
607
608 builder.ensure(compile::Rustc::new(build_compiler, target));
612
613 let mut cargo = tool::prepare_tool_cargo(
614 builder,
615 build_compiler,
616 Mode::ToolRustcPrivate,
617 target,
618 Kind::Test,
619 "src/tools/rustfmt",
620 SourceType::InTree,
621 &[],
622 );
623
624 let dir = testdir(builder, target);
625 t!(fs::create_dir_all(&dir));
626 cargo.env("RUSTFMT_TEST_DIR", dir);
627
628 cargo.add_rustc_lib_path(builder);
629
630 run_cargo_test(cargo, &[], &[], "rustfmt", target, builder, record_failed_tests);
631 }
632
633 fn metadata(&self) -> Option<StepMetadata> {
634 Some(
635 StepMetadata::test("rustfmt", self.compilers.target())
636 .built_by(self.compilers.build_compiler()),
637 )
638 }
639}
640
641#[derive(Debug, Clone, PartialEq, Eq, Hash)]
642pub struct Miri {
643 target: TargetSelection,
644}
645
646impl Miri {
647 pub fn build_miri_sysroot(
649 builder: &Builder<'_>,
650 compiler: Compiler,
651 target: TargetSelection,
652 ) -> PathBuf {
653 let miri_sysroot = builder.out.join(compiler.host).join("miri-sysroot");
654 let mut cargo = builder::Cargo::new(
655 builder,
656 compiler,
657 Mode::Std,
658 SourceType::Submodule,
659 target,
660 Kind::MiriSetup,
661 );
662
663 cargo.env("MIRI_LIB_SRC", builder.src.join("library"));
665 cargo.env("MIRI_SYSROOT", &miri_sysroot);
667
668 let mut cargo = BootstrapCommand::from(cargo);
669 let _guard =
670 builder.msg(Kind::Build, "miri sysroot", Mode::ToolRustcPrivate, compiler, target);
671 cargo.run(builder);
672
673 cargo.arg("--print-sysroot");
679
680 builder.do_if_verbose(|| println!("running: {cargo:?}"));
681 let stdout = cargo.run_capture_stdout(builder).stdout();
682 let sysroot = stdout.trim_end();
684 builder.do_if_verbose(|| println!("`cargo miri setup --print-sysroot` said: {sysroot:?}"));
685 PathBuf::from(sysroot)
686 }
687}
688
689impl CommandLineStep for Miri {
690 type Output = ();
691
692 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
693 run.path("src/tools/miri")
694 }
695
696 fn make_run(run: RunConfig<'_>) {
697 run.builder.ensure(Miri { target: run.target });
698 }
699
700 fn run(self, builder: &Builder<'_>) {
702 let host = builder.build.host_target;
703 let target = self.target;
704 let stage = builder.top_stage;
705 if stage == 0 {
706 eprintln!("miri cannot be tested at stage 0");
707 std::process::exit(1);
708 }
709
710 let compilers = RustcPrivateCompilers::new(builder, stage, host);
712
713 let miri = builder.ensure(tool::Miri::from_compilers(compilers));
715 builder.ensure(tool::CargoMiri::from_compilers(compilers));
717
718 let target_compiler = compilers.target_compiler();
719
720 let miri_sysroot = Miri::build_miri_sysroot(builder, target_compiler, target);
723 builder.std(target_compiler, host);
724 let host_sysroot = builder.sysroot(target_compiler);
725
726 if !builder.config.dry_run() {
729 let ui_test_dep_dir = builder
732 .stage_out(miri.build_compiler, Mode::ToolStd)
733 .join(host)
734 .join("tmp")
735 .join("miri_ui");
736 build_stamp::clear_if_dirty(builder, &ui_test_dep_dir, &miri_sysroot);
740 }
741
742 let mut cargo = tool::prepare_tool_cargo(
745 builder,
746 miri.build_compiler,
747 Mode::ToolRustcPrivate,
748 host,
749 Kind::Test,
750 "src/tools/miri",
751 SourceType::InTree,
752 &[],
753 );
754
755 cargo.add_rustc_lib_path(builder);
756
757 let mut cargo = prepare_cargo_test(cargo, &[], &[], host, builder);
760
761 cargo.env("MIRI_SYSROOT", &miri_sysroot);
763 cargo.env("MIRI_HOST_SYSROOT", &host_sysroot);
764
765 cargo.env("MIRI_TEST_TARGET", target.rustc_target_arg());
767
768 {
769 let _guard = builder.msg_test("miri", target, target_compiler.stage);
770 let _time = helpers::timeit(builder);
771 cargo.run(builder);
772 }
773 }
774}
775
776#[derive(Debug, Clone, PartialEq, Eq, Hash)]
779pub struct CargoMiri {
780 target: TargetSelection,
781}
782
783impl CommandLineStep for CargoMiri {
784 type Output = ();
785
786 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
787 run.path("src/tools/miri/cargo-miri")
788 }
789
790 fn make_run(run: RunConfig<'_>) {
791 run.builder.ensure(CargoMiri { target: run.target });
792 }
793
794 fn run(self, builder: &Builder<'_>) {
796 let host = builder.build.host_target;
797 let target = self.target;
798 let stage = builder.top_stage;
799 if stage == 0 {
800 eprintln!("cargo-miri cannot be tested at stage 0");
801 std::process::exit(1);
802 }
803
804 let build_compiler = builder.compiler(stage, host);
806
807 let mut cargo = tool::prepare_tool_cargo(
812 builder,
813 build_compiler,
814 Mode::ToolStd, target,
816 Kind::MiriTest,
817 "src/tools/miri/test-cargo-miri",
818 SourceType::Submodule,
819 &[],
820 );
821 cargo.arg("--workspace");
823 cargo.env("MIRIFLAGS", "-Zmiri-disable-isolation");
825
826 if stage >= 2 {
829 let built_cargo = builder
830 .ensure(tool::Cargo::from_build_compiler(
831 builder.compiler(0, builder.host_target),
834 builder.host_target,
835 ))
836 .tool_path;
837 cargo.env("CARGO", built_cargo);
838 }
839
840 match builder.test_target {
843 TestTarget::AllTargets => {
844 cargo.args(["--lib", "--bins", "--examples", "--tests", "--benches"])
845 }
846 TestTarget::Default => &mut cargo,
847 TestTarget::DocOnly => cargo.arg("--doc"),
848 TestTarget::Tests => cargo.arg("--tests"),
849 };
850 cargo.arg("--").args(builder.config.test_args());
851
852 let mut cargo = BootstrapCommand::from(cargo);
854 {
855 let _guard = builder.msg_test("cargo-miri", target, stage);
856 let _time = helpers::timeit(builder);
857 cargo.run(builder);
858 }
859 }
860}
861
862#[derive(Debug, Clone, PartialEq, Eq, Hash)]
863pub struct Priroda {
864 target: TargetSelection,
865}
866
867impl CommandLineStep for Priroda {
868 type Output = ();
869
870 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
871 run.path("src/tools/miri/priroda")
872 }
873
874 fn make_run(run: RunConfig<'_>) {
875 run.builder.ensure(Priroda { target: run.target });
876 }
877
878 fn run(self, builder: &Builder<'_>) {
880 let host = builder.build.host_target;
881 let target = self.target;
882 let stage = builder.top_stage;
883
884 let compilers = RustcPrivateCompilers::new(builder, stage, host);
886 let miri = builder.ensure(tool::Miri::from_compilers(compilers));
887 let target_compiler = compilers.target_compiler();
888
889 let miri_sysroot = Miri::build_miri_sysroot(builder, target_compiler, target);
890 builder.std(target_compiler, host);
891 let host_sysroot = builder.sysroot(target_compiler);
892
893 let mut cargo = tool::prepare_tool_cargo(
894 builder,
895 miri.build_compiler,
896 Mode::ToolRustcPrivate,
897 host,
898 Kind::Test,
899 "src/tools/miri/priroda",
900 SourceType::InTree,
901 &[],
902 );
903
904 cargo.add_rustc_lib_path(builder);
905
906 let mut cargo = prepare_cargo_test(cargo, &[], &[], host, builder);
907
908 cargo.env("MIRI_SYSROOT", &miri_sysroot);
909 cargo.env("MIRI_HOST_SYSROOT", &host_sysroot);
910 cargo.env("MIRI_TEST_TARGET", target.rustc_target_arg());
911
912 {
913 let _guard = builder.msg_test("priroda", target, target_compiler.stage);
914 let _time = helpers::timeit(builder);
915 cargo.run(builder);
916 }
917 }
918}
919
920#[derive(Debug, Clone, PartialEq, Eq, Hash)]
921pub struct CompiletestTest {
922 host: TargetSelection,
923}
924
925impl CommandLineStep for CompiletestTest {
926 type Output = ();
927
928 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
929 run.path("src/tools/compiletest")
930 }
931
932 fn make_run(run: RunConfig<'_>) {
933 run.builder.ensure(CompiletestTest { host: run.target });
934 }
935
936 fn run(self, builder: &Builder<'_>) {
938 let host = self.host;
939 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
940
941 if builder.top_stage == 0 && !builder.config.compiletest_allow_stage0 {
947 eprintln!("\
948ERROR: `--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
949NOTE: 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`."
950 );
951 crate::exit!(1);
952 }
953
954 let bootstrap_compiler = builder.compiler(0, host);
955 let staged_compiler = builder.compiler(builder.top_stage, host);
956
957 let mut cargo = tool::prepare_tool_cargo(
958 builder,
959 bootstrap_compiler,
960 Mode::ToolBootstrap,
961 host,
962 Kind::Test,
963 "src/tools/compiletest",
964 SourceType::InTree,
965 &[],
966 );
967
968 cargo.env("TEST_RUSTC", builder.rustc(staged_compiler));
972
973 run_cargo_test(
974 cargo,
975 &[],
976 &[],
977 "compiletest self test",
978 host,
979 builder,
980 record_failed_tests,
981 );
982 }
983}
984
985#[derive(Debug, Clone, PartialEq, Eq, Hash)]
989pub struct StdarchVerify;
990
991impl CommandLineStep for StdarchVerify {
992 type Output = ();
993 const IS_HOST: bool = true;
994
995 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
996 run.path("library/stdarch/crates/stdarch-verify")
997 }
998
999 fn is_default_step(_builder: &Builder<'_>) -> bool {
1000 true
1001 }
1002
1003 fn make_run(run: RunConfig<'_>) {
1004 run.builder.ensure(StdarchVerify);
1005 }
1006
1007 fn run(self, builder: &Builder<'_>) {
1008 let host = builder.config.host_target;
1009 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
1010 let build_compiler = builder.compiler(0, host);
1011
1012 let cargo = tool::prepare_tool_cargo(
1013 builder,
1014 build_compiler,
1015 Mode::ToolBootstrap,
1016 host,
1017 Kind::Test,
1018 "library/stdarch/crates/stdarch-verify",
1019 SourceType::InTree,
1020 &[],
1021 );
1022
1023 run_cargo_test(
1024 cargo,
1025 &[],
1026 &["stdarch-verify".to_string()],
1027 Some("stdarch-verify"),
1028 host,
1029 builder,
1030 record_failed_tests,
1031 );
1032 }
1033}
1034
1035#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1045pub struct IntrinsicTest {
1046 host: TargetSelection,
1047}
1048
1049impl CommandLineStep for IntrinsicTest {
1050 type Output = ();
1051 const IS_HOST: bool = true;
1052
1053 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1054 run.alias("intrinsic-test")
1055 }
1056
1057 fn is_default_step(_builder: &Builder<'_>) -> bool {
1058 true
1059 }
1060
1061 fn make_run(run: RunConfig<'_>) {
1062 let target = run.target;
1063 let builder = run.builder;
1064
1065 let is_explicit =
1066 builder.config.paths.iter().any(|p| p.to_string_lossy() == "intrinsic-test");
1067
1068 if target.contains("x86_64-unknown-linux") && builder.config.sde.is_none() && is_explicit {
1069 panic!(
1070 "SDE is required to run intrinsic-test. Please configure `build.sde` in config.toml."
1071 );
1072 }
1073
1074 builder.ensure(IntrinsicTest { host: target });
1075 }
1076
1077 fn run(self, builder: &Builder<'_>) {
1078 let host = self.host;
1079 if cfg!(test)
1080 || (!host.contains("aarch64-unknown-linux") && !host.contains("x86_64-unknown-linux"))
1081 {
1082 builder.info(&format!("Skipping intrinsic-test, as it is not available for {host}"));
1083 return;
1084 }
1085
1086 let (input_file, skip_file, cflags, sde_runner) = if host.contains("x86_64-unknown-linux") {
1087 let Some(sde) = &builder.config.sde else {
1088 builder.info("Skipping intrinsic-test because `build.sde` is not configured");
1089 return;
1090 };
1091
1092 let cpuid_def =
1093 builder.src.join("library/stdarch/ci/docker/x86_64-unknown-linux-gnu/cpuid.def");
1094 let sde_runner = format!(
1095 "{} -cpuid-in {} -rtm-mode full -tsx --",
1096 sde.display(),
1097 cpuid_def.display()
1098 );
1099
1100 (
1101 builder.src.join("library/stdarch/intrinsics_data/x86-intel.xml"),
1102 [
1103 builder
1104 .src
1105 .join("library/stdarch/crates/intrinsic-test/missing_x86_common.txt"),
1106 builder.src.join("library/stdarch/crates/intrinsic-test/missing_x86_gcc.txt"),
1107 ],
1108 "-I/usr/include/x86_64-linux-gnu/",
1109 Some(sde_runner),
1110 )
1111 } else if host.contains("aarch64-unknown-linux") {
1112 (
1113 builder.src.join("library/stdarch/intrinsics_data/arm_intrinsics.json"),
1114 [
1115 builder
1116 .src
1117 .join("library/stdarch/crates/intrinsic-test/missing_aarch64_common.txt"),
1118 builder
1119 .src
1120 .join("library/stdarch/crates/intrinsic-test/missing_aarch64_gcc.txt"),
1121 ],
1122 "-I/usr/aarch64-linux-gnu/include/",
1123 None,
1124 )
1125 } else {
1126 panic!("intrinsic-test only supports aarch64/x86_64 Linux, got {host}");
1127 };
1128
1129 let out_dir = builder.out.join(host).join("intrinsic-test");
1130 t!(fs::create_dir_all(&out_dir));
1131
1132 let crates_link = out_dir.join("crates");
1133 if !crates_link.exists() {
1134 t!(
1135 helpers::symlink_dir(
1136 &builder.config,
1137 &builder.src.join("library/stdarch/crates"),
1138 &crates_link
1139 ),
1140 format!("failed to symlink stdarch crates into {}", crates_link.display())
1141 );
1142 }
1143
1144 let mut cmd = builder.tool_cmd(Tool::IntrinsicTest);
1145 cmd.current_dir(&out_dir);
1146 cmd.arg(&input_file);
1147 cmd.arg("--target").arg(&*host.triple);
1148 for skip in &skip_file {
1149 cmd.arg("--skip").arg(skip);
1150 }
1151 cmd.arg("--sample-percentage").arg("100");
1152 cmd.arg("--cc-arg-style").arg("gcc");
1153 cmd.env("CC", builder.cc(host));
1154 cmd.env("CFLAGS", cflags);
1155 let Some(rustfmt_path) = builder.ensure(InternalRustfmt) else {
1158 eprintln!(
1159 "WARNING: intrinsic-test skipped because rustfmt is required but not available on this channel"
1160 );
1161 return;
1162 };
1163
1164 let mut path_dirs: Vec<PathBuf> = Vec::new();
1165 if let Some(cargo_dir) = builder.initial_cargo.parent() {
1166 path_dirs.push(cargo_dir.to_path_buf());
1167 }
1168 if let Some(rustfmt_dir) = rustfmt_path.parent() {
1169 path_dirs.push(rustfmt_dir.to_path_buf());
1170 }
1171 let old_path = env::var_os("PATH").unwrap_or_default();
1172 let new_path = env::join_paths(path_dirs.into_iter().chain(env::split_paths(&old_path)))
1173 .expect("could not build PATH for intrinsic-test");
1174 cmd.env("PATH", new_path);
1175 cmd.run(builder);
1176
1177 let tested_compiler = builder.compiler(builder.top_stage, host);
1178 builder.std(tested_compiler, host);
1179 let rustc = builder.rustc(tested_compiler);
1180
1181 let manifest = out_dir.join("rust_programs/Cargo.toml");
1182 let mut cargo = command(&builder.initial_cargo);
1183 cargo.arg("test");
1184 cargo.arg("--tests");
1185 cargo.arg("--manifest-path").arg(&manifest);
1186 cargo.arg("--target").arg(&*host.triple);
1187 cargo.arg("--profile").arg("release");
1188 cargo.env("CC", builder.cc(host));
1189 cargo.env("CFLAGS", cflags);
1190 cargo.env("RUSTC", rustc);
1191 cargo.env("RUSTC_BOOTSTRAP", "1");
1192 if let Some(runner) = sde_runner {
1193 cargo.env("CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER", runner);
1194 }
1195 cargo.run(builder);
1196 }
1197
1198 fn metadata(&self) -> Option<StepMetadata> {
1199 Some(StepMetadata::test("intrinsic-test", self.host))
1200 }
1201}
1202
1203#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1204pub struct Clippy {
1205 compilers: RustcPrivateCompilers,
1206}
1207
1208impl CommandLineStep for Clippy {
1209 type Output = ();
1210 const IS_HOST: bool = true;
1211
1212 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1213 run.suite_path("src/tools/clippy/tests").path("src/tools/clippy")
1214 }
1215
1216 fn is_default_step(_builder: &Builder<'_>) -> bool {
1217 false
1218 }
1219
1220 fn make_run(run: RunConfig<'_>) {
1221 run.builder.ensure(Clippy {
1222 compilers: RustcPrivateCompilers::new(
1223 run.builder,
1224 run.builder.top_stage,
1225 run.builder.host_target,
1226 ),
1227 });
1228 }
1229
1230 fn run(self, builder: &Builder<'_>) {
1232 let target = self.compilers.target();
1233
1234 let target_compiler = self.compilers.target_compiler();
1238 let build_compiler = self.compilers.build_compiler();
1239
1240 builder.ensure(compile::Rustc::new(build_compiler, target));
1244
1245 let mut cargo = tool::prepare_tool_cargo(
1246 builder,
1247 build_compiler,
1248 Mode::ToolRustcPrivate,
1249 target,
1250 Kind::Test,
1251 "src/tools/clippy",
1252 SourceType::InTree,
1253 &[],
1254 );
1255
1256 cargo.env("RUSTC_TEST_SUITE", builder.rustc(build_compiler));
1257 cargo.env("RUSTC_LIB_PATH", builder.rustc_libdir(build_compiler));
1258 let host_libs = builder
1259 .stage_out(build_compiler, Mode::ToolRustcPrivate)
1260 .join(builder.cargo_dir(Mode::ToolRustcPrivate));
1261 cargo.env("HOST_LIBS", host_libs);
1262
1263 builder.std(target_compiler, target);
1265 cargo.env("TEST_SYSROOT", builder.sysroot(target_compiler));
1266 cargo.env("TEST_RUSTC", builder.rustc(target_compiler));
1267 cargo.env("TEST_RUSTC_LIB", builder.rustc_libdir(target_compiler));
1268
1269 'partially_test: {
1271 let paths = &builder.config.paths[..];
1272 let mut test_names = Vec::new();
1273 for path in paths {
1274 match helpers::is_valid_test_suite_arg(path, "src/tools/clippy/tests", builder) {
1275 TestFilterCategory::Arg(path) => {
1276 test_names.push(path);
1277 }
1278 TestFilterCategory::Fullsuite => {
1279 break 'partially_test;
1281 }
1282 TestFilterCategory::Uninteresting => {}
1283 }
1284 }
1285 cargo.env("TESTNAME", test_names.join(","));
1286 }
1287
1288 cargo.add_rustc_lib_path(builder);
1289 let cargo = prepare_cargo_test(cargo, &[], &[], target, builder);
1290
1291 let _guard = builder.msg_test("clippy", target, target_compiler.stage);
1292
1293 if cargo.allow_failure().run(builder) {
1295 return;
1297 }
1298
1299 if !builder.config.cmd.bless() {
1300 crate::exit!(1);
1301 }
1302 }
1303
1304 fn metadata(&self) -> Option<StepMetadata> {
1305 Some(
1306 StepMetadata::test("clippy", self.compilers.target())
1307 .built_by(self.compilers.build_compiler()),
1308 )
1309 }
1310}
1311
1312fn bin_path_for_cargo(builder: &Builder<'_>, compiler: Compiler) -> OsString {
1313 let path = builder.sysroot(compiler).join("bin");
1314 let old_path = env::var_os("PATH").unwrap_or_default();
1315 env::join_paths(iter::once(path).chain(env::split_paths(&old_path))).expect("")
1316}
1317
1318#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1320pub struct RustdocTheme {
1321 test_compiler: Compiler,
1323}
1324
1325impl CommandLineStep for RustdocTheme {
1326 type Output = ();
1327 const IS_HOST: bool = true;
1328
1329 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1330 run.path("src/tools/rustdoc-themes")
1331 }
1332
1333 fn is_default_step(_builder: &Builder<'_>) -> bool {
1334 true
1335 }
1336
1337 fn make_run(run: RunConfig<'_>) {
1338 let test_compiler = run.builder.compiler(run.builder.top_stage, run.target);
1339
1340 run.builder.ensure(RustdocTheme { test_compiler });
1341 }
1342
1343 fn run(self, builder: &Builder<'_>) {
1344 let rustdoc = builder.bootstrap_out.join("rustdoc");
1345 let mut cmd = builder.tool_cmd(Tool::RustdocTheme);
1346 cmd.arg(rustdoc.to_str().unwrap())
1347 .arg(builder.src.join("src/librustdoc/html/static/css/rustdoc.css").to_str().unwrap())
1348 .env("RUSTC_STAGE", self.test_compiler.stage.to_string())
1349 .env("RUSTC_SYSROOT", builder.sysroot(self.test_compiler))
1350 .env(
1351 "RUSTDOC_LIBDIR",
1352 builder.sysroot_target_libdir(self.test_compiler, self.test_compiler.host),
1353 )
1354 .env("CFG_RELEASE_CHANNEL", &builder.config.channel)
1355 .env("RUSTDOC_REAL", builder.rustdoc_for_compiler(self.test_compiler))
1356 .env("RUSTC_BOOTSTRAP", "1");
1357 cmd.args(linker_args(builder, self.test_compiler.host, LldThreads::No));
1358
1359 cmd.delay_failure().run(builder);
1360 }
1361
1362 fn metadata(&self) -> Option<StepMetadata> {
1363 Some(
1364 StepMetadata::test("rustdoc-theme", self.test_compiler.host)
1365 .stage(self.test_compiler.stage),
1366 )
1367 }
1368}
1369
1370#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1372pub struct RustdocJSStd {
1373 build_compiler: Compiler,
1375 target: TargetSelection,
1376}
1377
1378impl CommandLineStep for RustdocJSStd {
1379 type Output = ();
1380 const IS_HOST: bool = true;
1381
1382 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1383 run.suite_path("tests/rustdoc-js-std")
1384 }
1385
1386 fn is_default_step(builder: &Builder<'_>) -> bool {
1387 builder.config.nodejs.is_some()
1388 }
1389
1390 fn make_run(run: RunConfig<'_>) {
1391 run.builder.ensure(RustdocJSStd {
1392 build_compiler: run.builder.compiler(run.builder.top_stage, run.builder.host_target),
1393 target: run.target,
1394 });
1395 }
1396
1397 fn run(self, builder: &Builder<'_>) {
1398 let nodejs =
1399 builder.config.nodejs.as_ref().expect("need nodejs to run rustdoc-js-std tests");
1400 let mut command = command(nodejs);
1401 command
1402 .arg(builder.src.join("src/tools/rustdoc-js/tester.js"))
1403 .arg("--crate-name")
1404 .arg("std")
1405 .arg("--resource-suffix")
1406 .arg(&builder.version)
1407 .arg("--doc-folder")
1408 .arg(builder.doc_out(self.target))
1409 .arg("--test-folder")
1410 .arg(builder.src.join("tests/rustdoc-js-std"));
1411
1412 let full_suite = builder.paths.iter().any(|path| {
1413 matches!(
1414 helpers::is_valid_test_suite_arg(path, "tests/rustdoc-js-std", builder),
1415 TestFilterCategory::Fullsuite
1416 )
1417 });
1418
1419 if !full_suite {
1422 for path in &builder.paths {
1423 if let TestFilterCategory::Arg(p) =
1424 helpers::is_valid_test_suite_arg(path, "tests/rustdoc-js-std", builder)
1425 {
1426 if !p.ends_with(".js") {
1427 eprintln!("A non-js file was given: `{}`", path.display());
1428 panic!("Cannot run rustdoc-js-std tests");
1429 }
1430 command.arg("--test-file").arg(path);
1431 }
1432 }
1433 }
1434
1435 builder.ensure(crate::core::build_steps::doc::Std::from_build_compiler(
1436 self.build_compiler,
1437 self.target,
1438 DocumentationFormat::Html,
1439 ));
1440 let _guard = builder.msg_test("rustdoc-js-std", self.target, self.build_compiler.stage);
1441 command.run(builder);
1442 }
1443
1444 fn metadata(&self) -> Option<StepMetadata> {
1445 Some(StepMetadata::test("rustdoc-js-std", self.target).stage(self.build_compiler.stage))
1446 }
1447}
1448
1449#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1450pub struct RustdocJSNotStd {
1451 pub target: TargetSelection,
1452 pub compiler: Compiler,
1453}
1454
1455impl CommandLineStep for RustdocJSNotStd {
1456 type Output = ();
1457 const IS_HOST: bool = true;
1458
1459 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1460 run.suite_path("tests/rustdoc-js")
1461 }
1462
1463 fn is_default_step(builder: &Builder<'_>) -> bool {
1464 builder.config.nodejs.is_some()
1465 }
1466
1467 fn make_run(run: RunConfig<'_>) {
1468 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1469 run.builder.ensure(RustdocJSNotStd { target: run.target, compiler });
1470 }
1471
1472 fn run(self, builder: &Builder<'_>) {
1473 builder.ensure(Compiletest {
1474 test_compiler: self.compiler,
1475 target: self.target,
1476 mode: CompiletestMode::RustdocJs,
1477 suite: "rustdoc-js",
1478 path: "tests/rustdoc-js",
1479 compare_mode: None,
1480 });
1481 }
1482}
1483
1484fn get_browser_ui_test_version_inner(
1485 builder: &Builder<'_>,
1486 yarn: &Path,
1487 global: bool,
1488) -> Option<String> {
1489 let mut command = command(yarn);
1490 command
1491 .arg("--cwd")
1492 .arg(&builder.build.out)
1493 .arg("list")
1494 .arg("--parseable")
1495 .arg("--long")
1496 .arg("--depth=0");
1497 if global {
1498 command.arg("--global");
1499 }
1500 let lines = command.allow_failure().cached().run_capture(builder).stdout();
1503 lines
1504 .lines()
1505 .find_map(|l| l.split(':').nth(1)?.strip_prefix("browser-ui-test@"))
1506 .map(|v| v.to_owned())
1507}
1508
1509fn get_browser_ui_test_version(builder: &Builder<'_>) -> Option<String> {
1510 let yarn = builder.config.yarn.as_deref()?;
1511 get_browser_ui_test_version_inner(builder, yarn, false)
1512 .or_else(|| get_browser_ui_test_version_inner(builder, yarn, true))
1513}
1514
1515#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1517pub struct RustdocGUI {
1518 test_compiler: Compiler,
1520 target: TargetSelection,
1521}
1522
1523impl CommandLineStep for RustdocGUI {
1524 type Output = ();
1525 const IS_HOST: bool = true;
1526
1527 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1528 run.suite_path("tests/rustdoc-gui")
1529 }
1530
1531 fn is_default_step(builder: &Builder<'_>) -> bool {
1532 builder.config.nodejs.is_some()
1533 && builder.test_target != TestTarget::DocOnly
1534 && get_browser_ui_test_version(builder).is_some()
1535 }
1536
1537 fn make_run(run: RunConfig<'_>) {
1538 let test_compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1539 run.builder.ensure(RustdocGUI { test_compiler, target: run.target });
1540 }
1541
1542 fn run(self, builder: &Builder<'_>) {
1543 builder.std(self.test_compiler, self.target);
1544 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
1545
1546 let mut cmd = builder.tool_cmd(Tool::RustdocGUITest);
1547
1548 let out_dir = builder.test_out(self.target).join("rustdoc-gui");
1549 build_stamp::clear_if_dirty(
1550 builder,
1551 &out_dir,
1552 &builder.rustdoc_for_compiler(self.test_compiler),
1553 );
1554
1555 if let Some(src) = builder.config.src.to_str() {
1556 cmd.arg("--rust-src").arg(src);
1557 }
1558
1559 if let Some(out_dir) = out_dir.to_str() {
1560 cmd.arg("--out-dir").arg(out_dir);
1561 }
1562
1563 if let Some(initial_cargo) = builder.config.initial_cargo.to_str() {
1564 cmd.arg("--initial-cargo").arg(initial_cargo);
1565 }
1566
1567 cmd.arg("--jobs").arg(builder.jobs().to_string());
1568
1569 cmd.env("RUSTDOC", builder.rustdoc_for_compiler(self.test_compiler))
1570 .env("RUSTC", builder.rustc(self.test_compiler));
1571
1572 add_rustdoc_cargo_linker_args(&mut cmd, builder, self.test_compiler.host, LldThreads::No);
1573
1574 let full_suite = builder.paths.iter().any(|path| {
1575 matches!(
1576 helpers::is_valid_test_suite_arg(path, "tests/rustdoc-js-std", builder),
1577 TestFilterCategory::Fullsuite
1578 )
1579 });
1580
1581 if !full_suite {
1584 for path in &builder.paths {
1585 if let TestFilterCategory::Arg(p) =
1586 helpers::is_valid_test_suite_arg(path, "tests/rustdoc-gui", builder)
1587 {
1588 if !p.ends_with(".goml") {
1589 eprintln!("A non-goml file was given: `{}`", path.display());
1590 panic!("Cannot run rustdoc-gui tests");
1591 }
1592 if let Some(name) = path.file_name().and_then(|f| f.to_str()) {
1593 cmd.arg("--goml-file").arg(name);
1594 }
1595 }
1596 }
1597 }
1598
1599 for test_arg in builder.config.test_args() {
1600 cmd.arg("--test-arg").arg(test_arg);
1601 }
1602
1603 if let Some(ref nodejs) = builder.config.nodejs {
1604 cmd.arg("--nodejs").arg(nodejs);
1605 }
1606
1607 if let Some(ref yarn) = builder.config.yarn {
1608 cmd.arg("--yarn").arg(yarn);
1609 }
1610
1611 let _time = helpers::timeit(builder);
1612 let _guard = builder.msg_test("rustdoc-gui", self.target, self.test_compiler.stage);
1613 try_run_tests(builder, &mut cmd, true, record_failed_tests);
1614 }
1615
1616 fn metadata(&self) -> Option<StepMetadata> {
1617 Some(StepMetadata::test("rustdoc-gui", self.target).stage(self.test_compiler.stage))
1618 }
1619}
1620
1621#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1626pub struct Tidy;
1627
1628impl CommandLineStep for Tidy {
1629 type Output = ();
1630 const IS_HOST: bool = true;
1631
1632 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1633 run.path("src/tools/tidy")
1634 }
1635
1636 fn is_default_step(builder: &Builder<'_>) -> bool {
1637 builder.test_target != TestTarget::DocOnly
1638 }
1639
1640 fn make_run(run: RunConfig<'_>) {
1641 run.builder.ensure(Tidy);
1642 }
1643
1644 fn run(self, builder: &Builder<'_>) {
1653 let mut cmd = builder.tool_cmd(Tool::Tidy);
1654 cmd.arg(format!("--root-path={}", builder.src.display()));
1655 cmd.arg(format!("--cargo-path={}", builder.initial_cargo.display()));
1656 cmd.arg(format!("--output-dir={}", builder.out.display()));
1657 let jobs = builder.config.jobs.unwrap_or_else(|| {
1659 8 * std::thread::available_parallelism().map_or(1, std::num::NonZeroUsize::get) as u32
1660 });
1661 cmd.arg(format!("--concurrency={jobs}"));
1662 if let Some(yarn) = &builder.config.yarn {
1664 cmd.arg(format!("--npm-path={}", yarn.display()));
1665 } else {
1666 cmd.arg("--npm-path=yarn");
1667 }
1668 if builder.is_verbose() {
1669 cmd.arg("--verbose");
1670 }
1671 if builder.config.cmd.bless() {
1672 cmd.arg("--bless");
1673 }
1674 if builder.config.is_running_on_ci() {
1675 cmd.arg("--ci=true");
1676 }
1677 if let Some(s) =
1678 builder.config.cmd.extra_checks().or(builder.config.tidy_extra_checks.as_deref())
1679 {
1680 cmd.arg(format!("--extra-checks={s}"));
1681 }
1682 let mut args = std::env::args_os();
1683 if args.any(|arg| arg == OsStr::new("--")) {
1684 cmd.arg("--");
1685 cmd.args(args);
1686 }
1687
1688 if builder.config.channel == "dev" || builder.config.channel == "nightly" {
1689 if !builder.config.json_output {
1690 builder.info("fmt check");
1691
1692 let Some(rustfmt) = builder.ensure(InternalRustfmt) else {
1695 let inferred_rustfmt_dir = builder.initial_sysroot.join("bin");
1696 eprintln!(
1697 "\
1698ERROR: no `rustfmt` binary found in {PATH}
1699INFO: `rust.channel` is currently set to \"{CHAN}\"
1700HELP: if you are testing a beta branch, set `rust.channel` to \"beta\" in the `bootstrap.toml` file
1701HELP: to skip test's attempt to check tidiness, pass `--skip src/tools/tidy` to `x.py test`",
1702 PATH = inferred_rustfmt_dir.display(),
1703 CHAN = builder.config.channel,
1704 );
1705 crate::exit!(1);
1706 };
1707 let all = false;
1708 crate::core::build_steps::format::format(
1709 builder,
1710 rustfmt,
1711 !builder.config.cmd.bless(),
1712 all,
1713 &[],
1714 );
1715 } else {
1716 eprintln!(
1717 "WARNING: `--json-output` is not supported on rustfmt, formatting will be skipped"
1718 );
1719 }
1720 }
1721
1722 builder.info("tidy check");
1723 cmd.delay_failure().run(builder);
1724
1725 builder.info("x.py completions check");
1726 let completion_paths = get_completion_paths(builder);
1727 if builder.config.cmd.bless() {
1728 builder.ensure(crate::core::build_steps::run::GenerateCompletions);
1729 } else if completion_paths
1730 .into_iter()
1731 .any(|(shell, path)| get_completion(shell, &path).is_some())
1732 {
1733 eprintln!(
1734 "x.py completions were changed; run `x.py run generate-completions` to update them"
1735 );
1736 crate::exit!(1);
1737 }
1738
1739 builder.info("x.py help check");
1740 if builder.config.cmd.bless() {
1741 builder.ensure(crate::core::build_steps::run::GenerateHelp);
1742 } else {
1743 let help_path = get_help_path(builder);
1744 let cur_help = std::fs::read_to_string(&help_path).unwrap_or_else(|err| {
1745 eprintln!("couldn't read {}: {}", help_path.display(), err);
1746 crate::exit!(1);
1747 });
1748 let new_help = top_level_help();
1749
1750 if new_help != cur_help {
1751 eprintln!("x.py help was changed; run `x.py run generate-help` to update it");
1752 crate::exit!(1);
1753 }
1754 }
1755 }
1756
1757 fn metadata(&self) -> Option<StepMetadata> {
1758 Some(StepMetadata::test("tidy", TargetSelection::default()))
1759 }
1760}
1761
1762#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1765pub struct CrateRunMakeSupport {
1766 host: TargetSelection,
1767}
1768
1769impl CommandLineStep for CrateRunMakeSupport {
1770 type Output = ();
1771 const IS_HOST: bool = true;
1772
1773 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1774 run.path("src/tools/run-make-support")
1775 }
1776
1777 fn make_run(run: RunConfig<'_>) {
1778 run.builder.ensure(CrateRunMakeSupport { host: run.target });
1779 }
1780
1781 fn run(self, builder: &Builder<'_>) {
1783 let host = self.host;
1784 let compiler = builder.compiler(0, host);
1785 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
1786
1787 let mut cargo = tool::prepare_tool_cargo(
1788 builder,
1789 compiler,
1790 Mode::ToolBootstrap,
1791 host,
1792 Kind::Test,
1793 "src/tools/run-make-support",
1794 SourceType::InTree,
1795 &[],
1796 );
1797 cargo.allow_features("test");
1798 run_cargo_test(
1799 cargo,
1800 &[],
1801 &[],
1802 "run-make-support self test",
1803 host,
1804 builder,
1805 record_failed_tests,
1806 );
1807 }
1808}
1809
1810#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1811pub struct CrateBuildHelper {
1812 host: TargetSelection,
1813}
1814
1815impl CommandLineStep for CrateBuildHelper {
1816 type Output = ();
1817 const IS_HOST: bool = true;
1818
1819 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1820 run.path("src/build_helper")
1821 }
1822
1823 fn make_run(run: RunConfig<'_>) {
1824 run.builder.ensure(CrateBuildHelper { host: run.target });
1825 }
1826
1827 fn run(self, builder: &Builder<'_>) {
1829 let host = self.host;
1830 let compiler = builder.compiler(0, host);
1831 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
1832
1833 let mut cargo = tool::prepare_tool_cargo(
1834 builder,
1835 compiler,
1836 Mode::ToolBootstrap,
1837 host,
1838 Kind::Test,
1839 "src/build_helper",
1840 SourceType::InTree,
1841 &[],
1842 );
1843 cargo.allow_features("test");
1844 run_cargo_test(
1845 cargo,
1846 &[],
1847 &[],
1848 "build_helper self test",
1849 host,
1850 builder,
1851 record_failed_tests,
1852 );
1853 }
1854}
1855
1856fn testdir(builder: &Builder<'_>, host: TargetSelection) -> PathBuf {
1857 builder.out.join(host).join("test")
1858}
1859
1860macro_rules! test {
1862 (
1863 $( #[$attr:meta] )* $name:ident {
1865 path: $path:expr,
1866 mode: $mode:expr,
1867 suite: $suite:expr,
1868 default: $default:expr
1869 $( , IS_HOST: $IS_HOST:expr )? $( , compare_mode: $compare_mode:expr )? $( , )? }
1873 ) => {
1874 $( #[$attr] )*
1875 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
1876 pub struct $name {
1877 test_compiler: Compiler,
1878 target: TargetSelection,
1879 }
1880
1881 impl CommandLineStep for $name {
1882 type Output = ();
1883 const IS_HOST: bool = (const {
1884 #[allow(unused_assignments, unused_mut)]
1885 let mut value = false;
1886 $( value = $IS_HOST; )?
1887 value
1888 });
1889
1890 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1891 run.suite_path($path)
1892 }
1893
1894 fn is_default_step(_builder: &Builder<'_>) -> bool {
1895 const { $default }
1896 }
1897
1898 fn make_run(run: RunConfig<'_>) {
1899 let test_compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1900
1901 run.builder.ensure($name { test_compiler, target: run.target });
1902 }
1903
1904 fn run(self, builder: &Builder<'_>) {
1905 builder.ensure(Compiletest {
1906 test_compiler: self.test_compiler,
1907 target: self.target,
1908 mode: const { $mode },
1909 suite: $suite,
1910 path: $path,
1911 compare_mode: (const {
1912 #[allow(unused_assignments, unused_mut)]
1913 let mut value = None;
1914 $( value = $compare_mode; )?
1915 value
1916 }),
1917 })
1918 }
1919 }
1920 };
1921}
1922
1923test!(Ui { path: "tests/ui", mode: CompiletestMode::Ui, suite: "ui", default: true });
1924
1925test!(Crashes {
1926 path: "tests/crashes",
1927 mode: CompiletestMode::Crashes,
1928 suite: "crashes",
1929 default: true,
1930});
1931
1932test!(CodegenLlvm {
1933 path: "tests/codegen-llvm",
1934 mode: CompiletestMode::Codegen,
1935 suite: "codegen-llvm",
1936 default: true
1937});
1938
1939test!(CodegenUnits {
1940 path: "tests/codegen-units",
1941 mode: CompiletestMode::CodegenUnits,
1942 suite: "codegen-units",
1943 default: true,
1944});
1945
1946test!(Incremental {
1947 path: "tests/incremental",
1948 mode: CompiletestMode::Incremental,
1949 suite: "incremental",
1950 default: true,
1951});
1952
1953test!(Debuginfo {
1954 path: "tests/debuginfo",
1955 mode: CompiletestMode::Debuginfo,
1956 suite: "debuginfo",
1957 default: true,
1958 compare_mode: Some("split-dwarf"),
1959});
1960
1961test!(UiFullDeps {
1962 path: "tests/ui-fulldeps",
1963 mode: CompiletestMode::Ui,
1964 suite: "ui-fulldeps",
1965 default: true,
1966 IS_HOST: true,
1967});
1968
1969test!(RustdocHtml {
1970 path: "tests/rustdoc-html",
1971 mode: CompiletestMode::RustdocHtml,
1972 suite: "rustdoc-html",
1973 default: true,
1974 IS_HOST: true,
1975});
1976test!(RustdocUi {
1977 path: "tests/rustdoc-ui",
1978 mode: CompiletestMode::Ui,
1979 suite: "rustdoc-ui",
1980 default: true,
1981 IS_HOST: true,
1982});
1983
1984test!(RustdocJson {
1985 path: "tests/rustdoc-json",
1986 mode: CompiletestMode::RustdocJson,
1987 suite: "rustdoc-json",
1988 default: true,
1989 IS_HOST: true,
1990});
1991
1992test!(Pretty {
1993 path: "tests/pretty",
1994 mode: CompiletestMode::Pretty,
1995 suite: "pretty",
1996 default: true,
1997 IS_HOST: true,
1998});
1999
2000test!(RunMake {
2001 path: "tests/run-make",
2002 mode: CompiletestMode::RunMake,
2003 suite: "run-make",
2004 default: true,
2005});
2006test!(RunMakeCargo {
2007 path: "tests/run-make-cargo",
2008 mode: CompiletestMode::RunMake,
2009 suite: "run-make-cargo",
2010 default: true
2011});
2012test!(BuildStd {
2013 path: "tests/build-std",
2014 mode: CompiletestMode::RunMake,
2015 suite: "build-std",
2016 default: false
2017});
2018
2019test!(AssemblyLlvm {
2020 path: "tests/assembly-llvm",
2021 mode: CompiletestMode::Assembly,
2022 suite: "assembly-llvm",
2023 default: true
2024});
2025
2026#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2029pub struct Coverage {
2030 pub compiler: Compiler,
2031 pub target: TargetSelection,
2032 pub(crate) mode: CompiletestMode,
2033}
2034
2035impl Coverage {
2036 const PATH: &'static str = "tests/coverage";
2037 const SUITE: &'static str = "coverage";
2038 const ALL_MODES: &[CompiletestMode] =
2039 &[CompiletestMode::CoverageMap, CompiletestMode::CoverageRun];
2040
2041 fn new(run: &RunConfig<'_>, mode: CompiletestMode) -> Self {
2042 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
2043 let target = run.target;
2044 Coverage { compiler, target, mode }
2045 }
2046}
2047
2048impl CommandLineStep for Coverage {
2049 type Output = ();
2050 const IS_HOST: bool = false;
2052
2053 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2054 run.suite_path(Coverage::PATH)
2061 }
2062
2063 fn is_default_step(_builder: &Builder<'_>) -> bool {
2064 true
2065 }
2066
2067 fn make_run(run: RunConfig<'_>) {
2068 for &mode in Coverage::ALL_MODES {
2072 if !run.builder.config.skip.iter().any(|skip| skip == Path::new(mode.as_str())) {
2073 run.builder.ensure(Coverage::new(&run, mode));
2074 }
2075 }
2076 }
2077
2078 fn run(self, builder: &Builder<'_>) {
2079 let Self { compiler, target, mode } = self;
2080 builder.ensure(Compiletest {
2083 test_compiler: compiler,
2084 target,
2085 mode,
2086 suite: Self::SUITE,
2087 path: Self::PATH,
2088 compare_mode: None,
2089 });
2090 }
2091}
2092
2093#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2101pub enum CoverageModeAlias {}
2102
2103impl CommandLineStep for CoverageModeAlias {
2104 type Output = ();
2105
2106 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2107 Coverage::ALL_MODES.iter().fold(run, |run, mode| run.alias(mode.as_str()))
2112 }
2113
2114 fn is_default_step(_builder: &Builder<'_>) -> bool {
2115 false
2116 }
2117
2118 fn make_run(run: RunConfig<'_>) {
2119 for path in &run.paths {
2120 let single_path = &path.assert_single_path().path;
2121 for &mode in Coverage::ALL_MODES {
2122 if single_path == Path::new(mode.as_str()) {
2123 run.builder.ensure(Coverage::new(&run, mode));
2126 }
2127 }
2128 }
2129 }
2130
2131 fn run(self, _builder: &Builder<'_>) {
2132 unreachable!("never instantiated; `make_run` creates a Coverage step instead");
2133 }
2134}
2135
2136test!(CoverageRunRustdoc {
2137 path: "tests/coverage-run-rustdoc",
2138 mode: CompiletestMode::CoverageRun,
2139 suite: "coverage-run-rustdoc",
2140 default: true,
2141 IS_HOST: true,
2142});
2143
2144#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2146pub struct MirOpt {
2147 pub compiler: Compiler,
2148 pub target: TargetSelection,
2149}
2150
2151impl CommandLineStep for MirOpt {
2152 type Output = ();
2153
2154 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2155 run.suite_path("tests/mir-opt")
2156 }
2157
2158 fn is_default_step(_builder: &Builder<'_>) -> bool {
2159 true
2160 }
2161
2162 fn make_run(run: RunConfig<'_>) {
2163 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
2164 run.builder.ensure(MirOpt { compiler, target: run.target });
2165 }
2166
2167 fn run(self, builder: &Builder<'_>) {
2168 let run = |target| {
2169 builder.ensure(Compiletest {
2170 test_compiler: self.compiler,
2171 target,
2172 mode: CompiletestMode::MirOpt,
2173 suite: "mir-opt",
2174 path: "tests/mir-opt",
2175 compare_mode: None,
2176 })
2177 };
2178
2179 run(self.target);
2180
2181 if builder.config.cmd.bless() {
2184 for target in ["aarch64-unknown-linux-gnu", "i686-pc-windows-msvc"] {
2190 run(TargetSelection::from_user(target));
2191 }
2192
2193 for target in ["x86_64-apple-darwin", "i686-unknown-linux-musl"] {
2194 let target = TargetSelection::from_user(target);
2195 let panic_abort_target = builder.ensure(MirOptPanicAbortSyntheticTarget {
2196 compiler: self.compiler,
2197 base: target,
2198 });
2199 run(panic_abort_target);
2200 }
2201 }
2202 }
2203}
2204
2205#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2211struct Compiletest {
2212 test_compiler: Compiler,
2214 target: TargetSelection,
2215 mode: CompiletestMode,
2216 suite: &'static str,
2217 path: &'static str,
2218 compare_mode: Option<&'static str>,
2219}
2220
2221impl Step for Compiletest {
2222 type Output = ();
2223
2224 fn run(self, builder: &Builder<'_>) {
2225 if builder.test_target == TestTarget::DocOnly {
2226 return;
2227 }
2228
2229 if builder.top_stage == 0 && !builder.config.compiletest_allow_stage0 {
2230 eprintln!("\
2231ERROR: `--stage 0` runs compiletest on the stage0 (precompiled) compiler, not your local changes, and will almost always cause tests to fail
2232HELP: to test the compiler or standard library, omit the stage or explicitly use `--stage 1` instead
2233NOTE: 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`."
2234 );
2235 crate::exit!(1);
2236 }
2237
2238 let mut test_compiler = self.test_compiler;
2239 let target = self.target;
2240 let mode = self.mode;
2241 let suite = self.suite;
2242 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
2243
2244 let suite_path = self.path;
2246
2247 if !builder.config.codegen_tests && mode == CompiletestMode::Codegen {
2249 return;
2250 }
2251
2252 let query_compiler;
2259 let (stage, stage_id) = if suite == "ui-fulldeps" && test_compiler.stage == 1 {
2260 query_compiler = Some(test_compiler);
2263 let build = builder.build.host_target;
2267 test_compiler = builder.compiler(test_compiler.stage - 1, build);
2268 let test_stage = test_compiler.stage + 1;
2269 (test_stage, format!("stage{test_stage}-{build}"))
2270 } else {
2271 query_compiler = None;
2272 let stage = test_compiler.stage;
2273 (stage, format!("stage{stage}-{target}"))
2274 };
2275
2276 if suite.ends_with("fulldeps") {
2277 builder.ensure(compile::Rustc::new(test_compiler, target));
2278 }
2279
2280 if builder.config.wasm_proc_macros {
2282 builder.ensure(compile::Std::new(
2283 test_compiler,
2284 TargetSelection::from_user("wasm32-wasip2"),
2285 ));
2286 }
2287
2288 if suite == "debuginfo" {
2289 builder.ensure(dist::DebuggerScripts {
2290 sysroot: builder.sysroot(test_compiler).to_path_buf(),
2291 target,
2292 });
2293 }
2294 if mode == CompiletestMode::RunMake {
2295 builder.tool_exe(Tool::RunMakeSupport);
2296 }
2297
2298 if suite == "mir-opt" {
2300 builder.ensure(
2301 compile::Std::new(test_compiler, test_compiler.host).is_for_mir_opt_tests(true),
2302 );
2303 } else {
2304 builder.std(test_compiler, test_compiler.host);
2305 }
2306
2307 let mut cmd = builder.tool_cmd(Tool::Compiletest);
2308
2309 if suite == "mir-opt" {
2310 builder.ensure(compile::Std::new(test_compiler, target).is_for_mir_opt_tests(true));
2311 } else {
2312 builder.std(test_compiler, target);
2313 }
2314
2315 builder.ensure(RemoteCopyLibs { build_compiler: test_compiler, target });
2316
2317 cmd.arg("--stage").arg(stage.to_string());
2321 cmd.arg("--stage-id").arg(stage_id);
2322
2323 cmd.arg("--compile-lib-path").arg(builder.rustc_libdir(test_compiler));
2324 cmd.arg("--run-lib-path").arg(builder.sysroot_target_libdir(test_compiler, target));
2325 cmd.arg("--rustc-path").arg(builder.rustc(test_compiler));
2326 if let Some(query_compiler) = query_compiler {
2327 cmd.arg("--query-rustc-path").arg(builder.rustc(query_compiler));
2328 }
2329
2330 cmd.arg("--minicore-path")
2333 .arg(builder.src.join("tests").join("auxiliary").join("minicore.rs"));
2334
2335 let is_rustdoc = suite == "rustdoc-ui" || suite == "rustdoc-js";
2336
2337 if builder.config.wasm_proc_macros {
2338 cmd.arg("--wasm-proc-macros");
2339 }
2340
2341 if mode == CompiletestMode::RunMake {
2356 let stage0_rustc_path = builder.compiler(0, test_compiler.host);
2359 cmd.arg("--stage0-rustc-path").arg(builder.rustc(stage0_rustc_path));
2360
2361 if matches!(suite, "run-make-cargo" | "build-std") {
2362 let cargo_path = if test_compiler.stage == 0 {
2363 builder.initial_cargo.clone()
2365 } else {
2366 builder
2367 .ensure(tool::Cargo::from_build_compiler(
2368 builder.compiler(test_compiler.stage - 1, test_compiler.host),
2369 test_compiler.host,
2370 ))
2371 .tool_path
2372 };
2373
2374 cmd.arg("--cargo-path").arg(cargo_path);
2375 }
2376 }
2377
2378 if matches!(
2380 mode,
2381 CompiletestMode::RunMake
2382 | CompiletestMode::RustdocHtml
2383 | CompiletestMode::RustdocJs
2384 | CompiletestMode::RustdocJson
2385 ) || matches!(suite, "rustdoc-ui" | "coverage-run-rustdoc")
2386 {
2387 cmd.arg("--rustdoc-path").arg(builder.rustdoc_for_compiler(test_compiler));
2388 }
2389
2390 if mode == CompiletestMode::RustdocJson {
2391 let json_compiler = builder.compiler(0, builder.host_target);
2393 cmd.arg("--jsondocck-path")
2394 .arg(builder.ensure(tool::JsonDocCk { compiler: json_compiler, target }).tool_path);
2395 cmd.arg("--jsondoclint-path").arg(
2396 builder.ensure(tool::JsonDocLint { compiler: json_compiler, target }).tool_path,
2397 );
2398 }
2399
2400 if matches!(mode, CompiletestMode::CoverageMap | CompiletestMode::CoverageRun) {
2401 let coverage_dump = builder.tool_exe(Tool::CoverageDump);
2402 cmd.arg("--coverage-dump-path").arg(coverage_dump);
2403 }
2404
2405 cmd.arg("--src-root").arg(&builder.src);
2406 cmd.arg("--src-test-suite-root").arg(builder.src.join("tests").join(suite));
2407
2408 cmd.arg("--build-root").arg(&builder.out);
2412 cmd.arg("--build-test-suite-root").arg(testdir(builder, test_compiler.host).join(suite));
2413
2414 let sysroot = if builder.top_stage == 0 {
2419 builder.initial_sysroot.clone()
2420 } else {
2421 builder.sysroot(test_compiler)
2422 };
2423
2424 cmd.arg("--sysroot-base").arg(sysroot);
2425
2426 cmd.arg("--suite").arg(suite);
2427 cmd.arg("--mode").arg(mode.as_str());
2428 cmd.arg("--target").arg(target.rustc_target_arg());
2429 cmd.arg("--host").arg(&*test_compiler.host.triple);
2430
2431 let filecheck = builder.ensure(llvm::FileCheck { target: builder.config.host_target });
2432 cmd.arg("--llvm-filecheck").arg(filecheck);
2433
2434 if let Some(codegen_backend) = builder.config.cmd.test_codegen_backend() {
2435 if !builder
2436 .config
2437 .enabled_codegen_backends(test_compiler.host)
2438 .contains(codegen_backend)
2439 {
2440 eprintln!(
2441 "\
2442ERROR: No configured backend named `{name}`
2443HELP: You can add it into `bootstrap.toml` in `rust.codegen-backends = [{name:?}]`",
2444 name = codegen_backend.name(),
2445 );
2446 crate::exit!(1);
2447 }
2448
2449 if let CodegenBackendKind::Gcc = codegen_backend
2450 && builder.config.rustc_debug_assertions
2451 {
2452 eprintln!(
2453 r#"WARNING: Running tests with the GCC codegen backend while rustc debug assertions are enabled. This might lead to test failures.
2454Please disable assertions with `rust.debug-assertions = false`.
2455 "#
2456 );
2457 }
2458
2459 cmd.arg("--override-codegen-backend").arg(codegen_backend.name());
2462 cmd.arg("--default-codegen-backend").arg(codegen_backend.name());
2465 } else {
2466 cmd.arg("--default-codegen-backend")
2469 .arg(builder.config.default_codegen_backend(test_compiler.host).name());
2470 }
2471 if builder.config.cmd.bypass_ignore_backends() {
2472 cmd.arg("--bypass-ignore-backends");
2473 }
2474
2475 if builder.build.config.llvm_enzyme {
2476 cmd.arg("--has-enzyme");
2477 }
2478
2479 if builder.build.config.llvm_offload {
2480 cmd.arg("--has-offload");
2481 }
2482
2483 if builder.config.cmd.bless() {
2484 cmd.arg("--bless");
2485 }
2486
2487 if builder.config.cmd.force_rerun() {
2488 cmd.arg("--force-rerun");
2489 }
2490
2491 if builder.config.cmd.no_capture() {
2492 cmd.arg("--no-capture");
2493 }
2494
2495 let compare_mode =
2496 builder.config.cmd.compare_mode().or_else(|| {
2497 if builder.config.test_compare_mode { self.compare_mode } else { None }
2498 });
2499
2500 if let Some(ref pass) = builder.config.cmd.pass() {
2501 cmd.arg("--pass");
2502 cmd.arg(pass);
2503 }
2504
2505 if let Some(ref run) = builder.config.cmd.run() {
2506 cmd.arg("--run");
2507 cmd.arg(run);
2508 }
2509
2510 if let Some(ref nodejs) = builder.config.nodejs {
2511 cmd.arg("--nodejs").arg(nodejs);
2512 } else if mode == CompiletestMode::RustdocJs {
2513 panic!("need nodejs to run rustdoc-js suite");
2514 }
2515 if builder.config.rust_optimize_tests {
2516 cmd.arg("--optimize-tests");
2517 }
2518 if builder.config.rust_randomize_layout {
2519 cmd.arg("--rust-randomized-layout");
2520 }
2521 if builder.config.cmd.only_modified() {
2522 cmd.arg("--only-modified");
2523 }
2524 if let Some(compiletest_diff_tool) = &builder.config.compiletest_diff_tool {
2525 cmd.arg("--compiletest-diff-tool").arg(compiletest_diff_tool);
2526 }
2527
2528 let mut flags = if is_rustdoc { Vec::new() } else { vec!["-Crpath".to_string()] };
2529 flags.push(format!(
2530 "-Cdebuginfo={}",
2531 if mode == CompiletestMode::Codegen {
2532 if builder.config.rust_debuginfo_level_tests
2535 != crate::core::config::DebuginfoLevel::None
2536 {
2537 println!(
2538 "NOTE: ignoring `rust.debuginfo-level-tests={}` for codegen tests",
2539 builder.config.rust_debuginfo_level_tests
2540 );
2541 }
2542 crate::core::config::DebuginfoLevel::None
2543 } else {
2544 builder.config.rust_debuginfo_level_tests
2545 }
2546 ));
2547 flags.extend(builder.config.cmd.compiletest_rustc_args().iter().map(|s| s.to_string()));
2548
2549 if suite != "mir-opt" {
2550 if let Some(linker) = builder.linker(target) {
2551 cmd.arg("--target-linker").arg(linker);
2552 }
2553 if let Some(linker) = builder.linker(test_compiler.host) {
2554 cmd.arg("--host-linker").arg(linker);
2555 }
2556 }
2557
2558 if suite == "ui-fulldeps" && target.ends_with("darwin") {
2560 flags.push("-Alinker_messages".into());
2561 }
2562
2563 let mut hostflags = flags.clone();
2564 hostflags.extend(linker_flags(builder, test_compiler.host, LldThreads::No));
2565
2566 let mut targetflags = flags;
2567
2568 if suite == "ui" || suite == "incremental" {
2570 builder.ensure(TestHelpers { target: test_compiler.host });
2571 builder.ensure(TestHelpers { target });
2572 hostflags.push(format!(
2573 "-Lnative={}",
2574 builder.test_helpers_out(test_compiler.host).display()
2575 ));
2576 let target_helpers = builder.test_helpers_out(target);
2577 targetflags.push(format!("-Lnative={}", target_helpers.display()));
2578 if target.is_pauthtest() {
2579 targetflags.push(format!("-Clink-arg=-Wl,-rpath,{}", target_helpers.display()));
2582 }
2583 }
2584
2585 for flag in hostflags {
2586 cmd.arg("--host-rustcflags").arg(flag);
2587 }
2588 for flag in targetflags {
2589 cmd.arg("--target-rustcflags").arg(flag);
2590 }
2591 if target.is_synthetic() {
2592 cmd.arg("--target-rustcflags").arg("-Zunstable-options");
2593 }
2594
2595 cmd.arg("--python").arg(
2596 builder.config.python.as_ref().expect("python is required for running rustdoc tests"),
2597 );
2598
2599 let android = android::discover_android(builder, target);
2601 if let Some(android::Android { adb_path, adb_test_dir, android_cross_path }) = &android {
2602 cmd.arg("--adb-path").arg(adb_path);
2603 cmd.arg("--adb-test-dir").arg(adb_test_dir);
2604 cmd.arg("--android-cross-path").arg(android_cross_path);
2605 }
2606
2607 if mode == CompiletestMode::Debuginfo {
2608 if let Some(debuggers::Cdb { cdb }) = debuggers::discover_cdb(target) {
2609 cmd.arg("--cdb").arg(cdb);
2610 }
2611
2612 if let Some(debuggers::Gdb { gdb }) = debuggers::discover_gdb(builder, android.as_ref())
2613 {
2614 cmd.arg("--gdb").arg(gdb);
2615 }
2616
2617 if let Some(debuggers::Lldb { lldb_exe, lldb_version }) =
2618 debuggers::discover_lldb(builder)
2619 {
2620 cmd.arg("--lldb").arg(lldb_exe);
2621 cmd.arg("--lldb-version").arg(lldb_version);
2622 }
2623 }
2624
2625 if helpers::forcing_clang_based_tests() {
2626 let clang_exe = builder.llvm_out(target).join("bin").join("clang");
2627 cmd.arg("--run-clang-based-tests-with").arg(clang_exe);
2628 }
2629
2630 for exclude in &builder.config.skip {
2631 cmd.arg("--skip");
2632 cmd.arg(exclude);
2633 }
2634
2635 let mut paths = match &builder.config.cmd {
2637 Subcommand::Test { .. } => &builder.config.paths[..],
2638 _ => &[],
2639 };
2640
2641 let mut paths_v;
2644 if mode == CompiletestMode::RustdocJs {
2645 paths_v = paths.to_vec();
2646 for p in &mut paths_v {
2647 if let Some(ext) = p.extension()
2648 && ext == "js"
2649 {
2650 p.set_extension("rs");
2651 }
2652 }
2653 paths = &paths_v;
2654 }
2655
2656 let mut test_args = Vec::new();
2658 for p in paths {
2659 match helpers::is_valid_test_suite_arg(p, suite_path, builder) {
2660 TestFilterCategory::Fullsuite => {
2661 test_args.clear();
2666 break;
2667 }
2668 TestFilterCategory::Arg(a) => test_args.push(a),
2669 TestFilterCategory::Uninteresting => {}
2670 }
2671 }
2672
2673 test_args.append(&mut builder.config.test_args());
2674
2675 if cfg!(windows) {
2678 let test_args_win: Vec<String> =
2679 test_args.iter().map(|s| s.replace('/', "\\")).collect();
2680 cmd.args(&test_args_win);
2681 } else {
2682 cmd.args(&test_args);
2683 }
2684
2685 if builder.is_verbose() {
2686 cmd.arg("--verbose");
2687 }
2688
2689 if builder.config.cmd.verbose_run_make_subprocess_output() {
2690 cmd.arg("--verbose-run-make-subprocess-output");
2691 }
2692
2693 if builder.config.rustc_debug_assertions {
2694 cmd.arg("--with-rustc-debug-assertions");
2695 }
2696
2697 if builder.config.std_debug_assertions {
2698 cmd.arg("--with-std-debug-assertions");
2699 }
2700
2701 if builder.config.rust_remap_debuginfo {
2702 cmd.arg("--with-std-remap-debuginfo");
2703 }
2704
2705 cmd.arg("--jobs").arg(builder.jobs().to_string());
2706
2707 let mut llvm_components_passed = false;
2708 let mut copts_passed = false;
2709 if builder.config.llvm_enabled(test_compiler.host) {
2710 let llvm::LlvmOutput { host_llvm_config, .. } =
2711 builder.ensure(llvm::Llvm { target: builder.config.host_target });
2712 if !builder.config.dry_run() {
2713 let llvm_version = get_llvm_version(builder, &host_llvm_config);
2714 let llvm_components = command(&host_llvm_config)
2715 .cached()
2716 .arg("--components")
2717 .run_capture_stdout(builder)
2718 .stdout();
2719 cmd.arg("--llvm-version")
2721 .arg(llvm_version.trim())
2722 .arg("--llvm-components")
2723 .arg(llvm_components.trim());
2724 llvm_components_passed = true;
2725 }
2726 if !builder.config.is_rust_llvm(target) {
2727 cmd.arg("--system-llvm");
2728 }
2729
2730 if !builder.config.dry_run() && suite.ends_with("fulldeps") {
2735 let llvm_libdir = command(&host_llvm_config)
2736 .cached()
2737 .arg("--libdir")
2738 .run_capture_stdout(builder)
2739 .stdout();
2740 let link_llvm = if target.is_msvc() {
2741 format!("-Clink-arg=-LIBPATH:{llvm_libdir}")
2742 } else {
2743 format!("-Clink-arg=-L{llvm_libdir}")
2744 };
2745 cmd.arg("--host-rustcflags").arg(link_llvm);
2746 }
2747
2748 if !builder.config.dry_run()
2749 && matches!(mode, CompiletestMode::RunMake | CompiletestMode::CoverageRun)
2750 {
2751 let llvm_bin_path = host_llvm_config
2756 .parent()
2757 .expect("Expected llvm-config to be contained in directory");
2758 assert!(llvm_bin_path.is_dir());
2759 cmd.arg("--llvm-bin-dir").arg(llvm_bin_path);
2760 }
2761
2762 if !builder.config.dry_run() && mode == CompiletestMode::RunMake {
2763 if builder.config.lld_enabled {
2765 let lld_install_root =
2766 builder.ensure(llvm::Lld { target: builder.config.host_target });
2767
2768 let lld_bin_path = lld_install_root.join("bin");
2769
2770 let old_path = env::var_os("PATH").unwrap_or_default();
2771 let new_path = env::join_paths(
2772 std::iter::once(lld_bin_path).chain(env::split_paths(&old_path)),
2773 )
2774 .expect("Could not add LLD bin path to PATH");
2775 cmd.env("PATH", new_path);
2776 }
2777 }
2778 }
2779
2780 if !builder.config.dry_run() && mode == CompiletestMode::RunMake {
2783 let mut cflags = builder.cc_handled_cflags(target, CLang::C);
2784 cflags.extend(builder.cc_unhandled_cflags(target, GitRepo::Rustc, CLang::C));
2785 let mut cxxflags = builder.cc_handled_cflags(target, CLang::Cxx);
2786 cxxflags.extend(builder.cc_unhandled_cflags(target, GitRepo::Rustc, CLang::Cxx));
2787 cmd.arg("--cc")
2788 .arg(builder.cc(target))
2789 .arg("--cxx")
2790 .arg(builder.cxx(target).unwrap())
2791 .arg("--cflags")
2792 .arg(cflags.join(" "))
2793 .arg("--cxxflags")
2794 .arg(cxxflags.join(" "));
2795 copts_passed = true;
2796 if let Some(ar) = builder.ar(target) {
2797 cmd.arg("--ar").arg(ar);
2798 }
2799 }
2800
2801 if !llvm_components_passed {
2802 cmd.arg("--llvm-components").arg("");
2803 }
2804 if !copts_passed {
2805 cmd.arg("--cc")
2806 .arg("")
2807 .arg("--cxx")
2808 .arg("")
2809 .arg("--cflags")
2810 .arg("")
2811 .arg("--cxxflags")
2812 .arg("");
2813 }
2814
2815 if builder.remote_tested(target) {
2816 cmd.arg("--remote-test-client").arg(builder.tool_exe(Tool::RemoteTestClient));
2817 } else if let Some(tool) = builder.runner(target) {
2818 cmd.arg("--runner").arg(tool);
2819 }
2820
2821 if suite != "mir-opt" {
2822 if !builder.config.dry_run() && target.is_msvc() {
2828 for (k, v) in builder.cc[&target].env() {
2829 if k != "PATH" {
2830 cmd.env(k, v);
2831 }
2832 }
2833 }
2834 }
2835
2836 if !builder.config.dry_run()
2838 && target.contains("msvc")
2839 && builder.config.sanitizers_enabled(target)
2840 {
2841 cmd.env("ASAN_WIN_CONTINUE_ON_INTERCEPTION_FAILURE", "1");
2844 let asan_runtime_path = builder.cc[&target].path().parent().unwrap().to_path_buf();
2846 let old_path = cmd
2847 .get_envs()
2848 .find_map(|(k, v)| (k == "PATH").then_some(v))
2849 .flatten()
2850 .map_or_else(|| env::var_os("PATH").unwrap_or_default(), |v| v.to_owned());
2851 let new_path = env::join_paths(
2852 env::split_paths(&old_path).chain(std::iter::once(asan_runtime_path)),
2853 )
2854 .expect("Could not add ASAN runtime path to PATH");
2855 cmd.env("PATH", new_path);
2856 }
2857
2858 cmd.env_remove("CARGO");
2861
2862 cmd.env("RUSTC_BOOTSTRAP", "1");
2863 cmd.env("RUSTC_FORCE_RUSTC_VERSION", "compiletest");
2866 cmd.env("DOC_RUST_LANG_ORG_CHANNEL", builder.doc_rust_lang_org_channel());
2867 builder.add_rust_test_threads(&mut cmd);
2868
2869 if builder.config.sanitizers_enabled(target) {
2870 cmd.env("RUSTC_SANITIZER_SUPPORT", "1");
2871 }
2872
2873 if builder.config.profiler_enabled(target) {
2874 cmd.arg("--profiler-runtime");
2875 }
2876
2877 cmd.env("RUST_TEST_TMPDIR", builder.tempdir());
2878
2879 if builder.config.cmd.rustfix_coverage() {
2880 cmd.arg("--rustfix-coverage");
2881 }
2882
2883 cmd.arg("--channel").arg(&builder.config.channel);
2884
2885 if !builder.config.omit_git_hash {
2886 cmd.arg("--git-hash");
2887 }
2888
2889 let git_config = builder.config.git_config();
2890 cmd.arg("--nightly-branch").arg(git_config.nightly_branch);
2891 cmd.arg("--git-merge-commit-email").arg(git_config.git_merge_commit_email);
2892
2893 #[cfg(feature = "build-metrics")]
2894 builder.metrics.begin_test_suite(
2895 build_helper::metrics::TestSuiteMetadata::Compiletest {
2896 suite: suite.into(),
2897 mode: mode.to_string(),
2898 compare_mode: None,
2899 target: self.target.triple.to_string(),
2900 host: self.test_compiler.host.triple.to_string(),
2901 stage: self.test_compiler.stage,
2902 },
2903 builder,
2904 );
2905
2906 let _group = builder.msg_test(
2907 format!("with compiletest suite={suite} mode={mode}"),
2908 target,
2909 test_compiler.stage,
2910 );
2911 try_run_tests(builder, &mut cmd, false, record_failed_tests.clone());
2912
2913 if let Some(compare_mode) = compare_mode {
2914 cmd.arg("--compare-mode").arg(compare_mode);
2915
2916 #[cfg(feature = "build-metrics")]
2917 builder.metrics.begin_test_suite(
2918 build_helper::metrics::TestSuiteMetadata::Compiletest {
2919 suite: suite.into(),
2920 mode: mode.to_string(),
2921 compare_mode: Some(compare_mode.into()),
2922 target: self.target.triple.to_string(),
2923 host: self.test_compiler.host.triple.to_string(),
2924 stage: self.test_compiler.stage,
2925 },
2926 builder,
2927 );
2928
2929 builder.info(&format!(
2930 "Check compiletest suite={} mode={} compare_mode={} ({} -> {})",
2931 suite, mode, compare_mode, test_compiler.host, target
2932 ));
2933 let _time = helpers::timeit(builder);
2934 try_run_tests(builder, &mut cmd, false, record_failed_tests);
2935 }
2936 }
2937
2938 fn metadata(&self) -> Option<StepMetadata> {
2939 Some(
2940 StepMetadata::test(&format!("compiletest-{}", self.suite), self.target)
2941 .stage(self.test_compiler.stage),
2942 )
2943 }
2944}
2945
2946#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2948struct BookTest {
2949 test_compiler: Compiler,
2950 path: PathBuf,
2951 name: &'static str,
2952 is_ext_doc: bool,
2953 dependencies: Vec<&'static str>,
2954}
2955
2956impl Step for BookTest {
2957 type Output = ();
2958
2959 fn run(self, builder: &Builder<'_>) {
2960 if self.is_ext_doc {
2970 self.run_ext_doc(builder);
2971 } else {
2972 self.run_local_doc(builder);
2973 }
2974 }
2975}
2976
2977impl BookTest {
2978 fn run_ext_doc(self, builder: &Builder<'_>) {
2981 let test_compiler = self.test_compiler;
2982
2983 builder.std(test_compiler, test_compiler.host);
2984
2985 let mut rustdoc_path = builder.rustdoc_for_compiler(test_compiler);
2988 rustdoc_path.pop();
2989 let old_path = env::var_os("PATH").unwrap_or_default();
2990 let new_path = env::join_paths(iter::once(rustdoc_path).chain(env::split_paths(&old_path)))
2991 .expect("could not add rustdoc to PATH");
2992
2993 let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook);
2994 let path = builder.src.join(&self.path);
2995 rustbook_cmd.env("RUSTC_BOOTSTRAP", "1");
2997 rustbook_cmd.env("PATH", new_path).arg("test").arg(path);
2998
2999 let libs = if !self.dependencies.is_empty() {
3004 let mut lib_paths = vec![];
3005 for dep in self.dependencies {
3006 let mode = Mode::ToolRustcPrivate;
3007 let target = builder.config.host_target;
3008 let cargo = tool::prepare_tool_cargo(
3009 builder,
3010 test_compiler,
3011 mode,
3012 target,
3013 Kind::Build,
3014 dep,
3015 SourceType::Submodule,
3016 &[],
3017 );
3018
3019 let stamp = BuildStamp::new(&builder.cargo_out(test_compiler, mode, target))
3020 .with_prefix(PathBuf::from(dep).file_name().and_then(|v| v.to_str()).unwrap());
3021
3022 let output_paths =
3023 run_cargo(builder, cargo, vec![], &stamp, vec![], ArtifactKeepMode::OnlyRlib);
3024 let directories = output_paths
3025 .into_iter()
3026 .filter_map(|p| p.parent().map(ToOwned::to_owned))
3027 .fold(HashSet::new(), |mut set, dir| {
3028 set.insert(dir);
3029 set
3030 });
3031
3032 lib_paths.extend(directories);
3033 }
3034 lib_paths
3035 } else {
3036 vec![]
3037 };
3038
3039 if !libs.is_empty() {
3040 let paths = libs
3041 .into_iter()
3042 .map(|path| path.into_os_string())
3043 .collect::<Vec<OsString>>()
3044 .join(OsStr::new(","));
3045 rustbook_cmd.args([OsString::from("--library-path"), paths]);
3046 }
3047
3048 builder.add_rust_test_threads(&mut rustbook_cmd);
3049 let _guard = builder.msg_test(
3050 format_args!("mdbook {}", self.path.display()),
3051 test_compiler.host,
3052 test_compiler.stage,
3053 );
3054 let _time = helpers::timeit(builder);
3055 let toolstate = if rustbook_cmd.delay_failure().run(builder) {
3056 ToolState::TestPass
3057 } else {
3058 ToolState::TestFail
3059 };
3060 builder.save_toolstate(self.name, toolstate);
3061 }
3062
3063 fn run_local_doc(self, builder: &Builder<'_>) {
3065 let test_compiler = self.test_compiler;
3066 let host = self.test_compiler.host;
3067
3068 builder.std(test_compiler, host);
3069
3070 let _guard = builder.msg_test(
3071 format!("book {}", self.name),
3072 test_compiler.host,
3073 test_compiler.stage,
3074 );
3075
3076 let mut stack = vec![builder.src.join(self.path)];
3079 let _time = helpers::timeit(builder);
3080 let mut files = Vec::new();
3081 while let Some(p) = stack.pop() {
3082 if p.is_dir() {
3083 stack.extend(t!(p.read_dir()).map(|p| t!(p).path()));
3084 continue;
3085 }
3086
3087 if p.extension().and_then(|s| s.to_str()) != Some("md") {
3088 continue;
3089 }
3090
3091 files.push(p);
3092 }
3093
3094 files.sort();
3095
3096 for file in files {
3097 markdown_test(builder, test_compiler, &file);
3098 }
3099 }
3100}
3101
3102macro_rules! test_book {
3103 ($(
3104 $name:ident, $path:expr, $book_name:expr,
3105 default=$default:expr
3106 $(,submodules = $submodules:expr)?
3107 $(,dependencies=$dependencies:expr)?
3108 ;
3109 )+) => {
3110 $(
3111 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
3112 pub struct $name {
3113 test_compiler: Compiler,
3114 }
3115
3116 impl CommandLineStep for $name {
3117 type Output = ();
3118 const IS_HOST: bool = true;
3119
3120 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3121 run.path($path)
3122 }
3123
3124 fn is_default_step(_builder: &Builder<'_>) -> bool {
3125 const { $default }
3126 }
3127
3128 fn make_run(run: RunConfig<'_>) {
3129 run.builder.ensure($name {
3130 test_compiler: run.builder.compiler(run.builder.top_stage, run.target),
3131 });
3132 }
3133
3134 fn run(self, builder: &Builder<'_>) {
3135 $(
3136 for submodule in $submodules {
3137 builder.require_submodule(submodule, None);
3138 }
3139 )*
3140
3141 let dependencies = vec![];
3142 $(
3143 let mut dependencies = dependencies;
3144 for dep in $dependencies {
3145 dependencies.push(dep);
3146 }
3147 )?
3148
3149 builder.ensure(BookTest {
3150 test_compiler: self.test_compiler,
3151 path: PathBuf::from($path),
3152 name: $book_name,
3153 is_ext_doc: !$default,
3154 dependencies,
3155 });
3156 }
3157 }
3158 )+
3159 }
3160}
3161
3162test_book!(
3163 Nomicon, "src/doc/nomicon", "nomicon", default=false, submodules=["src/doc/nomicon"];
3164 Reference, "src/doc/reference", "reference", default=false, submodules=["src/doc/reference"];
3165 RustdocBook, "src/doc/rustdoc", "rustdoc", default=true;
3166 RustcBook, "src/doc/rustc", "rustc", default=true;
3167 RustByExample, "src/doc/rust-by-example", "rust-by-example", default=false, submodules=["src/doc/rust-by-example"];
3168 EmbeddedBook, "src/doc/embedded-book", "embedded-book", default=false, submodules=["src/doc/embedded-book"];
3169 TheBook, "src/doc/book", "book", default=false, submodules=["src/doc/book"], dependencies=["src/doc/book/packages/trpl"];
3170 UnstableBook, "src/doc/unstable-book", "unstable-book", default=true;
3171 EditionGuide, "src/doc/edition-guide", "edition-guide", default=false, submodules=["src/doc/edition-guide"];
3172);
3173
3174#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3175pub struct ErrorIndex {
3176 compilers: RustcPrivateCompilers,
3177}
3178
3179impl CommandLineStep for ErrorIndex {
3180 type Output = ();
3181 const IS_HOST: bool = true;
3182
3183 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3184 run.path("src/tools/error_index_generator").alias("error-index")
3187 }
3188
3189 fn is_default_step(_builder: &Builder<'_>) -> bool {
3190 true
3191 }
3192
3193 fn make_run(run: RunConfig<'_>) {
3194 let compilers = RustcPrivateCompilers::new(
3198 run.builder,
3199 run.builder.top_stage,
3200 run.builder.config.host_target,
3201 );
3202 run.builder.ensure(ErrorIndex { compilers });
3203 }
3204
3205 fn run(self, builder: &Builder<'_>) {
3212 let target_compiler = self.compilers.target_compiler();
3214
3215 let dir = testdir(builder, target_compiler.host);
3216 t!(fs::create_dir_all(&dir));
3217 let output = dir.join("error-index.md");
3218
3219 let mut tool = tool::ErrorIndex::command(builder, self.compilers);
3220 tool.arg("markdown").arg(&output);
3221
3222 let guard = builder.msg_test("error-index", target_compiler.host, target_compiler.stage);
3223 let _time = helpers::timeit(builder);
3224 tool.run_capture(builder);
3225 drop(guard);
3226 builder.std(target_compiler, target_compiler.host);
3229 markdown_test(builder, target_compiler, &output);
3230 }
3231}
3232
3233fn markdown_test(builder: &Builder<'_>, compiler: Compiler, markdown: &Path) -> bool {
3234 if let Ok(contents) = fs::read_to_string(markdown)
3235 && !contents.contains("```")
3236 {
3237 return true;
3238 }
3239
3240 builder.do_if_verbose(|| println!("doc tests for: {}", markdown.display()));
3241 let mut cmd = builder.rustdoc_cmd(compiler);
3242 builder.add_rust_test_threads(&mut cmd);
3243 cmd.arg("-Z");
3245 cmd.arg("unstable-options");
3246 cmd.arg("--test");
3247 cmd.arg(markdown);
3248 cmd.env("RUSTC_BOOTSTRAP", "1");
3249
3250 let test_args = builder.config.test_args().join(" ");
3251 cmd.arg("--test-args").arg(test_args);
3252
3253 cmd = cmd.delay_failure();
3254 if !builder.config.verbose_tests {
3255 cmd.run_capture(builder).is_success()
3256 } else {
3257 cmd.run(builder)
3258 }
3259}
3260
3261#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3266pub struct CrateLibrustc {
3267 build_compiler: Compiler,
3269 target: TargetSelection,
3270 crates: Vec<String>,
3271}
3272
3273impl CommandLineStep for CrateLibrustc {
3274 type Output = ();
3275 const IS_HOST: bool = true;
3276
3277 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3278 run.crate_or_deps("rustc-main").path("compiler")
3279 }
3280
3281 fn is_default_step(_builder: &Builder<'_>) -> bool {
3282 true
3283 }
3284
3285 fn make_run(run: RunConfig<'_>) {
3286 let builder = run.builder;
3287 let host = run.build_triple();
3288 let build_compiler = builder.compiler(builder.top_stage - 1, host);
3289 let crates = run.make_run_crates(Alias::Compiler);
3290
3291 builder.ensure(CrateLibrustc { build_compiler, target: run.target, crates });
3292 }
3293
3294 fn run(self, builder: &Builder<'_>) {
3295 builder.std(self.build_compiler, self.target);
3296
3297 builder.ensure(Crate {
3299 build_compiler: self.build_compiler,
3300 target: self.target,
3301 mode: Mode::Rustc,
3302 crates: self.crates,
3303 });
3304 }
3305
3306 fn metadata(&self) -> Option<StepMetadata> {
3307 Some(StepMetadata::test("CrateLibrustc", self.target).built_by(self.build_compiler))
3308 }
3309}
3310
3311fn run_cargo_test<'a>(
3315 cargo: builder::Cargo,
3316 libtest_args: &[&str],
3317 crates: &[String],
3318 description: impl Into<Option<&'a str>>,
3319 target: TargetSelection,
3320 builder: &Builder<'_>,
3321 record_failed_tests: RecordFailedTests,
3322) -> bool {
3323 let compiler = cargo.compiler();
3324 let stage = match cargo.mode() {
3325 Mode::Std => compiler.stage,
3326 _ => compiler.stage + 1,
3327 };
3328
3329 let mut cargo = prepare_cargo_test(cargo, libtest_args, crates, target, builder);
3330 let _time = helpers::timeit(builder);
3331
3332 let _group = description.into().and_then(|what| builder.msg_test(what, target, stage));
3333
3334 #[cfg(feature = "build-metrics")]
3335 builder.metrics.begin_test_suite(
3336 build_helper::metrics::TestSuiteMetadata::CargoPackage {
3337 crates: crates.iter().map(|c| c.to_string()).collect(),
3338 target: target.triple.to_string(),
3339 host: compiler.host.triple.to_string(),
3340 stage: compiler.stage,
3341 },
3342 builder,
3343 );
3344 add_flags_and_try_run_tests(builder, &mut cargo, record_failed_tests)
3345}
3346
3347fn prepare_cargo_test(
3349 cargo: builder::Cargo,
3350 libtest_args: &[&str],
3351 crates: &[String],
3352 target: TargetSelection,
3353 builder: &Builder<'_>,
3354) -> BootstrapCommand {
3355 let compiler = cargo.compiler();
3356 let mut cargo: BootstrapCommand = cargo.into();
3357
3358 if builder.config.cmd.bless() && !cargo.get_envs().any(|v| v.0 == "RUSTC_BLESS") {
3362 cargo.env("RUSTC_BLESS", "Gesundheit");
3363 }
3364
3365 if builder.kind == Kind::Test && !builder.fail_fast {
3369 cargo.arg("--no-fail-fast");
3370 }
3371
3372 if builder.config.json_output {
3373 cargo.arg("--message-format=json");
3374 }
3375
3376 match builder.test_target {
3377 TestTarget::AllTargets => cargo.args(["--bins", "--examples", "--tests", "--benches"]),
3378 TestTarget::Default => &mut cargo,
3379 TestTarget::DocOnly => cargo.arg("--doc"),
3380 TestTarget::Tests => cargo.arg("--tests"),
3381 };
3382
3383 for krate in crates {
3384 cargo.arg("-p").arg(krate);
3385 }
3386
3387 cargo.arg("--").args(builder.config.test_args()).args(libtest_args);
3388 if !builder.config.verbose_tests {
3389 cargo.arg("--quiet");
3390 }
3391
3392 if builder.kind != Kind::Miri {
3401 let mut dylib_paths = builder.rustc_lib_paths(compiler);
3402 dylib_paths.push(builder.sysroot_target_libdir(compiler, target));
3403 helpers::add_dylib_path(dylib_paths, &mut cargo);
3404 }
3405
3406 if builder.remote_tested(target) {
3407 cargo.env(
3408 format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)),
3409 format!("{} run 0", builder.tool_exe(Tool::RemoteTestClient).display()),
3410 );
3411 } else if let Some(tool) = builder.runner(target) {
3412 cargo.env(format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)), tool);
3413 }
3414
3415 cargo
3416}
3417
3418#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3426pub struct Crate {
3427 build_compiler: Compiler,
3429 target: TargetSelection,
3430 mode: Mode,
3431 crates: Vec<String>,
3432}
3433
3434impl CommandLineStep for Crate {
3435 type Output = ();
3436
3437 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3438 run.crate_or_deps("sysroot").crate_or_deps("coretests").crate_or_deps("alloctests")
3439 }
3440
3441 fn is_default_step(_builder: &Builder<'_>) -> bool {
3442 true
3443 }
3444
3445 fn make_run(run: RunConfig<'_>) {
3446 let builder = run.builder;
3447 let host = run.build_triple();
3448 let build_compiler = builder.compiler(builder.top_stage, host);
3449 let crates = run
3450 .paths
3451 .iter()
3452 .map(|p| builder.crate_paths[&p.assert_single_path().path].clone())
3453 .collect();
3454
3455 builder.ensure(Crate { build_compiler, target: run.target, mode: Mode::Std, crates });
3456 }
3457
3458 fn run(self, builder: &Builder<'_>) {
3467 let build_compiler = self.build_compiler;
3468 let target = self.target;
3469 let mode = self.mode;
3470
3471 builder.ensure(Std::new(build_compiler, build_compiler.host).force_recompile(true));
3474 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
3475
3476 let mut cargo = if builder.kind == Kind::Miri {
3477 if builder.top_stage == 0 {
3478 eprintln!("ERROR: `x.py miri` requires stage 1 or higher");
3479 std::process::exit(1);
3480 }
3481
3482 let mut cargo = builder::Cargo::new(
3485 builder,
3486 build_compiler,
3487 mode,
3488 SourceType::InTree,
3489 target,
3490 Kind::MiriTest,
3491 );
3492 cargo.env("MIRI_REPLACE_LIBRS_IF_NOT_TEST", "1");
3504 cargo.rustflag("-Zforce-unstable-if-unmarked");
3508 cargo.env(
3513 "MIRIFLAGS",
3514 format!(
3515 "{} -Zmiri-env-forward=RUSTC_BOOTSTRAP",
3516 env::var("MIRIFLAGS").unwrap_or_default()
3517 ),
3518 );
3519 cargo
3520 } else {
3521 if !builder.config.is_host_target(target) {
3523 builder.ensure(compile::Std::new(build_compiler, target).force_recompile(true));
3524 builder.ensure(RemoteCopyLibs { build_compiler, target });
3525 }
3526
3527 builder::Cargo::new(
3529 builder,
3530 build_compiler,
3531 mode,
3532 SourceType::InTree,
3533 target,
3534 builder.kind,
3535 )
3536 };
3537
3538 match mode {
3539 Mode::Std => {
3540 if builder.kind == Kind::Miri {
3541 cargo
3547 .arg("--manifest-path")
3548 .arg(builder.src.join("library/sysroot/Cargo.toml"));
3549 } else {
3550 compile::std_cargo(builder, target, &mut cargo, &[]);
3551 }
3552 }
3553 Mode::Rustc => {
3554 compile::rustc_cargo(builder, &mut cargo, target, &build_compiler, &self.crates);
3555 }
3556 _ => panic!("can only test libraries"),
3557 };
3558
3559 let mut crates = self.crates.clone();
3560 if crates.iter().any(|crate_| crate_ == "core") {
3565 crates.push("coretests".to_owned());
3566 }
3567 if crates.iter().any(|crate_| crate_ == "alloc") {
3568 crates.push("alloctests".to_owned());
3569 };
3570 let description = crate_description(&self.crates);
3571 run_cargo_test(cargo, &[], &crates, &*description, target, builder, record_failed_tests);
3572 }
3573}
3574
3575#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3578pub struct CrateRustdoc {
3579 host: TargetSelection,
3580}
3581
3582impl CommandLineStep for CrateRustdoc {
3583 type Output = ();
3584 const IS_HOST: bool = true;
3585
3586 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3587 run.multi_path(&["src/librustdoc", "src/tools/rustdoc"])
3588 }
3589
3590 fn is_default_step(_builder: &Builder<'_>) -> bool {
3591 true
3592 }
3593
3594 fn make_run(run: RunConfig<'_>) {
3595 let builder = run.builder;
3596
3597 builder.ensure(CrateRustdoc { host: run.target });
3598 }
3599
3600 fn run(self, builder: &Builder<'_>) {
3601 let target = self.host;
3602 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
3603
3604 let compiler = if builder.download_rustc() {
3605 builder.compiler(builder.top_stage, target)
3606 } else {
3607 builder.compiler_for(builder.top_stage, target, target)
3612 };
3613 builder.std(compiler, target);
3618 builder.ensure(compile::Rustc::new(compiler, target));
3619
3620 let mut cargo = tool::prepare_tool_cargo(
3621 builder,
3622 compiler,
3623 Mode::ToolRustcPrivate,
3624 target,
3625 builder.kind,
3626 "src/tools/rustdoc",
3627 SourceType::InTree,
3628 &[],
3629 );
3630 if self.host.contains("musl") {
3631 cargo.arg("'-Ctarget-feature=-crt-static'");
3632 }
3633
3634 let libdir = if builder.download_rustc() {
3661 builder.rustc_libdir(compiler)
3662 } else {
3663 builder.sysroot_target_libdir(compiler, target).to_path_buf()
3664 };
3665 let mut dylib_path = dylib_path();
3666 dylib_path.insert(0, PathBuf::from(&*libdir));
3667 cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());
3668
3669 run_cargo_test(
3670 cargo,
3671 &[],
3672 &["rustdoc:0.0.0".to_string()],
3673 "rustdoc",
3674 target,
3675 builder,
3676 record_failed_tests,
3677 );
3678 }
3679}
3680
3681#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3682pub struct CrateRustdocJsonTypes {
3683 build_compiler: Compiler,
3684 target: TargetSelection,
3685}
3686
3687impl CommandLineStep for CrateRustdocJsonTypes {
3688 type Output = ();
3689 const IS_HOST: bool = true;
3690
3691 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3692 run.path("src/rustdoc-json-types")
3693 }
3694
3695 fn is_default_step(_builder: &Builder<'_>) -> bool {
3696 true
3697 }
3698
3699 fn make_run(run: RunConfig<'_>) {
3700 let builder = run.builder;
3701
3702 builder.ensure(CrateRustdocJsonTypes {
3703 build_compiler: get_tool_target_compiler(
3704 builder,
3705 ToolTargetBuildMode::Build(run.target),
3706 ),
3707 target: run.target,
3708 });
3709 }
3710
3711 fn run(self, builder: &Builder<'_>) {
3712 let target = self.target;
3713 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
3714
3715 let cargo = tool::prepare_tool_cargo(
3716 builder,
3717 self.build_compiler,
3718 Mode::ToolTarget,
3719 target,
3720 builder.kind,
3721 "src/rustdoc-json-types",
3722 SourceType::InTree,
3723 &["rkyv_0_8".to_owned()],
3724 );
3725
3726 let libtest_args = if target.contains("musl") {
3728 ["'-Ctarget-feature=-crt-static'"].as_slice()
3729 } else {
3730 &[]
3731 };
3732
3733 run_cargo_test(
3734 cargo,
3735 libtest_args,
3736 &["rustdoc-json-types".to_string()],
3737 "rustdoc-json-types",
3738 target,
3739 builder,
3740 record_failed_tests,
3741 );
3742 }
3743}
3744
3745#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3755pub struct RemoteCopyLibs {
3756 build_compiler: Compiler,
3757 target: TargetSelection,
3758}
3759
3760impl Step for RemoteCopyLibs {
3761 type Output = ();
3762
3763 fn run(self, builder: &Builder<'_>) {
3764 let build_compiler = self.build_compiler;
3765 let target = self.target;
3766 if !builder.remote_tested(target) {
3767 return;
3768 }
3769
3770 builder.std(build_compiler, target);
3771
3772 builder.info(&format!("REMOTE copy libs to emulator ({target})"));
3773
3774 let remote_test_server = builder.ensure(tool::RemoteTestServer { build_compiler, target });
3775
3776 let tool = builder.tool_exe(Tool::RemoteTestClient);
3778 let mut cmd = command(&tool);
3779 cmd.arg("spawn-emulator")
3780 .arg(target.triple)
3781 .arg(&remote_test_server.tool_path)
3782 .arg(builder.tempdir());
3783 if let Some(rootfs) = builder.qemu_rootfs(target) {
3784 cmd.arg(rootfs);
3785 }
3786 cmd.run(builder);
3787
3788 for f in t!(builder.sysroot_target_libdir(build_compiler, target).read_dir()) {
3790 let f = t!(f);
3791 if helpers::is_dylib(&f.path()) {
3792 command(&tool).arg("push").arg(f.path()).run(builder);
3793 }
3794 }
3795 }
3796}
3797
3798#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3799pub struct Distcheck;
3800
3801impl CommandLineStep for Distcheck {
3802 type Output = ();
3803
3804 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3805 run.alias("distcheck")
3806 }
3807
3808 fn make_run(run: RunConfig<'_>) {
3809 run.builder.ensure(Distcheck);
3810 }
3811
3812 fn run(self, builder: &Builder<'_>) {
3822 let root_dir = std::env::temp_dir().join("distcheck");
3825
3826 distcheck_plain_source_tarball(builder, &root_dir.join("distcheck-rustc-src"));
3827 distcheck_rust_src(builder, &root_dir.join("distcheck-rust-src"));
3828 distcheck_rustc_dev(builder, &root_dir.join("distcheck-rustc-dev"));
3829 }
3830}
3831
3832fn distcheck_plain_source_tarball(builder: &Builder<'_>, plain_src_dir: &Path) {
3834 builder.info("Distcheck plain source tarball");
3835 let plain_src_tarball = builder.ensure(dist::PlainSourceTarball);
3836 builder.clear_dir(plain_src_dir);
3837
3838 let configure_args: Vec<String> = std::env::var("DISTCHECK_CONFIGURE_ARGS")
3839 .map(|args| args.split(" ").map(|s| s.to_string()).collect::<Vec<String>>())
3840 .unwrap_or_default();
3841
3842 command("tar")
3843 .arg("-xf")
3844 .arg(plain_src_tarball.tarball())
3845 .arg("--strip-components=1")
3846 .current_dir(plain_src_dir)
3847 .run(builder);
3848 command("./configure")
3849 .arg("--set")
3850 .arg("rust.omit-git-hash=false")
3851 .arg("--set")
3852 .arg("rust.remap-debuginfo=false")
3853 .args(&configure_args)
3854 .arg("--enable-vendor")
3855 .current_dir(plain_src_dir)
3856 .run(builder);
3857 command(helpers::make(&builder.config.host_target.triple))
3858 .arg("check")
3859 .env("GITHUB_ACTIONS", "0")
3862 .current_dir(plain_src_dir)
3863 .run(builder);
3864 builder.remove_dir(plain_src_dir);
3866}
3867
3868fn distcheck_rust_src(builder: &Builder<'_>, src_dir: &Path) {
3870 builder.info("Distcheck rust-src");
3871 let src_tarball = builder.ensure(dist::Src);
3872 builder.clear_dir(src_dir);
3873
3874 command("tar")
3875 .arg("-xf")
3876 .arg(src_tarball.tarball())
3877 .arg("--strip-components=1")
3878 .current_dir(src_dir)
3879 .run(builder);
3880
3881 let toml = src_dir.join("rust-src/lib/rustlib/src/rust/library/std/Cargo.toml");
3882 command(&builder.initial_cargo)
3883 .env("RUSTC_BOOTSTRAP", "1")
3886 .arg("generate-lockfile")
3887 .arg("--manifest-path")
3888 .arg(&toml)
3889 .current_dir(src_dir)
3890 .run(builder);
3891 builder.remove_dir(src_dir);
3893}
3894
3895fn distcheck_rustc_dev(builder: &Builder<'_>, dir: &Path) {
3897 builder.info("Distcheck rustc-dev");
3898 let tarball = builder.ensure(dist::RustcDev::new(builder, builder.host_target)).unwrap();
3899 builder.clear_dir(dir);
3900
3901 command("tar")
3902 .arg("-xf")
3903 .arg(tarball.tarball())
3904 .arg("--strip-components=1")
3905 .current_dir(dir)
3906 .run(builder);
3907
3908 command(&builder.initial_cargo)
3909 .arg("metadata")
3910 .arg("--manifest-path")
3911 .arg("rustc-dev/lib/rustlib/rustc-src/rust/compiler/rustc/Cargo.toml")
3912 .env("RUSTC_BOOTSTRAP", "1")
3913 .env("RUSTC", &builder.initial_rustc)
3915 .current_dir(dir)
3916 .run(builder);
3917 builder.remove_dir(dir);
3919}
3920
3921#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3923pub(crate) struct BootstrapPy;
3924
3925impl CommandLineStep for BootstrapPy {
3926 type Output = ();
3927 const IS_HOST: bool = true;
3928
3929 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3930 run.alias("bootstrap-py")
3931 }
3932
3933 fn is_default_step(builder: &Builder<'_>) -> bool {
3934 builder.config.is_running_on_ci()
3938 }
3939
3940 fn make_run(run: RunConfig<'_>) {
3941 run.builder.ensure(BootstrapPy)
3942 }
3943
3944 fn run(self, builder: &Builder<'_>) -> Self::Output {
3945 let mut check_bootstrap = command(
3946 builder.config.python.as_ref().expect("python is required for running bootstrap tests"),
3947 );
3948 check_bootstrap
3949 .args(["-m", "unittest", "bootstrap_test.py"])
3950 .args(builder.config.test_args())
3952 .env("BUILD_DIR", &builder.out)
3953 .env("BUILD_PLATFORM", builder.build.host_target.triple)
3954 .env("BOOTSTRAP_TEST_RUSTC_BIN", &builder.initial_rustc)
3955 .env("BOOTSTRAP_TEST_CARGO_BIN", &builder.initial_cargo)
3956 .current_dir(builder.src.join("src/bootstrap/"));
3957 check_bootstrap.delay_failure().run(builder);
3958 }
3959}
3960
3961#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3962pub struct Bootstrap;
3963
3964impl CommandLineStep for Bootstrap {
3965 type Output = ();
3966 const IS_HOST: bool = true;
3967
3968 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3969 run.path("src/bootstrap")
3970 }
3971
3972 fn is_default_step(builder: &Builder<'_>) -> bool {
3973 builder.config.is_running_on_ci()
3977 }
3978
3979 fn run(self, builder: &Builder<'_>) {
3981 let host = builder.config.host_target;
3982 let build_compiler = builder.compiler(0, host);
3983 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
3984
3985 builder.build.require_submodule("src/tools/cargo", None);
3987
3988 let mut cargo = tool::prepare_tool_cargo(
3989 builder,
3990 build_compiler,
3991 Mode::ToolBootstrap,
3992 host,
3993 Kind::Test,
3994 "src/bootstrap",
3995 SourceType::InTree,
3996 &[],
3997 );
3998
3999 cargo.release_build(false);
4000
4001 cargo
4002 .rustflag("-Cdebuginfo=2")
4003 .env("CARGO_TARGET_DIR", builder.out.join("bootstrap"))
4004 .env("INSTA_WORKSPACE_ROOT", &builder.src)
4006 .env("RUSTC_BOOTSTRAP", "1");
4007
4008 if builder.config.cmd.bless() {
4009 cargo.env("INSTA_UPDATE", "always");
4013 }
4014
4015 run_cargo_test(cargo, &[], &[], None, host, builder, record_failed_tests);
4016 }
4017
4018 fn make_run(run: RunConfig<'_>) {
4019 run.builder.ensure(Bootstrap);
4020 }
4021}
4022
4023fn get_compiler_to_test(builder: &Builder<'_>, target: TargetSelection) -> Compiler {
4024 builder.compiler(builder.top_stage, target)
4025}
4026
4027#[derive(Debug, Clone, PartialEq, Eq, Hash)]
4030pub struct TierCheck {
4031 test_compiler: Compiler,
4032}
4033
4034impl CommandLineStep for TierCheck {
4035 type Output = ();
4036 const IS_HOST: bool = true;
4037
4038 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
4039 run.path("src/tools/tier-check")
4040 }
4041
4042 fn is_default_step(_builder: &Builder<'_>) -> bool {
4043 true
4044 }
4045
4046 fn make_run(run: RunConfig<'_>) {
4047 run.builder
4048 .ensure(TierCheck { test_compiler: get_compiler_to_test(run.builder, run.target) });
4049 }
4050
4051 fn run(self, builder: &Builder<'_>) {
4052 let tool_build_compiler = builder.compiler(0, builder.host_target);
4053
4054 let mut cargo = tool::prepare_tool_cargo(
4055 builder,
4056 tool_build_compiler,
4057 Mode::ToolBootstrap,
4058 tool_build_compiler.host,
4059 Kind::Run,
4060 "src/tools/tier-check",
4061 SourceType::InTree,
4062 &[],
4063 );
4064 cargo.arg(builder.src.join("src/doc/rustc/src/platform-support.md"));
4065 cargo.arg(builder.rustc(self.test_compiler));
4066
4067 let _guard = builder.msg_test(
4068 "platform support check",
4069 self.test_compiler.host,
4070 self.test_compiler.stage,
4071 );
4072 BootstrapCommand::from(cargo).delay_failure().run(builder);
4073 }
4074
4075 fn metadata(&self) -> Option<StepMetadata> {
4076 Some(StepMetadata::test("tier-check", self.test_compiler.host))
4077 }
4078}
4079
4080#[derive(Debug, Clone, PartialEq, Eq, Hash)]
4081pub struct LintDocs {
4082 build_compiler: Compiler,
4083 target: TargetSelection,
4084}
4085
4086impl CommandLineStep for LintDocs {
4087 type Output = ();
4088 const IS_HOST: bool = true;
4089
4090 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
4091 run.path("src/tools/lint-docs")
4092 }
4093
4094 fn is_default_step(builder: &Builder<'_>) -> bool {
4095 builder.top_stage >= 2
4098 }
4099
4100 fn make_run(run: RunConfig<'_>) {
4101 if run.builder.top_stage < 2 {
4102 eprintln!("WARNING: lint-docs tests might not work below stage 2");
4103 }
4104
4105 run.builder.ensure(LintDocs {
4106 build_compiler: prepare_doc_compiler(
4107 run.builder,
4108 run.builder.config.host_target,
4109 run.builder.top_stage,
4110 ),
4111 target: run.target,
4112 });
4113 }
4114
4115 fn run(self, builder: &Builder<'_>) {
4118 builder.ensure(crate::core::build_steps::doc::RustcBook::validate(
4119 self.build_compiler,
4120 self.target,
4121 ));
4122 }
4123
4124 fn metadata(&self) -> Option<StepMetadata> {
4125 Some(StepMetadata::test("lint-docs", self.target).built_by(self.build_compiler))
4126 }
4127}
4128
4129#[derive(Debug, Clone, PartialEq, Eq, Hash)]
4130pub struct RustInstaller;
4131
4132impl CommandLineStep for RustInstaller {
4133 type Output = ();
4134 const IS_HOST: bool = true;
4135
4136 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
4137 run.path("src/tools/rust-installer")
4138 }
4139
4140 fn is_default_step(_builder: &Builder<'_>) -> bool {
4141 true
4142 }
4143
4144 fn make_run(run: RunConfig<'_>) {
4145 run.builder.ensure(Self);
4146 }
4147
4148 fn run(self, builder: &Builder<'_>) {
4150 let bootstrap_host = builder.config.host_target;
4151 let build_compiler = builder.compiler(0, bootstrap_host);
4152 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
4153 let cargo = tool::prepare_tool_cargo(
4154 builder,
4155 build_compiler,
4156 Mode::ToolBootstrap,
4157 bootstrap_host,
4158 Kind::Test,
4159 "src/tools/rust-installer",
4160 SourceType::InTree,
4161 &[],
4162 );
4163
4164 let _guard = builder.msg_test("rust-installer", bootstrap_host, 1);
4165 run_cargo_test(cargo, &[], &[], None, bootstrap_host, builder, record_failed_tests);
4166
4167 if bootstrap_host != "x86_64-unknown-linux-gnu" {
4171 return;
4172 }
4173
4174 let mut cmd = command(builder.src.join("src/tools/rust-installer/test.sh"));
4175 let tmpdir = testdir(builder, build_compiler.host).join("rust-installer");
4176 let _ = std::fs::remove_dir_all(&tmpdir);
4177 let _ = std::fs::create_dir_all(&tmpdir);
4178 cmd.current_dir(&tmpdir);
4179 cmd.env("CARGO_TARGET_DIR", tmpdir.join("cargo-target"));
4180 cmd.env("CARGO", &builder.initial_cargo);
4181 cmd.env("RUSTC", &builder.initial_rustc);
4182 cmd.env("TMP_DIR", &tmpdir);
4183 cmd.delay_failure().run(builder);
4184 }
4185}
4186
4187#[derive(Debug, Clone, PartialEq, Eq, Hash)]
4188pub struct TestHelpers {
4189 pub target: TargetSelection,
4190}
4191
4192impl CommandLineStep for TestHelpers {
4193 type Output = ();
4194
4195 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
4196 run.path("tests/auxiliary/rust_test_helpers.c")
4197 }
4198
4199 fn make_run(run: RunConfig<'_>) {
4200 run.builder.ensure(TestHelpers { target: run.target })
4201 }
4202
4203 fn run(self, builder: &Builder<'_>) {
4206 if builder.config.dry_run() {
4207 return;
4208 }
4209 let target = if self.target == "x86_64-fortanix-unknown-sgx" {
4213 TargetSelection::from_user("x86_64-unknown-linux-gnu")
4214 } else {
4215 self.target
4216 };
4217 let dst = builder.test_helpers_out(target);
4218 let src = builder.src.join("tests/auxiliary/rust_test_helpers.c");
4219 let _guard = builder.msg_unstaged(Kind::Build, "test helpers", target);
4220 t!(fs::create_dir_all(&dst));
4221
4222 if !up_to_date(&src, &dst.join("librust_test_helpers.a")) {
4223 let mut cfg = cc::Build::new();
4224
4225 if !target.is_msvc() {
4229 if let Some(ar) = builder.ar(target) {
4230 cfg.archiver(ar);
4231 }
4232 cfg.compiler(builder.cc(target));
4233 }
4234 cfg.cargo_metadata(false)
4235 .out_dir(&dst)
4236 .target(&target.triple)
4237 .host(&builder.config.host_target.triple)
4238 .opt_level(0)
4239 .warnings(false)
4240 .debug(false)
4241 .file(builder.src.join("tests/auxiliary/rust_test_helpers.c"))
4242 .compile("rust_test_helpers");
4243 }
4244 if target.is_pauthtest() {
4245 let so = dst.join("librust_test_helpers.so");
4246 if up_to_date(&src, &so) {
4247 return;
4248 }
4249
4250 let status = Command::new(builder.cc(target))
4251 .arg("-target")
4252 .arg(target.triple)
4253 .arg("-march=armv8.3-a+pauth")
4254 .arg("-fPIC")
4255 .arg("-shared")
4256 .arg("-O0") .arg("-o")
4258 .arg(&so)
4259 .arg(&src)
4260 .status()
4261 .unwrap_or_else(|_| panic!("Failed to run clang for {} toolchain", target.triple));
4262
4263 if !status.success() {
4264 panic!("Linking of librust_test_helpers.so failed (target: {})", target.triple);
4265 }
4266 }
4267 }
4268}
4269
4270#[derive(Debug, Clone, PartialEq, Eq, Hash)]
4271pub struct CodegenCranelift {
4272 compilers: RustcPrivateCompilers,
4273 target: TargetSelection,
4274}
4275
4276impl CommandLineStep for CodegenCranelift {
4277 type Output = ();
4278 const IS_HOST: bool = true;
4279
4280 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
4281 run.path("compiler/rustc_codegen_cranelift")
4282 }
4283
4284 fn is_default_step(_builder: &Builder<'_>) -> bool {
4285 true
4286 }
4287
4288 fn make_run(run: RunConfig<'_>) {
4289 let builder = run.builder;
4290 let host = run.build_triple();
4291 let compilers = RustcPrivateCompilers::new(run.builder, run.builder.top_stage, host);
4292
4293 if builder.test_target == TestTarget::DocOnly {
4294 return;
4295 }
4296
4297 if builder.download_rustc() {
4298 builder.info("CI rustc uses the default codegen backend. skipping");
4299 return;
4300 }
4301
4302 if !target_supports_cranelift_backend(run.target) {
4303 builder.info("target not supported by rustc_codegen_cranelift. skipping");
4304 return;
4305 }
4306
4307 if builder.remote_tested(run.target) {
4308 builder.info("remote testing is not supported by rustc_codegen_cranelift. skipping");
4309 return;
4310 }
4311
4312 if !builder
4313 .config
4314 .enabled_codegen_backends(run.target)
4315 .contains(&CodegenBackendKind::Cranelift)
4316 {
4317 builder.info("cranelift not in rust.codegen-backends. skipping");
4318 return;
4319 }
4320
4321 builder.ensure(CodegenCranelift { compilers, target: run.target });
4322 }
4323
4324 fn run(self, builder: &Builder<'_>) {
4325 let compilers = self.compilers;
4326 let build_compiler = compilers.build_compiler();
4327
4328 let target_compiler = compilers.target_compiler();
4331 let target = self.target;
4332
4333 builder.std(target_compiler, target);
4334
4335 let mut cargo = builder::Cargo::new(
4336 builder,
4337 target_compiler,
4338 Mode::Codegen, SourceType::InTree,
4340 target,
4341 Kind::Run,
4342 );
4343
4344 cargo.current_dir(&builder.src.join("compiler/rustc_codegen_cranelift"));
4345 cargo
4346 .arg("--manifest-path")
4347 .arg(builder.src.join("compiler/rustc_codegen_cranelift/build_system/Cargo.toml"));
4348 compile::rustc_cargo_env(builder, &mut cargo, target);
4349
4350 cargo.env("CARGO_BUILD_INCREMENTAL", "false");
4352
4353 let _guard = builder.msg_test(
4354 "rustc_codegen_cranelift",
4355 target_compiler.host,
4356 target_compiler.stage,
4357 );
4358
4359 let download_dir = builder.out.join("cg_clif_download");
4361
4362 cargo
4363 .arg("--")
4364 .arg("test")
4365 .arg("--download-dir")
4366 .arg(&download_dir)
4367 .arg("--out-dir")
4368 .arg(builder.stage_out(build_compiler, Mode::Codegen).join("cg_clif"))
4369 .arg("--no-unstable-features")
4370 .arg("--use-backend")
4371 .arg("cranelift")
4372 .arg("--sysroot")
4374 .arg("llvm")
4375 .arg("--skip-test")
4378 .arg("testsuite.extended_sysroot");
4379
4380 cargo.into_cmd().run(builder);
4381 }
4382
4383 fn metadata(&self) -> Option<StepMetadata> {
4384 Some(
4385 StepMetadata::test("rustc_codegen_cranelift", self.target)
4386 .built_by(self.compilers.build_compiler()),
4387 )
4388 }
4389}
4390
4391#[derive(Debug, Clone, PartialEq, Eq, Hash)]
4392pub struct CodegenGCC {
4393 compilers: RustcPrivateCompilers,
4394 target: TargetSelection,
4395}
4396
4397impl CommandLineStep for CodegenGCC {
4398 type Output = ();
4399 const IS_HOST: bool = true;
4400
4401 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
4402 run.path("compiler/rustc_codegen_gcc")
4403 }
4404
4405 fn is_default_step(_builder: &Builder<'_>) -> bool {
4406 true
4407 }
4408
4409 fn make_run(run: RunConfig<'_>) {
4410 let builder = run.builder;
4411 let host = run.build_triple();
4412 let compilers = RustcPrivateCompilers::new(run.builder, run.builder.top_stage, host);
4413
4414 if builder.test_target == TestTarget::DocOnly {
4415 return;
4416 }
4417
4418 if builder.download_rustc() {
4419 builder.info("CI rustc uses the default codegen backend. skipping");
4420 return;
4421 }
4422
4423 let triple = run.target.triple;
4424 let target_supported =
4425 if triple.contains("linux") { triple.contains("x86_64") } else { false };
4426 if !target_supported {
4427 builder.info("target not supported by rustc_codegen_gcc. skipping");
4428 return;
4429 }
4430
4431 if builder.remote_tested(run.target) {
4432 builder.info("remote testing is not supported by rustc_codegen_gcc. skipping");
4433 return;
4434 }
4435
4436 if !builder.config.enabled_codegen_backends(run.target).contains(&CodegenBackendKind::Gcc) {
4437 builder.info("gcc not in rust.codegen-backends. skipping");
4438 return;
4439 }
4440
4441 builder.ensure(CodegenGCC { compilers, target: run.target });
4442 }
4443
4444 fn run(self, builder: &Builder<'_>) {
4445 let compilers = self.compilers;
4446 let target = self.target;
4447
4448 let gcc = builder.ensure(Gcc { target_pair: GccTargetPair::for_native_build(target) });
4449
4450 builder.ensure(
4451 compile::Std::new(compilers.build_compiler(), target)
4452 .extra_rust_args(&["-Csymbol-mangling-version=v0", "-Cpanic=abort"]),
4453 );
4454
4455 let _guard = builder.msg_test(
4456 "rustc_codegen_gcc",
4457 compilers.target(),
4458 compilers.target_compiler().stage,
4459 );
4460
4461 let mut cargo = builder::Cargo::new(
4462 builder,
4463 compilers.build_compiler(),
4464 Mode::Codegen, SourceType::InTree,
4466 target,
4467 Kind::Run,
4468 );
4469
4470 cargo.current_dir(&builder.src.join("compiler/rustc_codegen_gcc"));
4471 cargo
4472 .arg("--manifest-path")
4473 .arg(builder.src.join("compiler/rustc_codegen_gcc/build_system/Cargo.toml"));
4474 compile::rustc_cargo_env(builder, &mut cargo, target);
4475 add_cg_gcc_cargo_flags(&mut cargo, &gcc);
4476
4477 cargo.env("CARGO_BUILD_INCREMENTAL", "false");
4479 cargo.rustflag("-Cpanic=abort");
4480
4481 cargo
4482 .env("CG_RUSTFLAGS", "-Alinker-messages")
4484 .arg("--")
4485 .arg("test")
4486 .arg("--use-backend")
4487 .arg("gcc")
4488 .arg("--gcc-path")
4489 .arg(gcc.libgccjit().parent().unwrap())
4490 .arg("--out-dir")
4491 .arg(builder.stage_out(compilers.build_compiler(), Mode::Codegen).join("cg_gcc"))
4492 .arg("--release")
4493 .arg("--mini-tests")
4494 .arg("--std-tests");
4495
4496 cargo.args(builder.config.test_args());
4497
4498 cargo.into_cmd().run(builder);
4499 }
4500
4501 fn metadata(&self) -> Option<StepMetadata> {
4502 Some(
4503 StepMetadata::test("rustc_codegen_gcc", self.target)
4504 .built_by(self.compilers.build_compiler()),
4505 )
4506 }
4507}
4508
4509#[derive(Debug, Clone, PartialEq, Eq, Hash)]
4514pub struct TestFloatParse {
4515 build_compiler: Compiler,
4524 target: TargetSelection,
4526}
4527
4528impl CommandLineStep for TestFloatParse {
4529 type Output = ();
4530 const IS_HOST: bool = true;
4531
4532 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
4533 run.path("src/tools/test-float-parse")
4534 }
4535
4536 fn is_default_step(_builder: &Builder<'_>) -> bool {
4537 true
4538 }
4539
4540 fn make_run(run: RunConfig<'_>) {
4541 run.builder.ensure(Self {
4542 build_compiler: get_compiler_to_test(run.builder, run.target),
4543 target: run.target,
4544 });
4545 }
4546
4547 fn run(self, builder: &Builder<'_>) {
4548 let build_compiler = self.build_compiler;
4549 let target = self.target;
4550
4551 builder.std(build_compiler, target);
4553 builder.std(build_compiler, builder.host_target);
4554 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
4555
4556 let mut cargo_test = tool::prepare_tool_cargo(
4558 builder,
4559 build_compiler,
4560 Mode::ToolStd,
4561 target,
4562 Kind::Test,
4563 "src/tools/test-float-parse",
4564 SourceType::InTree,
4565 &[],
4566 );
4567 cargo_test.allow_features(TEST_FLOAT_PARSE_ALLOW_FEATURES);
4568
4569 run_cargo_test(
4570 cargo_test,
4571 &[],
4572 &[],
4573 "test-float-parse",
4574 target,
4575 builder,
4576 record_failed_tests,
4577 );
4578
4579 let mut cargo_run = tool::prepare_tool_cargo(
4581 builder,
4582 build_compiler,
4583 Mode::ToolStd,
4584 target,
4585 Kind::Run,
4586 "src/tools/test-float-parse",
4587 SourceType::InTree,
4588 &[],
4589 );
4590 cargo_run.allow_features(TEST_FLOAT_PARSE_ALLOW_FEATURES);
4591
4592 if !matches!(env::var("FLOAT_PARSE_TESTS_NO_SKIP_HUGE").as_deref(), Ok("1") | Ok("true")) {
4593 cargo_run.args(["--", "--skip-huge"]);
4594 }
4595
4596 cargo_run.into_cmd().run(builder);
4597 }
4598}
4599
4600#[derive(Debug, Clone, Hash, PartialEq, Eq)]
4604pub struct CollectLicenseMetadata;
4605
4606impl CommandLineStep for CollectLicenseMetadata {
4607 type Output = PathBuf;
4608 const IS_HOST: bool = true;
4609
4610 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
4611 run.path("src/tools/collect-license-metadata")
4612 }
4613
4614 fn make_run(run: RunConfig<'_>) {
4615 run.builder.ensure(CollectLicenseMetadata);
4616 }
4617
4618 fn run(self, builder: &Builder<'_>) -> Self::Output {
4619 let Some(reuse) = &builder.config.reuse else {
4620 panic!("REUSE is required to collect the license metadata");
4621 };
4622
4623 let dest = builder.src.join("license-metadata.json");
4624
4625 let mut cmd = builder.tool_cmd(Tool::CollectLicenseMetadata);
4626 cmd.env("REUSE_EXE", reuse);
4627 cmd.env("DEST", &dest);
4628 cmd.env("ONLY_CHECK", "1");
4629 cmd.run(builder);
4630
4631 dest
4632 }
4633}
4634
4635#[derive(Debug, Clone, PartialEq, Eq, Hash)]
4636pub struct RemoteTestClientTests {
4637 host: TargetSelection,
4638}
4639
4640impl CommandLineStep for RemoteTestClientTests {
4641 type Output = ();
4642 const IS_HOST: bool = true;
4643
4644 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
4645 run.path("src/tools/remote-test-client")
4646 }
4647
4648 fn is_default_step(_builder: &Builder<'_>) -> bool {
4649 true
4650 }
4651
4652 fn make_run(run: RunConfig<'_>) {
4653 run.builder.ensure(Self { host: run.target });
4654 }
4655
4656 fn run(self, builder: &Builder<'_>) {
4657 let bootstrap_host = builder.config.host_target;
4658 let compiler = builder.compiler(0, bootstrap_host);
4659 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
4660
4661 let cargo = tool::prepare_tool_cargo(
4662 builder,
4663 compiler,
4664 Mode::ToolBootstrap,
4665 bootstrap_host,
4666 Kind::Test,
4667 "src/tools/remote-test-client",
4668 SourceType::InTree,
4669 &[],
4670 );
4671
4672 run_cargo_test(
4673 cargo,
4674 &[],
4675 &[],
4676 "remote-test-client",
4677 bootstrap_host,
4678 builder,
4679 record_failed_tests,
4680 );
4681 }
4682}
4683
4684fn check_if_cargo_semver_checks_is_installed(builder: &Builder<'_>) -> bool {
4685 command(&builder.initial_cargo)
4686 .allow_failure()
4687 .arg("semver-checks")
4688 .arg("--version")
4689 .cached()
4691 .run_capture_stdout(builder)
4692 .is_success()
4693}
4694
4695#[derive(Debug, Clone, PartialEq, Eq, Hash)]
4706pub struct StdSemverCheck {
4707 build_compiler: Compiler,
4708 target: TargetSelection,
4709 commit: String,
4711}
4712
4713impl CommandLineStep for StdSemverCheck {
4714 type Output = ();
4715
4716 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
4717 run.alias("std-semver-check")
4718 }
4719
4720 fn make_run(run: RunConfig<'_>) {
4721 if !check_if_cargo_semver_checks_is_installed(run.builder) {
4722 panic!("cargo-semver-checks was not found, please install it");
4723 }
4724
4725 let baseline_commit =
4726 run.builder.config.stdlib_semver_baseline.clone().unwrap_or_else(|| {
4727 match get_closest_upstream_commit(
4728 Some(&run.builder.config.src),
4729 &run.builder.config.git_config(),
4730 run.builder.config.ci_env,
4731 ) {
4732 Ok(Some(commit)) => commit,
4733 Ok(None) => {
4734 panic!("No baseline parent commit found for std-semver-check");
4735 }
4736 Err(error) => {
4737 panic!("Cannot get baseline parent commit for std-semver-check: {error:?}");
4738 }
4739 }
4740 });
4741
4742 run.builder.ensure(Self {
4743 build_compiler: run.builder.compiler_for_std(run.builder.top_stage),
4744 target: run.target,
4745 commit: baseline_commit,
4746 });
4747 }
4748
4749 fn run(self, builder: &Builder<'_>) {
4750 const STDLIB_SEMVER_CHECK_STAMP_PATH: &str = "src/bootstrap/stdlib-semver-check-stamp";
4751
4752 if builder.config.ci_env.is_running_in_ci()
4753 && builder.config.has_changes_from_upstream(&[STDLIB_SEMVER_CHECK_STAMP_PATH])
4754 {
4755 builder.info(&format!("Skipping stdlib semver check, because {STDLIB_SEMVER_CHECK_STAMP_PATH} was modified."));
4756 return;
4757 }
4758
4759 let Some(docs_dir) = builder.config.download_std_json_docs(self.target, &self.commit)
4760 else {
4761 return;
4762 };
4763
4764 let directory = builder.ensure(crate::core::build_steps::doc::Std::from_build_compiler(
4765 self.build_compiler,
4766 self.target,
4767 DocumentationFormat::Json,
4768 ));
4769 let baseline_dir = docs_dir.join("share").join("doc").join("rust").join("json");
4770
4771 for library in ["core", "alloc", "std"] {
4772 println!("Checking semver compatibility of {library}");
4773 let mut cmd = command(&builder.initial_cargo);
4774 cmd.arg("semver-checks")
4775 .arg("-Z")
4776 .arg("unstable-options")
4777 .arg("--stability-aware")
4778 .arg("--release-type")
4779 .arg("minor")
4780 .arg("--current-rustdoc")
4781 .arg(directory.join(format!("{library}.json")))
4782 .arg("--baseline-rustdoc")
4783 .arg(baseline_dir.join(format!("{library}.json")));
4784
4785 let res = cmd.allow_failure().run_capture(builder);
4787 match res.status() {
4788 Some(status) if status.success() => {
4789 println!("{}\n{}", res.stdout(), res.stderr());
4790 }
4791 Some(status) if status.code() == Some(101) => {
4794 eprintln!(
4795 "cargo-semver-checks was unable to process {library} (this is not a fatal error)\n{}\n{}",
4796 res.stderr(),
4797 res.stdout()
4798 );
4799 }
4800 Some(status) if status.code() == Some(100) => {
4802 let error = format!(
4803 "cargo-semver-checks found semver breakage in {library}\n{}\n{}",
4804 res.stderr(),
4805 res.stdout()
4806 );
4807 if builder.fail_fast {
4808 eprintln!("{error}",);
4809 exit!(1);
4810 } else {
4811 builder.config.exec_ctx().add_to_delay_failure(error);
4812 }
4813 }
4814 _ => {
4815 eprintln!("cargo-semver-checks failed.\n{}\n{}", res.stderr(), res.stdout());
4816 exit!(1);
4817 }
4818 }
4819 }
4820 }
4821}