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.cmd.verbose_run_make_subprocess_output() {
2338 cmd.arg("--verbose-run-make-subprocess-output");
2339 }
2340
2341 if builder.config.rustc_debug_assertions {
2342 cmd.arg("--with-rustc-debug-assertions");
2343 }
2344
2345 if builder.config.std_debug_assertions {
2346 cmd.arg("--with-std-debug-assertions");
2347 }
2348
2349 if builder.config.rust_remap_debuginfo {
2350 cmd.arg("--with-std-remap-debuginfo");
2351 }
2352
2353 cmd.arg("--jobs").arg(builder.jobs().to_string());
2354
2355 let mut llvm_components_passed = false;
2356 let mut copts_passed = false;
2357 if builder.config.llvm_enabled(test_compiler.host) {
2358 let llvm::LlvmResult { host_llvm_config, .. } =
2359 builder.ensure(llvm::Llvm { target: builder.config.host_target });
2360 if !builder.config.dry_run() {
2361 let llvm_version = get_llvm_version(builder, &host_llvm_config);
2362 let llvm_components = command(&host_llvm_config)
2363 .cached()
2364 .arg("--components")
2365 .run_capture_stdout(builder)
2366 .stdout();
2367 cmd.arg("--llvm-version")
2369 .arg(llvm_version.trim())
2370 .arg("--llvm-components")
2371 .arg(llvm_components.trim());
2372 llvm_components_passed = true;
2373 }
2374 if !builder.config.is_rust_llvm(target) {
2375 cmd.arg("--system-llvm");
2376 }
2377
2378 if !builder.config.dry_run() && suite.ends_with("fulldeps") {
2383 let llvm_libdir = command(&host_llvm_config)
2384 .cached()
2385 .arg("--libdir")
2386 .run_capture_stdout(builder)
2387 .stdout();
2388 let link_llvm = if target.is_msvc() {
2389 format!("-Clink-arg=-LIBPATH:{llvm_libdir}")
2390 } else {
2391 format!("-Clink-arg=-L{llvm_libdir}")
2392 };
2393 cmd.arg("--host-rustcflags").arg(link_llvm);
2394 }
2395
2396 if !builder.config.dry_run()
2397 && matches!(mode, CompiletestMode::RunMake | CompiletestMode::CoverageRun)
2398 {
2399 let llvm_bin_path = host_llvm_config
2404 .parent()
2405 .expect("Expected llvm-config to be contained in directory");
2406 assert!(llvm_bin_path.is_dir());
2407 cmd.arg("--llvm-bin-dir").arg(llvm_bin_path);
2408 }
2409
2410 if !builder.config.dry_run() && mode == CompiletestMode::RunMake {
2411 if builder.config.lld_enabled {
2413 let lld_install_root =
2414 builder.ensure(llvm::Lld { target: builder.config.host_target });
2415
2416 let lld_bin_path = lld_install_root.join("bin");
2417
2418 let old_path = env::var_os("PATH").unwrap_or_default();
2419 let new_path = env::join_paths(
2420 std::iter::once(lld_bin_path).chain(env::split_paths(&old_path)),
2421 )
2422 .expect("Could not add LLD bin path to PATH");
2423 cmd.env("PATH", new_path);
2424 }
2425 }
2426 }
2427
2428 if !builder.config.dry_run() && mode == CompiletestMode::RunMake {
2431 let mut cflags = builder.cc_handled_clags(target, CLang::C);
2432 cflags.extend(builder.cc_unhandled_cflags(target, GitRepo::Rustc, CLang::C));
2433 let mut cxxflags = builder.cc_handled_clags(target, CLang::Cxx);
2434 cxxflags.extend(builder.cc_unhandled_cflags(target, GitRepo::Rustc, CLang::Cxx));
2435 cmd.arg("--cc")
2436 .arg(builder.cc(target))
2437 .arg("--cxx")
2438 .arg(builder.cxx(target).unwrap())
2439 .arg("--cflags")
2440 .arg(cflags.join(" "))
2441 .arg("--cxxflags")
2442 .arg(cxxflags.join(" "));
2443 copts_passed = true;
2444 if let Some(ar) = builder.ar(target) {
2445 cmd.arg("--ar").arg(ar);
2446 }
2447 }
2448
2449 if !llvm_components_passed {
2450 cmd.arg("--llvm-components").arg("");
2451 }
2452 if !copts_passed {
2453 cmd.arg("--cc")
2454 .arg("")
2455 .arg("--cxx")
2456 .arg("")
2457 .arg("--cflags")
2458 .arg("")
2459 .arg("--cxxflags")
2460 .arg("");
2461 }
2462
2463 if builder.remote_tested(target) {
2464 cmd.arg("--remote-test-client").arg(builder.tool_exe(Tool::RemoteTestClient));
2465 } else if let Some(tool) = builder.runner(target) {
2466 cmd.arg("--runner").arg(tool);
2467 }
2468
2469 if suite != "mir-opt" {
2470 if !builder.config.dry_run() && target.is_msvc() {
2476 for (k, v) in builder.cc[&target].env() {
2477 if k != "PATH" {
2478 cmd.env(k, v);
2479 }
2480 }
2481 }
2482 }
2483
2484 if !builder.config.dry_run()
2486 && target.contains("msvc")
2487 && builder.config.sanitizers_enabled(target)
2488 {
2489 cmd.env("ASAN_WIN_CONTINUE_ON_INTERCEPTION_FAILURE", "1");
2492 let asan_runtime_path = builder.cc[&target].path().parent().unwrap().to_path_buf();
2494 let old_path = cmd
2495 .get_envs()
2496 .find_map(|(k, v)| (k == "PATH").then_some(v))
2497 .flatten()
2498 .map_or_else(|| env::var_os("PATH").unwrap_or_default(), |v| v.to_owned());
2499 let new_path = env::join_paths(
2500 env::split_paths(&old_path).chain(std::iter::once(asan_runtime_path)),
2501 )
2502 .expect("Could not add ASAN runtime path to PATH");
2503 cmd.env("PATH", new_path);
2504 }
2505
2506 cmd.env_remove("CARGO");
2509
2510 cmd.env("RUSTC_BOOTSTRAP", "1");
2511 cmd.env("RUSTC_FORCE_RUSTC_VERSION", "compiletest");
2514 cmd.env("DOC_RUST_LANG_ORG_CHANNEL", builder.doc_rust_lang_org_channel());
2515 builder.add_rust_test_threads(&mut cmd);
2516
2517 if builder.config.sanitizers_enabled(target) {
2518 cmd.env("RUSTC_SANITIZER_SUPPORT", "1");
2519 }
2520
2521 if builder.config.profiler_enabled(target) {
2522 cmd.arg("--profiler-runtime");
2523 }
2524
2525 cmd.env("RUST_TEST_TMPDIR", builder.tempdir());
2526
2527 if builder.config.cmd.rustfix_coverage() {
2528 cmd.arg("--rustfix-coverage");
2529 }
2530
2531 cmd.arg("--channel").arg(&builder.config.channel);
2532
2533 if !builder.config.omit_git_hash {
2534 cmd.arg("--git-hash");
2535 }
2536
2537 let git_config = builder.config.git_config();
2538 cmd.arg("--nightly-branch").arg(git_config.nightly_branch);
2539 cmd.arg("--git-merge-commit-email").arg(git_config.git_merge_commit_email);
2540
2541 #[cfg(feature = "build-metrics")]
2542 builder.metrics.begin_test_suite(
2543 build_helper::metrics::TestSuiteMetadata::Compiletest {
2544 suite: suite.into(),
2545 mode: mode.to_string(),
2546 compare_mode: None,
2547 target: self.target.triple.to_string(),
2548 host: self.test_compiler.host.triple.to_string(),
2549 stage: self.test_compiler.stage,
2550 },
2551 builder,
2552 );
2553
2554 let _group = builder.msg_test(
2555 format!("with compiletest suite={suite} mode={mode}"),
2556 target,
2557 test_compiler.stage,
2558 );
2559 try_run_tests(builder, &mut cmd, false);
2560
2561 if let Some(compare_mode) = compare_mode {
2562 cmd.arg("--compare-mode").arg(compare_mode);
2563
2564 #[cfg(feature = "build-metrics")]
2565 builder.metrics.begin_test_suite(
2566 build_helper::metrics::TestSuiteMetadata::Compiletest {
2567 suite: suite.into(),
2568 mode: mode.to_string(),
2569 compare_mode: Some(compare_mode.into()),
2570 target: self.target.triple.to_string(),
2571 host: self.test_compiler.host.triple.to_string(),
2572 stage: self.test_compiler.stage,
2573 },
2574 builder,
2575 );
2576
2577 builder.info(&format!(
2578 "Check compiletest suite={} mode={} compare_mode={} ({} -> {})",
2579 suite, mode, compare_mode, &test_compiler.host, target
2580 ));
2581 let _time = helpers::timeit(builder);
2582 try_run_tests(builder, &mut cmd, false);
2583 }
2584 }
2585
2586 fn metadata(&self) -> Option<StepMetadata> {
2587 Some(
2588 StepMetadata::test(&format!("compiletest-{}", self.suite), self.target)
2589 .stage(self.test_compiler.stage),
2590 )
2591 }
2592}
2593
2594#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2596struct BookTest {
2597 test_compiler: Compiler,
2598 path: PathBuf,
2599 name: &'static str,
2600 is_ext_doc: bool,
2601 dependencies: Vec<&'static str>,
2602}
2603
2604impl Step for BookTest {
2605 type Output = ();
2606 const IS_HOST: bool = true;
2607
2608 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2609 run.never()
2610 }
2611
2612 fn run(self, builder: &Builder<'_>) {
2613 if self.is_ext_doc {
2623 self.run_ext_doc(builder);
2624 } else {
2625 self.run_local_doc(builder);
2626 }
2627 }
2628}
2629
2630impl BookTest {
2631 fn run_ext_doc(self, builder: &Builder<'_>) {
2634 let test_compiler = self.test_compiler;
2635
2636 builder.std(test_compiler, test_compiler.host);
2637
2638 let mut rustdoc_path = builder.rustdoc_for_compiler(test_compiler);
2641 rustdoc_path.pop();
2642 let old_path = env::var_os("PATH").unwrap_or_default();
2643 let new_path = env::join_paths(iter::once(rustdoc_path).chain(env::split_paths(&old_path)))
2644 .expect("could not add rustdoc to PATH");
2645
2646 let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook);
2647 let path = builder.src.join(&self.path);
2648 rustbook_cmd.env("RUSTC_BOOTSTRAP", "1");
2650 rustbook_cmd.env("PATH", new_path).arg("test").arg(path);
2651
2652 let libs = if !self.dependencies.is_empty() {
2657 let mut lib_paths = vec![];
2658 for dep in self.dependencies {
2659 let mode = Mode::ToolRustcPrivate;
2660 let target = builder.config.host_target;
2661 let cargo = tool::prepare_tool_cargo(
2662 builder,
2663 test_compiler,
2664 mode,
2665 target,
2666 Kind::Build,
2667 dep,
2668 SourceType::Submodule,
2669 &[],
2670 );
2671
2672 let stamp = BuildStamp::new(&builder.cargo_out(test_compiler, mode, target))
2673 .with_prefix(PathBuf::from(dep).file_name().and_then(|v| v.to_str()).unwrap());
2674
2675 let output_paths =
2676 run_cargo(builder, cargo, vec![], &stamp, vec![], ArtifactKeepMode::OnlyRlib);
2677 let directories = output_paths
2678 .into_iter()
2679 .filter_map(|p| p.parent().map(ToOwned::to_owned))
2680 .fold(HashSet::new(), |mut set, dir| {
2681 set.insert(dir);
2682 set
2683 });
2684
2685 lib_paths.extend(directories);
2686 }
2687 lib_paths
2688 } else {
2689 vec![]
2690 };
2691
2692 if !libs.is_empty() {
2693 let paths = libs
2694 .into_iter()
2695 .map(|path| path.into_os_string())
2696 .collect::<Vec<OsString>>()
2697 .join(OsStr::new(","));
2698 rustbook_cmd.args([OsString::from("--library-path"), paths]);
2699 }
2700
2701 builder.add_rust_test_threads(&mut rustbook_cmd);
2702 let _guard = builder.msg_test(
2703 format_args!("mdbook {}", self.path.display()),
2704 test_compiler.host,
2705 test_compiler.stage,
2706 );
2707 let _time = helpers::timeit(builder);
2708 let toolstate = if rustbook_cmd.delay_failure().run(builder) {
2709 ToolState::TestPass
2710 } else {
2711 ToolState::TestFail
2712 };
2713 builder.save_toolstate(self.name, toolstate);
2714 }
2715
2716 fn run_local_doc(self, builder: &Builder<'_>) {
2718 let test_compiler = self.test_compiler;
2719 let host = self.test_compiler.host;
2720
2721 builder.std(test_compiler, host);
2722
2723 let _guard = builder.msg_test(
2724 format!("book {}", self.name),
2725 test_compiler.host,
2726 test_compiler.stage,
2727 );
2728
2729 let mut stack = vec![builder.src.join(self.path)];
2732 let _time = helpers::timeit(builder);
2733 let mut files = Vec::new();
2734 while let Some(p) = stack.pop() {
2735 if p.is_dir() {
2736 stack.extend(t!(p.read_dir()).map(|p| t!(p).path()));
2737 continue;
2738 }
2739
2740 if p.extension().and_then(|s| s.to_str()) != Some("md") {
2741 continue;
2742 }
2743
2744 files.push(p);
2745 }
2746
2747 files.sort();
2748
2749 for file in files {
2750 markdown_test(builder, test_compiler, &file);
2751 }
2752 }
2753}
2754
2755macro_rules! test_book {
2756 ($(
2757 $name:ident, $path:expr, $book_name:expr,
2758 default=$default:expr
2759 $(,submodules = $submodules:expr)?
2760 $(,dependencies=$dependencies:expr)?
2761 ;
2762 )+) => {
2763 $(
2764 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
2765 pub struct $name {
2766 test_compiler: Compiler,
2767 }
2768
2769 impl Step for $name {
2770 type Output = ();
2771 const IS_HOST: bool = true;
2772
2773 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2774 run.path($path)
2775 }
2776
2777 fn is_default_step(_builder: &Builder<'_>) -> bool {
2778 const { $default }
2779 }
2780
2781 fn make_run(run: RunConfig<'_>) {
2782 run.builder.ensure($name {
2783 test_compiler: run.builder.compiler(run.builder.top_stage, run.target),
2784 });
2785 }
2786
2787 fn run(self, builder: &Builder<'_>) {
2788 $(
2789 for submodule in $submodules {
2790 builder.require_submodule(submodule, None);
2791 }
2792 )*
2793
2794 let dependencies = vec![];
2795 $(
2796 let mut dependencies = dependencies;
2797 for dep in $dependencies {
2798 dependencies.push(dep);
2799 }
2800 )?
2801
2802 builder.ensure(BookTest {
2803 test_compiler: self.test_compiler,
2804 path: PathBuf::from($path),
2805 name: $book_name,
2806 is_ext_doc: !$default,
2807 dependencies,
2808 });
2809 }
2810 }
2811 )+
2812 }
2813}
2814
2815test_book!(
2816 Nomicon, "src/doc/nomicon", "nomicon", default=false, submodules=["src/doc/nomicon"];
2817 Reference, "src/doc/reference", "reference", default=false, submodules=["src/doc/reference"];
2818 RustdocBook, "src/doc/rustdoc", "rustdoc", default=true;
2819 RustcBook, "src/doc/rustc", "rustc", default=true;
2820 RustByExample, "src/doc/rust-by-example", "rust-by-example", default=false, submodules=["src/doc/rust-by-example"];
2821 EmbeddedBook, "src/doc/embedded-book", "embedded-book", default=false, submodules=["src/doc/embedded-book"];
2822 TheBook, "src/doc/book", "book", default=false, submodules=["src/doc/book"], dependencies=["src/doc/book/packages/trpl"];
2823 UnstableBook, "src/doc/unstable-book", "unstable-book", default=true;
2824 EditionGuide, "src/doc/edition-guide", "edition-guide", default=false, submodules=["src/doc/edition-guide"];
2825);
2826
2827#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2828pub struct ErrorIndex {
2829 compilers: RustcPrivateCompilers,
2830}
2831
2832impl Step for ErrorIndex {
2833 type Output = ();
2834 const IS_HOST: bool = true;
2835
2836 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2837 run.path("src/tools/error_index_generator").alias("error-index")
2840 }
2841
2842 fn is_default_step(_builder: &Builder<'_>) -> bool {
2843 true
2844 }
2845
2846 fn make_run(run: RunConfig<'_>) {
2847 let compilers = RustcPrivateCompilers::new(
2851 run.builder,
2852 run.builder.top_stage,
2853 run.builder.config.host_target,
2854 );
2855 run.builder.ensure(ErrorIndex { compilers });
2856 }
2857
2858 fn run(self, builder: &Builder<'_>) {
2865 let target_compiler = self.compilers.target_compiler();
2867
2868 let dir = testdir(builder, target_compiler.host);
2869 t!(fs::create_dir_all(&dir));
2870 let output = dir.join("error-index.md");
2871
2872 let mut tool = tool::ErrorIndex::command(builder, self.compilers);
2873 tool.arg("markdown").arg(&output);
2874
2875 let guard = builder.msg_test("error-index", target_compiler.host, target_compiler.stage);
2876 let _time = helpers::timeit(builder);
2877 tool.run_capture(builder);
2878 drop(guard);
2879 builder.std(target_compiler, target_compiler.host);
2882 markdown_test(builder, target_compiler, &output);
2883 }
2884}
2885
2886fn markdown_test(builder: &Builder<'_>, compiler: Compiler, markdown: &Path) -> bool {
2887 if let Ok(contents) = fs::read_to_string(markdown)
2888 && !contents.contains("```")
2889 {
2890 return true;
2891 }
2892
2893 builder.do_if_verbose(|| println!("doc tests for: {}", markdown.display()));
2894 let mut cmd = builder.rustdoc_cmd(compiler);
2895 builder.add_rust_test_threads(&mut cmd);
2896 cmd.arg("-Z");
2898 cmd.arg("unstable-options");
2899 cmd.arg("--test");
2900 cmd.arg(markdown);
2901 cmd.env("RUSTC_BOOTSTRAP", "1");
2902
2903 let test_args = builder.config.test_args().join(" ");
2904 cmd.arg("--test-args").arg(test_args);
2905
2906 cmd = cmd.delay_failure();
2907 if !builder.config.verbose_tests {
2908 cmd.run_capture(builder).is_success()
2909 } else {
2910 cmd.run(builder)
2911 }
2912}
2913
2914#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2919pub struct CrateLibrustc {
2920 build_compiler: Compiler,
2922 target: TargetSelection,
2923 crates: Vec<String>,
2924}
2925
2926impl Step for CrateLibrustc {
2927 type Output = ();
2928 const IS_HOST: bool = true;
2929
2930 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2931 run.crate_or_deps("rustc-main").path("compiler")
2932 }
2933
2934 fn is_default_step(_builder: &Builder<'_>) -> bool {
2935 true
2936 }
2937
2938 fn make_run(run: RunConfig<'_>) {
2939 let builder = run.builder;
2940 let host = run.build_triple();
2941 let build_compiler = builder.compiler(builder.top_stage - 1, host);
2942 let crates = run.make_run_crates(Alias::Compiler);
2943
2944 builder.ensure(CrateLibrustc { build_compiler, target: run.target, crates });
2945 }
2946
2947 fn run(self, builder: &Builder<'_>) {
2948 builder.std(self.build_compiler, self.target);
2949
2950 builder.ensure(Crate {
2952 build_compiler: self.build_compiler,
2953 target: self.target,
2954 mode: Mode::Rustc,
2955 crates: self.crates,
2956 });
2957 }
2958
2959 fn metadata(&self) -> Option<StepMetadata> {
2960 Some(StepMetadata::test("CrateLibrustc", self.target).built_by(self.build_compiler))
2961 }
2962}
2963
2964fn run_cargo_test<'a>(
2968 cargo: builder::Cargo,
2969 libtest_args: &[&str],
2970 crates: &[String],
2971 description: impl Into<Option<&'a str>>,
2972 target: TargetSelection,
2973 builder: &Builder<'_>,
2974) -> bool {
2975 let compiler = cargo.compiler();
2976 let stage = match cargo.mode() {
2977 Mode::Std => compiler.stage,
2978 _ => compiler.stage + 1,
2979 };
2980
2981 let mut cargo = prepare_cargo_test(cargo, libtest_args, crates, target, builder);
2982 let _time = helpers::timeit(builder);
2983
2984 let _group = description.into().and_then(|what| builder.msg_test(what, target, stage));
2985
2986 #[cfg(feature = "build-metrics")]
2987 builder.metrics.begin_test_suite(
2988 build_helper::metrics::TestSuiteMetadata::CargoPackage {
2989 crates: crates.iter().map(|c| c.to_string()).collect(),
2990 target: target.triple.to_string(),
2991 host: compiler.host.triple.to_string(),
2992 stage: compiler.stage,
2993 },
2994 builder,
2995 );
2996 add_flags_and_try_run_tests(builder, &mut cargo)
2997}
2998
2999fn prepare_cargo_test(
3001 cargo: builder::Cargo,
3002 libtest_args: &[&str],
3003 crates: &[String],
3004 target: TargetSelection,
3005 builder: &Builder<'_>,
3006) -> BootstrapCommand {
3007 let compiler = cargo.compiler();
3008 let mut cargo: BootstrapCommand = cargo.into();
3009
3010 if builder.config.cmd.bless() && !cargo.get_envs().any(|v| v.0 == "RUSTC_BLESS") {
3014 cargo.env("RUSTC_BLESS", "Gesundheit");
3015 }
3016
3017 if builder.kind == Kind::Test && !builder.fail_fast {
3021 cargo.arg("--no-fail-fast");
3022 }
3023
3024 if builder.config.json_output {
3025 cargo.arg("--message-format=json");
3026 }
3027
3028 match builder.test_target {
3029 TestTarget::AllTargets => cargo.args(["--bins", "--examples", "--tests", "--benches"]),
3030 TestTarget::Default => &mut cargo,
3031 TestTarget::DocOnly => cargo.arg("--doc"),
3032 TestTarget::Tests => cargo.arg("--tests"),
3033 };
3034
3035 for krate in crates {
3036 cargo.arg("-p").arg(krate);
3037 }
3038
3039 cargo.arg("--").args(builder.config.test_args()).args(libtest_args);
3040 if !builder.config.verbose_tests {
3041 cargo.arg("--quiet");
3042 }
3043
3044 if builder.kind != Kind::Miri {
3053 let mut dylib_paths = builder.rustc_lib_paths(compiler);
3054 dylib_paths.push(builder.sysroot_target_libdir(compiler, target));
3055 helpers::add_dylib_path(dylib_paths, &mut cargo);
3056 }
3057
3058 if builder.remote_tested(target) {
3059 cargo.env(
3060 format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)),
3061 format!("{} run 0", builder.tool_exe(Tool::RemoteTestClient).display()),
3062 );
3063 } else if let Some(tool) = builder.runner(target) {
3064 cargo.env(format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)), tool);
3065 }
3066
3067 cargo
3068}
3069
3070#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3078pub struct Crate {
3079 build_compiler: Compiler,
3081 target: TargetSelection,
3082 mode: Mode,
3083 crates: Vec<String>,
3084}
3085
3086impl Step for Crate {
3087 type Output = ();
3088
3089 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3090 run.crate_or_deps("sysroot").crate_or_deps("coretests").crate_or_deps("alloctests")
3091 }
3092
3093 fn is_default_step(_builder: &Builder<'_>) -> bool {
3094 true
3095 }
3096
3097 fn make_run(run: RunConfig<'_>) {
3098 let builder = run.builder;
3099 let host = run.build_triple();
3100 let build_compiler = builder.compiler(builder.top_stage, host);
3101 let crates = run
3102 .paths
3103 .iter()
3104 .map(|p| builder.crate_paths[&p.assert_single_path().path].clone())
3105 .collect();
3106
3107 builder.ensure(Crate { build_compiler, target: run.target, mode: Mode::Std, crates });
3108 }
3109
3110 fn run(self, builder: &Builder<'_>) {
3119 let build_compiler = self.build_compiler;
3120 let target = self.target;
3121 let mode = self.mode;
3122
3123 builder.ensure(Std::new(build_compiler, build_compiler.host).force_recompile(true));
3126
3127 let mut cargo = if builder.kind == Kind::Miri {
3128 if builder.top_stage == 0 {
3129 eprintln!("ERROR: `x.py miri` requires stage 1 or higher");
3130 std::process::exit(1);
3131 }
3132
3133 let mut cargo = builder::Cargo::new(
3136 builder,
3137 build_compiler,
3138 mode,
3139 SourceType::InTree,
3140 target,
3141 Kind::MiriTest,
3142 );
3143 cargo.env("MIRI_REPLACE_LIBRS_IF_NOT_TEST", "1");
3155 cargo.rustflag("-Zforce-unstable-if-unmarked");
3159 cargo.env(
3164 "MIRIFLAGS",
3165 format!(
3166 "{} -Zmiri-env-forward=RUSTC_BOOTSTRAP",
3167 env::var("MIRIFLAGS").unwrap_or_default()
3168 ),
3169 );
3170 cargo
3171 } else {
3172 if !builder.config.is_host_target(target) {
3174 builder.ensure(compile::Std::new(build_compiler, target).force_recompile(true));
3175 builder.ensure(RemoteCopyLibs { build_compiler, target });
3176 }
3177
3178 builder::Cargo::new(
3180 builder,
3181 build_compiler,
3182 mode,
3183 SourceType::InTree,
3184 target,
3185 builder.kind,
3186 )
3187 };
3188
3189 match mode {
3190 Mode::Std => {
3191 if builder.kind == Kind::Miri {
3192 cargo
3198 .arg("--manifest-path")
3199 .arg(builder.src.join("library/sysroot/Cargo.toml"));
3200 } else {
3201 compile::std_cargo(builder, target, &mut cargo, &[]);
3202 }
3203 }
3204 Mode::Rustc => {
3205 compile::rustc_cargo(builder, &mut cargo, target, &build_compiler, &self.crates);
3206 }
3207 _ => panic!("can only test libraries"),
3208 };
3209
3210 let mut crates = self.crates.clone();
3211 if crates.iter().any(|crate_| crate_ == "core") {
3216 crates.push("coretests".to_owned());
3217 }
3218 if crates.iter().any(|crate_| crate_ == "alloc") {
3219 crates.push("alloctests".to_owned());
3220 }
3221
3222 run_cargo_test(cargo, &[], &crates, &*crate_description(&self.crates), target, builder);
3223 }
3224}
3225
3226#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3229pub struct CrateRustdoc {
3230 host: TargetSelection,
3231}
3232
3233impl Step for CrateRustdoc {
3234 type Output = ();
3235 const IS_HOST: bool = true;
3236
3237 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3238 run.path("src/librustdoc").path("src/tools/rustdoc")
3239 }
3240
3241 fn is_default_step(_builder: &Builder<'_>) -> bool {
3242 true
3243 }
3244
3245 fn make_run(run: RunConfig<'_>) {
3246 let builder = run.builder;
3247
3248 builder.ensure(CrateRustdoc { host: run.target });
3249 }
3250
3251 fn run(self, builder: &Builder<'_>) {
3252 let target = self.host;
3253
3254 let compiler = if builder.download_rustc() {
3255 builder.compiler(builder.top_stage, target)
3256 } else {
3257 builder.compiler_for(builder.top_stage, target, target)
3262 };
3263 builder.std(compiler, target);
3268 builder.ensure(compile::Rustc::new(compiler, target));
3269
3270 let mut cargo = tool::prepare_tool_cargo(
3271 builder,
3272 compiler,
3273 Mode::ToolRustcPrivate,
3274 target,
3275 builder.kind,
3276 "src/tools/rustdoc",
3277 SourceType::InTree,
3278 &[],
3279 );
3280 if self.host.contains("musl") {
3281 cargo.arg("'-Ctarget-feature=-crt-static'");
3282 }
3283
3284 let libdir = if builder.download_rustc() {
3311 builder.rustc_libdir(compiler)
3312 } else {
3313 builder.sysroot_target_libdir(compiler, target).to_path_buf()
3314 };
3315 let mut dylib_path = dylib_path();
3316 dylib_path.insert(0, PathBuf::from(&*libdir));
3317 cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());
3318
3319 run_cargo_test(cargo, &[], &["rustdoc:0.0.0".to_string()], "rustdoc", target, builder);
3320 }
3321}
3322
3323#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3324pub struct CrateRustdocJsonTypes {
3325 build_compiler: Compiler,
3326 target: TargetSelection,
3327}
3328
3329impl Step for CrateRustdocJsonTypes {
3330 type Output = ();
3331 const IS_HOST: bool = true;
3332
3333 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3334 run.path("src/rustdoc-json-types")
3335 }
3336
3337 fn is_default_step(_builder: &Builder<'_>) -> bool {
3338 true
3339 }
3340
3341 fn make_run(run: RunConfig<'_>) {
3342 let builder = run.builder;
3343
3344 builder.ensure(CrateRustdocJsonTypes {
3345 build_compiler: get_tool_target_compiler(
3346 builder,
3347 ToolTargetBuildMode::Build(run.target),
3348 ),
3349 target: run.target,
3350 });
3351 }
3352
3353 fn run(self, builder: &Builder<'_>) {
3354 let target = self.target;
3355
3356 let cargo = tool::prepare_tool_cargo(
3357 builder,
3358 self.build_compiler,
3359 Mode::ToolTarget,
3360 target,
3361 builder.kind,
3362 "src/rustdoc-json-types",
3363 SourceType::InTree,
3364 &["rkyv_0_8".to_owned()],
3365 );
3366
3367 let libtest_args = if target.contains("musl") {
3369 ["'-Ctarget-feature=-crt-static'"].as_slice()
3370 } else {
3371 &[]
3372 };
3373
3374 run_cargo_test(
3375 cargo,
3376 libtest_args,
3377 &["rustdoc-json-types".to_string()],
3378 "rustdoc-json-types",
3379 target,
3380 builder,
3381 );
3382 }
3383}
3384
3385#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3395pub struct RemoteCopyLibs {
3396 build_compiler: Compiler,
3397 target: TargetSelection,
3398}
3399
3400impl Step for RemoteCopyLibs {
3401 type Output = ();
3402
3403 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3404 run.never()
3405 }
3406
3407 fn run(self, builder: &Builder<'_>) {
3408 let build_compiler = self.build_compiler;
3409 let target = self.target;
3410 if !builder.remote_tested(target) {
3411 return;
3412 }
3413
3414 builder.std(build_compiler, target);
3415
3416 builder.info(&format!("REMOTE copy libs to emulator ({target})"));
3417
3418 let remote_test_server = builder.ensure(tool::RemoteTestServer { build_compiler, target });
3419
3420 let tool = builder.tool_exe(Tool::RemoteTestClient);
3422 let mut cmd = command(&tool);
3423 cmd.arg("spawn-emulator")
3424 .arg(target.triple)
3425 .arg(&remote_test_server.tool_path)
3426 .arg(builder.tempdir());
3427 if let Some(rootfs) = builder.qemu_rootfs(target) {
3428 cmd.arg(rootfs);
3429 }
3430 cmd.run(builder);
3431
3432 for f in t!(builder.sysroot_target_libdir(build_compiler, target).read_dir()) {
3434 let f = t!(f);
3435 if helpers::is_dylib(&f.path()) {
3436 command(&tool).arg("push").arg(f.path()).run(builder);
3437 }
3438 }
3439 }
3440}
3441
3442#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3443pub struct Distcheck;
3444
3445impl Step for Distcheck {
3446 type Output = ();
3447
3448 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3449 run.alias("distcheck")
3450 }
3451
3452 fn make_run(run: RunConfig<'_>) {
3453 run.builder.ensure(Distcheck);
3454 }
3455
3456 fn run(self, builder: &Builder<'_>) {
3466 let root_dir = std::env::temp_dir().join("distcheck");
3469
3470 distcheck_plain_source_tarball(builder, &root_dir.join("distcheck-rustc-src"));
3471 distcheck_rust_src(builder, &root_dir.join("distcheck-rust-src"));
3472 distcheck_rustc_dev(builder, &root_dir.join("distcheck-rustc-dev"));
3473 }
3474}
3475
3476fn distcheck_plain_source_tarball(builder: &Builder<'_>, plain_src_dir: &Path) {
3478 builder.info("Distcheck plain source tarball");
3479 let plain_src_tarball = builder.ensure(dist::PlainSourceTarball);
3480 builder.clear_dir(plain_src_dir);
3481
3482 let configure_args: Vec<String> = std::env::var("DISTCHECK_CONFIGURE_ARGS")
3483 .map(|args| args.split(" ").map(|s| s.to_string()).collect::<Vec<String>>())
3484 .unwrap_or_default();
3485
3486 command("tar")
3487 .arg("-xf")
3488 .arg(plain_src_tarball.tarball())
3489 .arg("--strip-components=1")
3490 .current_dir(plain_src_dir)
3491 .run(builder);
3492 command("./configure")
3493 .arg("--set")
3494 .arg("rust.omit-git-hash=false")
3495 .arg("--set")
3496 .arg("rust.remap-debuginfo=false")
3497 .args(&configure_args)
3498 .arg("--enable-vendor")
3499 .current_dir(plain_src_dir)
3500 .run(builder);
3501 command(helpers::make(&builder.config.host_target.triple))
3502 .arg("check")
3503 .env("GITHUB_ACTIONS", "0")
3506 .current_dir(plain_src_dir)
3507 .run(builder);
3508 builder.remove_dir(plain_src_dir);
3510}
3511
3512fn distcheck_rust_src(builder: &Builder<'_>, src_dir: &Path) {
3514 builder.info("Distcheck rust-src");
3515 let src_tarball = builder.ensure(dist::Src);
3516 builder.clear_dir(src_dir);
3517
3518 command("tar")
3519 .arg("-xf")
3520 .arg(src_tarball.tarball())
3521 .arg("--strip-components=1")
3522 .current_dir(src_dir)
3523 .run(builder);
3524
3525 let toml = src_dir.join("rust-src/lib/rustlib/src/rust/library/std/Cargo.toml");
3526 command(&builder.initial_cargo)
3527 .env("RUSTC_BOOTSTRAP", "1")
3530 .arg("generate-lockfile")
3531 .arg("--manifest-path")
3532 .arg(&toml)
3533 .current_dir(src_dir)
3534 .run(builder);
3535 builder.remove_dir(src_dir);
3537}
3538
3539fn distcheck_rustc_dev(builder: &Builder<'_>, dir: &Path) {
3541 builder.info("Distcheck rustc-dev");
3542 let tarball = builder.ensure(dist::RustcDev::new(builder, builder.host_target)).unwrap();
3543 builder.clear_dir(dir);
3544
3545 command("tar")
3546 .arg("-xf")
3547 .arg(tarball.tarball())
3548 .arg("--strip-components=1")
3549 .current_dir(dir)
3550 .run(builder);
3551
3552 command(&builder.initial_cargo)
3553 .arg("metadata")
3554 .arg("--manifest-path")
3555 .arg("rustc-dev/lib/rustlib/rustc-src/rust/compiler/rustc/Cargo.toml")
3556 .env("RUSTC_BOOTSTRAP", "1")
3557 .env("RUSTC", &builder.initial_rustc)
3559 .current_dir(dir)
3560 .run(builder);
3561 builder.remove_dir(dir);
3563}
3564
3565#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3567pub(crate) struct BootstrapPy;
3568
3569impl Step for BootstrapPy {
3570 type Output = ();
3571 const IS_HOST: bool = true;
3572
3573 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3574 run.alias("bootstrap-py")
3575 }
3576
3577 fn is_default_step(builder: &Builder<'_>) -> bool {
3578 builder.config.is_running_on_ci()
3582 }
3583
3584 fn make_run(run: RunConfig<'_>) {
3585 run.builder.ensure(BootstrapPy)
3586 }
3587
3588 fn run(self, builder: &Builder<'_>) -> Self::Output {
3589 let mut check_bootstrap = command(
3590 builder.config.python.as_ref().expect("python is required for running bootstrap tests"),
3591 );
3592 check_bootstrap
3593 .args(["-m", "unittest", "bootstrap_test.py"])
3594 .args(builder.config.test_args())
3596 .env("BUILD_DIR", &builder.out)
3597 .env("BUILD_PLATFORM", builder.build.host_target.triple)
3598 .env("BOOTSTRAP_TEST_RUSTC_BIN", &builder.initial_rustc)
3599 .env("BOOTSTRAP_TEST_CARGO_BIN", &builder.initial_cargo)
3600 .current_dir(builder.src.join("src/bootstrap/"));
3601 check_bootstrap.delay_failure().run(builder);
3602 }
3603}
3604
3605#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3606pub struct Bootstrap;
3607
3608impl Step for Bootstrap {
3609 type Output = ();
3610 const IS_HOST: bool = true;
3611
3612 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3613 run.path("src/bootstrap")
3614 }
3615
3616 fn is_default_step(builder: &Builder<'_>) -> bool {
3617 builder.config.is_running_on_ci()
3621 }
3622
3623 fn run(self, builder: &Builder<'_>) {
3625 let host = builder.config.host_target;
3626 let build_compiler = builder.compiler(0, host);
3627
3628 builder.build.require_submodule("src/tools/cargo", None);
3630
3631 let mut cargo = tool::prepare_tool_cargo(
3632 builder,
3633 build_compiler,
3634 Mode::ToolBootstrap,
3635 host,
3636 Kind::Test,
3637 "src/bootstrap",
3638 SourceType::InTree,
3639 &[],
3640 );
3641
3642 cargo.release_build(false);
3643
3644 cargo
3645 .rustflag("-Cdebuginfo=2")
3646 .env("CARGO_TARGET_DIR", builder.out.join("bootstrap"))
3647 .env("INSTA_WORKSPACE_ROOT", &builder.src)
3649 .env("RUSTC_BOOTSTRAP", "1");
3650
3651 if builder.config.cmd.bless() {
3652 cargo.env("INSTA_UPDATE", "always");
3656 }
3657
3658 run_cargo_test(cargo, &[], &[], None, host, builder);
3659 }
3660
3661 fn make_run(run: RunConfig<'_>) {
3662 run.builder.ensure(Bootstrap);
3663 }
3664}
3665
3666fn get_compiler_to_test(builder: &Builder<'_>, target: TargetSelection) -> Compiler {
3667 builder.compiler(builder.top_stage, target)
3668}
3669
3670#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3673pub struct TierCheck {
3674 test_compiler: Compiler,
3675}
3676
3677impl Step for TierCheck {
3678 type Output = ();
3679 const IS_HOST: bool = true;
3680
3681 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3682 run.path("src/tools/tier-check")
3683 }
3684
3685 fn is_default_step(_builder: &Builder<'_>) -> bool {
3686 true
3687 }
3688
3689 fn make_run(run: RunConfig<'_>) {
3690 run.builder
3691 .ensure(TierCheck { test_compiler: get_compiler_to_test(run.builder, run.target) });
3692 }
3693
3694 fn run(self, builder: &Builder<'_>) {
3695 let tool_build_compiler = builder.compiler(0, builder.host_target);
3696
3697 let mut cargo = tool::prepare_tool_cargo(
3698 builder,
3699 tool_build_compiler,
3700 Mode::ToolBootstrap,
3701 tool_build_compiler.host,
3702 Kind::Run,
3703 "src/tools/tier-check",
3704 SourceType::InTree,
3705 &[],
3706 );
3707 cargo.arg(builder.src.join("src/doc/rustc/src/platform-support.md"));
3708 cargo.arg(builder.rustc(self.test_compiler));
3709
3710 let _guard = builder.msg_test(
3711 "platform support check",
3712 self.test_compiler.host,
3713 self.test_compiler.stage,
3714 );
3715 BootstrapCommand::from(cargo).delay_failure().run(builder);
3716 }
3717
3718 fn metadata(&self) -> Option<StepMetadata> {
3719 Some(StepMetadata::test("tier-check", self.test_compiler.host))
3720 }
3721}
3722
3723#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3724pub struct LintDocs {
3725 build_compiler: Compiler,
3726 target: TargetSelection,
3727}
3728
3729impl Step for LintDocs {
3730 type Output = ();
3731 const IS_HOST: bool = true;
3732
3733 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3734 run.path("src/tools/lint-docs")
3735 }
3736
3737 fn is_default_step(builder: &Builder<'_>) -> bool {
3738 builder.top_stage >= 2
3741 }
3742
3743 fn make_run(run: RunConfig<'_>) {
3744 if run.builder.top_stage < 2 {
3745 eprintln!("WARNING: lint-docs tests might not work below stage 2");
3746 }
3747
3748 run.builder.ensure(LintDocs {
3749 build_compiler: prepare_doc_compiler(
3750 run.builder,
3751 run.builder.config.host_target,
3752 run.builder.top_stage,
3753 ),
3754 target: run.target,
3755 });
3756 }
3757
3758 fn run(self, builder: &Builder<'_>) {
3761 builder.ensure(crate::core::build_steps::doc::RustcBook::validate(
3762 self.build_compiler,
3763 self.target,
3764 ));
3765 }
3766
3767 fn metadata(&self) -> Option<StepMetadata> {
3768 Some(StepMetadata::test("lint-docs", self.target).built_by(self.build_compiler))
3769 }
3770}
3771
3772#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3773pub struct RustInstaller;
3774
3775impl Step for RustInstaller {
3776 type Output = ();
3777 const IS_HOST: bool = true;
3778
3779 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3780 run.path("src/tools/rust-installer")
3781 }
3782
3783 fn is_default_step(_builder: &Builder<'_>) -> bool {
3784 true
3785 }
3786
3787 fn make_run(run: RunConfig<'_>) {
3788 run.builder.ensure(Self);
3789 }
3790
3791 fn run(self, builder: &Builder<'_>) {
3793 let bootstrap_host = builder.config.host_target;
3794 let build_compiler = builder.compiler(0, bootstrap_host);
3795 let cargo = tool::prepare_tool_cargo(
3796 builder,
3797 build_compiler,
3798 Mode::ToolBootstrap,
3799 bootstrap_host,
3800 Kind::Test,
3801 "src/tools/rust-installer",
3802 SourceType::InTree,
3803 &[],
3804 );
3805
3806 let _guard = builder.msg_test("rust-installer", bootstrap_host, 1);
3807 run_cargo_test(cargo, &[], &[], None, bootstrap_host, builder);
3808
3809 if bootstrap_host != "x86_64-unknown-linux-gnu" {
3813 return;
3814 }
3815
3816 let mut cmd = command(builder.src.join("src/tools/rust-installer/test.sh"));
3817 let tmpdir = testdir(builder, build_compiler.host).join("rust-installer");
3818 let _ = std::fs::remove_dir_all(&tmpdir);
3819 let _ = std::fs::create_dir_all(&tmpdir);
3820 cmd.current_dir(&tmpdir);
3821 cmd.env("CARGO_TARGET_DIR", tmpdir.join("cargo-target"));
3822 cmd.env("CARGO", &builder.initial_cargo);
3823 cmd.env("RUSTC", &builder.initial_rustc);
3824 cmd.env("TMP_DIR", &tmpdir);
3825 cmd.delay_failure().run(builder);
3826 }
3827}
3828
3829#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3830pub struct TestHelpers {
3831 pub target: TargetSelection,
3832}
3833
3834impl Step for TestHelpers {
3835 type Output = ();
3836
3837 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3838 run.path("tests/auxiliary/rust_test_helpers.c")
3839 }
3840
3841 fn make_run(run: RunConfig<'_>) {
3842 run.builder.ensure(TestHelpers { target: run.target })
3843 }
3844
3845 fn run(self, builder: &Builder<'_>) {
3848 if builder.config.dry_run() {
3849 return;
3850 }
3851 let target = if self.target == "x86_64-fortanix-unknown-sgx" {
3855 TargetSelection::from_user("x86_64-unknown-linux-gnu")
3856 } else {
3857 self.target
3858 };
3859 let dst = builder.test_helpers_out(target);
3860 let src = builder.src.join("tests/auxiliary/rust_test_helpers.c");
3861 if up_to_date(&src, &dst.join("librust_test_helpers.a")) {
3862 return;
3863 }
3864
3865 let _guard = builder.msg_unstaged(Kind::Build, "test helpers", target);
3866 t!(fs::create_dir_all(&dst));
3867 let mut cfg = cc::Build::new();
3868
3869 if !target.is_msvc() {
3873 if let Some(ar) = builder.ar(target) {
3874 cfg.archiver(ar);
3875 }
3876 cfg.compiler(builder.cc(target));
3877 }
3878 cfg.cargo_metadata(false)
3879 .out_dir(&dst)
3880 .target(&target.triple)
3881 .host(&builder.config.host_target.triple)
3882 .opt_level(0)
3883 .warnings(false)
3884 .debug(false)
3885 .file(builder.src.join("tests/auxiliary/rust_test_helpers.c"))
3886 .compile("rust_test_helpers");
3887 }
3888}
3889
3890#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3891pub struct CodegenCranelift {
3892 compilers: RustcPrivateCompilers,
3893 target: TargetSelection,
3894}
3895
3896impl Step for CodegenCranelift {
3897 type Output = ();
3898 const IS_HOST: bool = true;
3899
3900 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3901 run.path("compiler/rustc_codegen_cranelift")
3902 }
3903
3904 fn is_default_step(_builder: &Builder<'_>) -> bool {
3905 true
3906 }
3907
3908 fn make_run(run: RunConfig<'_>) {
3909 let builder = run.builder;
3910 let host = run.build_triple();
3911 let compilers = RustcPrivateCompilers::new(run.builder, run.builder.top_stage, host);
3912
3913 if builder.test_target == TestTarget::DocOnly {
3914 return;
3915 }
3916
3917 if builder.download_rustc() {
3918 builder.info("CI rustc uses the default codegen backend. skipping");
3919 return;
3920 }
3921
3922 if !target_supports_cranelift_backend(run.target) {
3923 builder.info("target not supported by rustc_codegen_cranelift. skipping");
3924 return;
3925 }
3926
3927 if builder.remote_tested(run.target) {
3928 builder.info("remote testing is not supported by rustc_codegen_cranelift. skipping");
3929 return;
3930 }
3931
3932 if !builder
3933 .config
3934 .enabled_codegen_backends(run.target)
3935 .contains(&CodegenBackendKind::Cranelift)
3936 {
3937 builder.info("cranelift not in rust.codegen-backends. skipping");
3938 return;
3939 }
3940
3941 builder.ensure(CodegenCranelift { compilers, target: run.target });
3942 }
3943
3944 fn run(self, builder: &Builder<'_>) {
3945 let compilers = self.compilers;
3946 let build_compiler = compilers.build_compiler();
3947
3948 let target_compiler = compilers.target_compiler();
3951 let target = self.target;
3952
3953 builder.std(target_compiler, target);
3954
3955 let mut cargo = builder::Cargo::new(
3956 builder,
3957 target_compiler,
3958 Mode::Codegen, SourceType::InTree,
3960 target,
3961 Kind::Run,
3962 );
3963
3964 cargo.current_dir(&builder.src.join("compiler/rustc_codegen_cranelift"));
3965 cargo
3966 .arg("--manifest-path")
3967 .arg(builder.src.join("compiler/rustc_codegen_cranelift/build_system/Cargo.toml"));
3968 compile::rustc_cargo_env(builder, &mut cargo, target);
3969
3970 cargo.env("CARGO_BUILD_INCREMENTAL", "false");
3972
3973 let _guard = builder.msg_test(
3974 "rustc_codegen_cranelift",
3975 target_compiler.host,
3976 target_compiler.stage,
3977 );
3978
3979 let download_dir = builder.out.join("cg_clif_download");
3981
3982 cargo
3983 .arg("--")
3984 .arg("test")
3985 .arg("--download-dir")
3986 .arg(&download_dir)
3987 .arg("--out-dir")
3988 .arg(builder.stage_out(build_compiler, Mode::Codegen).join("cg_clif"))
3989 .arg("--no-unstable-features")
3990 .arg("--use-backend")
3991 .arg("cranelift")
3992 .arg("--sysroot")
3994 .arg("llvm")
3995 .arg("--skip-test")
3998 .arg("testsuite.extended_sysroot");
3999
4000 cargo.into_cmd().run(builder);
4001 }
4002
4003 fn metadata(&self) -> Option<StepMetadata> {
4004 Some(
4005 StepMetadata::test("rustc_codegen_cranelift", self.target)
4006 .built_by(self.compilers.build_compiler()),
4007 )
4008 }
4009}
4010
4011#[derive(Debug, Clone, PartialEq, Eq, Hash)]
4012pub struct CodegenGCC {
4013 compilers: RustcPrivateCompilers,
4014 target: TargetSelection,
4015}
4016
4017impl Step for CodegenGCC {
4018 type Output = ();
4019 const IS_HOST: bool = true;
4020
4021 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
4022 run.path("compiler/rustc_codegen_gcc")
4023 }
4024
4025 fn is_default_step(_builder: &Builder<'_>) -> bool {
4026 true
4027 }
4028
4029 fn make_run(run: RunConfig<'_>) {
4030 let builder = run.builder;
4031 let host = run.build_triple();
4032 let compilers = RustcPrivateCompilers::new(run.builder, run.builder.top_stage, host);
4033
4034 if builder.test_target == TestTarget::DocOnly {
4035 return;
4036 }
4037
4038 if builder.download_rustc() {
4039 builder.info("CI rustc uses the default codegen backend. skipping");
4040 return;
4041 }
4042
4043 let triple = run.target.triple;
4044 let target_supported =
4045 if triple.contains("linux") { triple.contains("x86_64") } else { false };
4046 if !target_supported {
4047 builder.info("target not supported by rustc_codegen_gcc. skipping");
4048 return;
4049 }
4050
4051 if builder.remote_tested(run.target) {
4052 builder.info("remote testing is not supported by rustc_codegen_gcc. skipping");
4053 return;
4054 }
4055
4056 if !builder.config.enabled_codegen_backends(run.target).contains(&CodegenBackendKind::Gcc) {
4057 builder.info("gcc not in rust.codegen-backends. skipping");
4058 return;
4059 }
4060
4061 builder.ensure(CodegenGCC { compilers, target: run.target });
4062 }
4063
4064 fn run(self, builder: &Builder<'_>) {
4065 let compilers = self.compilers;
4066 let target = self.target;
4067
4068 let gcc = builder.ensure(Gcc { target_pair: GccTargetPair::for_native_build(target) });
4069
4070 builder.ensure(
4071 compile::Std::new(compilers.build_compiler(), target)
4072 .extra_rust_args(&["-Csymbol-mangling-version=v0", "-Cpanic=abort"]),
4073 );
4074
4075 let _guard = builder.msg_test(
4076 "rustc_codegen_gcc",
4077 compilers.target(),
4078 compilers.target_compiler().stage,
4079 );
4080
4081 let mut cargo = builder::Cargo::new(
4082 builder,
4083 compilers.build_compiler(),
4084 Mode::Codegen, SourceType::InTree,
4086 target,
4087 Kind::Run,
4088 );
4089
4090 cargo.current_dir(&builder.src.join("compiler/rustc_codegen_gcc"));
4091 cargo
4092 .arg("--manifest-path")
4093 .arg(builder.src.join("compiler/rustc_codegen_gcc/build_system/Cargo.toml"));
4094 compile::rustc_cargo_env(builder, &mut cargo, target);
4095 add_cg_gcc_cargo_flags(&mut cargo, &gcc);
4096
4097 cargo.env("CARGO_BUILD_INCREMENTAL", "false");
4099 cargo.rustflag("-Cpanic=abort");
4100
4101 cargo
4102 .env("CG_RUSTFLAGS", "-Alinker-messages")
4104 .arg("--")
4105 .arg("test")
4106 .arg("--use-backend")
4107 .arg("gcc")
4108 .arg("--gcc-path")
4109 .arg(gcc.libgccjit().parent().unwrap())
4110 .arg("--out-dir")
4111 .arg(builder.stage_out(compilers.build_compiler(), Mode::Codegen).join("cg_gcc"))
4112 .arg("--release")
4113 .arg("--mini-tests")
4114 .arg("--std-tests");
4115
4116 cargo.args(builder.config.test_args());
4117
4118 cargo.into_cmd().run(builder);
4119 }
4120
4121 fn metadata(&self) -> Option<StepMetadata> {
4122 Some(
4123 StepMetadata::test("rustc_codegen_gcc", self.target)
4124 .built_by(self.compilers.build_compiler()),
4125 )
4126 }
4127}
4128
4129#[derive(Debug, Clone, PartialEq, Eq, Hash)]
4134pub struct TestFloatParse {
4135 build_compiler: Compiler,
4144 target: TargetSelection,
4146}
4147
4148impl Step for TestFloatParse {
4149 type Output = ();
4150 const IS_HOST: bool = true;
4151
4152 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
4153 run.path("src/tools/test-float-parse")
4154 }
4155
4156 fn is_default_step(_builder: &Builder<'_>) -> bool {
4157 true
4158 }
4159
4160 fn make_run(run: RunConfig<'_>) {
4161 run.builder.ensure(Self {
4162 build_compiler: get_compiler_to_test(run.builder, run.target),
4163 target: run.target,
4164 });
4165 }
4166
4167 fn run(self, builder: &Builder<'_>) {
4168 let build_compiler = self.build_compiler;
4169 let target = self.target;
4170
4171 builder.std(build_compiler, target);
4173 builder.std(build_compiler, builder.host_target);
4174
4175 let mut cargo_test = tool::prepare_tool_cargo(
4177 builder,
4178 build_compiler,
4179 Mode::ToolStd,
4180 target,
4181 Kind::Test,
4182 "src/tools/test-float-parse",
4183 SourceType::InTree,
4184 &[],
4185 );
4186 cargo_test.allow_features(TEST_FLOAT_PARSE_ALLOW_FEATURES);
4187
4188 run_cargo_test(cargo_test, &[], &[], "test-float-parse", target, builder);
4189
4190 let mut cargo_run = tool::prepare_tool_cargo(
4192 builder,
4193 build_compiler,
4194 Mode::ToolStd,
4195 target,
4196 Kind::Run,
4197 "src/tools/test-float-parse",
4198 SourceType::InTree,
4199 &[],
4200 );
4201 cargo_run.allow_features(TEST_FLOAT_PARSE_ALLOW_FEATURES);
4202
4203 if !matches!(env::var("FLOAT_PARSE_TESTS_NO_SKIP_HUGE").as_deref(), Ok("1") | Ok("true")) {
4204 cargo_run.args(["--", "--skip-huge"]);
4205 }
4206
4207 cargo_run.into_cmd().run(builder);
4208 }
4209}
4210
4211#[derive(Debug, Clone, Hash, PartialEq, Eq)]
4215pub struct CollectLicenseMetadata;
4216
4217impl Step for CollectLicenseMetadata {
4218 type Output = PathBuf;
4219 const IS_HOST: bool = true;
4220
4221 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
4222 run.path("src/tools/collect-license-metadata")
4223 }
4224
4225 fn make_run(run: RunConfig<'_>) {
4226 run.builder.ensure(CollectLicenseMetadata);
4227 }
4228
4229 fn run(self, builder: &Builder<'_>) -> Self::Output {
4230 let Some(reuse) = &builder.config.reuse else {
4231 panic!("REUSE is required to collect the license metadata");
4232 };
4233
4234 let dest = builder.src.join("license-metadata.json");
4235
4236 let mut cmd = builder.tool_cmd(Tool::CollectLicenseMetadata);
4237 cmd.env("REUSE_EXE", reuse);
4238 cmd.env("DEST", &dest);
4239 cmd.env("ONLY_CHECK", "1");
4240 cmd.run(builder);
4241
4242 dest
4243 }
4244}
4245
4246#[derive(Debug, Clone, PartialEq, Eq, Hash)]
4247pub struct RemoteTestClientTests {
4248 host: TargetSelection,
4249}
4250
4251impl Step for RemoteTestClientTests {
4252 type Output = ();
4253 const IS_HOST: bool = true;
4254
4255 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
4256 run.path("src/tools/remote-test-client")
4257 }
4258
4259 fn is_default_step(_builder: &Builder<'_>) -> bool {
4260 true
4261 }
4262
4263 fn make_run(run: RunConfig<'_>) {
4264 run.builder.ensure(Self { host: run.target });
4265 }
4266
4267 fn run(self, builder: &Builder<'_>) {
4268 let bootstrap_host = builder.config.host_target;
4269 let compiler = builder.compiler(0, bootstrap_host);
4270
4271 let cargo = tool::prepare_tool_cargo(
4272 builder,
4273 compiler,
4274 Mode::ToolBootstrap,
4275 bootstrap_host,
4276 Kind::Test,
4277 "src/tools/remote-test-client",
4278 SourceType::InTree,
4279 &[],
4280 );
4281
4282 run_cargo_test(cargo, &[], &[], "remote-test-client", bootstrap_host, builder);
4283 }
4284}