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