1use std::fs;
4use std::path::{Path, PathBuf};
5
6use crate::core::backend::CodegenBackendKind;
7use crate::core::build_steps::compile::{
8 ArtifactKeepMode, add_to_sysroot, run_cargo, rustc_cargo, std_cargo, std_crates_for_make_run,
9};
10use crate::core::build_steps::tool;
11use crate::core::build_steps::tool::{
12 SourceType, TEST_FLOAT_PARSE_ALLOW_FEATURES, ToolTargetBuildMode, get_tool_target_compiler,
13 prepare_tool_cargo,
14};
15use crate::core::builder::{
16 self, Alias, Builder, Cargo, CommandLineStep, Kind, RunConfig, ShouldRun, Step, StepMetadata,
17 crate_description,
18};
19use crate::core::compiler::Compiler;
20use crate::core::config::TargetSelection;
21use crate::core::session::Mode;
22use crate::utils::build_stamp::{self, BuildStamp};
23use crate::utils::helpers::t;
24
25#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
28enum CheckKind {
29 Check,
30 Fix,
31}
32
33impl CheckKind {
34 fn to_kind(self) -> Kind {
35 match self {
36 CheckKind::Check => Kind::Check,
37 CheckKind::Fix => Kind::Fix,
38 }
39 }
40}
41
42#[derive(Debug, Clone, PartialEq, Eq, Hash)]
43pub struct Std {
44 pub build_compiler: Compiler,
46 pub target: TargetSelection,
47 crates: Vec<String>,
53}
54
55impl Std {
56 const CRATE_OR_DEPS: &[&str] = &["sysroot", "coretests", "alloctests"];
57}
58
59impl CommandLineStep for Std {
60 type Output = BuildStamp;
61
62 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
63 let mut run = run;
64 for c in Std::CRATE_OR_DEPS {
65 run = run.crate_or_deps(c);
66 }
67
68 run.path("library")
69 }
70
71 fn is_default_step(_builder: &Builder<'_>) -> bool {
72 true
73 }
74
75 fn make_run(run: RunConfig<'_>) {
76 if !run.builder.download_rustc() && run.builder.config.skip_std_check_if_no_download_rustc {
77 eprintln!(
78 "WARNING: `--skip-std-check-if-no-download-rustc` flag was passed and `rust.download-rustc` is not available. Skipping."
79 );
80 return;
81 }
82
83 if run.builder.config.compile_time_deps {
84 return;
86 }
87
88 let crates = std_crates_for_make_run(&run);
92 run.builder.ensure(Std {
93 build_compiler: prepare_compiler_for_check(run.builder, run.target, Mode::Std)
94 .build_compiler(),
95 target: run.target,
96 crates,
97 });
98 }
99
100 fn run(self, builder: &Builder<'_>) -> Self::Output {
101 let build_compiler = self.build_compiler;
102 let target = self.target;
103
104 let mut cargo = builder::Cargo::new(
105 builder,
106 build_compiler,
107 Mode::Std,
108 SourceType::InTree,
109 target,
110 builder.kind,
111 );
112
113 std_cargo(builder, target, &mut cargo, &self.crates);
114 if matches!(builder.kind, Kind::Fix) {
115 cargo.arg("--lib");
117 }
118
119 let _guard = builder.msg(
120 builder.kind,
121 format_args!("library artifacts{}", crate_description(&self.crates)),
122 Mode::Std,
123 build_compiler,
124 target,
125 );
126
127 let check_stamp =
128 build_stamp::libstd_stamp(builder, build_compiler, target).with_prefix("check");
129 run_cargo(
130 builder,
131 cargo,
132 builder.config.free_args.clone(),
133 &check_stamp,
134 vec![],
135 ArtifactKeepMode::OnlyRmeta,
136 );
137
138 drop(_guard);
139
140 if !self.crates.iter().any(|krate| krate == "test") {
142 return check_stamp;
143 }
144
145 let mut cargo = builder::Cargo::new(
152 builder,
153 build_compiler,
154 Mode::Std,
155 SourceType::InTree,
156 target,
157 Kind::Check,
158 );
159
160 std_cargo(builder, target, &mut cargo, &self.crates);
161
162 let stamp =
163 build_stamp::libstd_stamp(builder, build_compiler, target).with_prefix("check-test");
164 let _guard = builder.msg(
165 Kind::Check,
166 "library test/bench/example targets",
167 Mode::Std,
168 build_compiler,
169 target,
170 );
171 run_cargo(
172 builder,
173 cargo,
174 builder.config.free_args.clone(),
175 &stamp,
176 vec![],
177 ArtifactKeepMode::OnlyRmeta,
178 );
179 check_stamp
180 }
181
182 fn metadata(&self) -> Option<StepMetadata> {
183 Some(StepMetadata::check("std", self.target).built_by(self.build_compiler))
184 }
185}
186
187#[derive(Debug, Clone, PartialEq, Eq, Hash)]
191struct RmetaSysroot {
192 host_dir: PathBuf,
193 target_dir: PathBuf,
194}
195
196impl RmetaSysroot {
197 fn from_stamp(
199 builder: &Builder<'_>,
200 stamp: BuildStamp,
201 target: TargetSelection,
202 directory: &Path,
203 ) -> Self {
204 let host_dir = directory.join("host");
205 let target_dir = directory.join(target);
206 let _ = fs::remove_dir_all(directory);
207 t!(fs::create_dir_all(directory));
208 add_to_sysroot(builder, &target_dir, &host_dir, &stamp);
209
210 Self { host_dir, target_dir }
211 }
212
213 fn configure_cargo(&self, cargo: &mut Cargo) {
216 cargo.append_to_env(
217 "RUSTC_ADDITIONAL_SYSROOT_PATHS",
218 format!("{},{}", self.host_dir.to_str().unwrap(), self.target_dir.to_str().unwrap()),
219 ",",
220 );
221 }
222}
223
224#[derive(Debug, Clone, PartialEq, Eq, Hash)]
231struct PrepareRustcRmetaSysroot {
232 build_compiler: CompilerForCheck,
233 target: TargetSelection,
234}
235
236impl PrepareRustcRmetaSysroot {
237 fn new(build_compiler: CompilerForCheck, target: TargetSelection) -> Self {
238 Self { build_compiler, target }
239 }
240}
241
242impl Step for PrepareRustcRmetaSysroot {
243 type Output = RmetaSysroot;
244
245 fn run(self, builder: &Builder<'_>) -> Self::Output {
246 let stamp = Rustc::check_rustc_for_preparing_sysroot(builder, &self);
248
249 let build_compiler = self.build_compiler.build_compiler();
250
251 let dir = builder
253 .config
254 .out
255 .join(build_compiler.host)
256 .join(format!("stage{}-rustc-rmeta-artifacts", build_compiler.stage + 1));
257 RmetaSysroot::from_stamp(builder, stamp, self.target, &dir)
258 }
259}
260
261#[derive(Debug, Clone, PartialEq, Eq, Hash)]
268struct PrepareStdRmetaSysroot {
269 build_compiler: Compiler,
270 target: TargetSelection,
271}
272
273impl PrepareStdRmetaSysroot {
274 fn new(build_compiler: Compiler, target: TargetSelection) -> Self {
275 Self { build_compiler, target }
276 }
277}
278
279impl Step for PrepareStdRmetaSysroot {
280 type Output = RmetaSysroot;
281
282 fn run(self, builder: &Builder<'_>) -> Self::Output {
283 let stamp = builder.ensure(Std {
285 build_compiler: self.build_compiler,
286 target: self.target,
287 crates: vec![],
288 });
289
290 let dir = builder
292 .config
293 .out
294 .join(self.build_compiler.host)
295 .join(format!("stage{}-std-rmeta-artifacts", self.build_compiler.stage));
296
297 RmetaSysroot::from_stamp(builder, stamp, self.target, &dir)
298 }
299}
300
301#[derive(Debug, Clone, PartialEq, Eq, Hash)]
303pub struct Rustc {
304 check_kind: CheckKind,
305
306 build_compiler: CompilerForCheck,
308 target: TargetSelection,
309
310 crates: Vec<String>,
316}
317
318impl Rustc {
319 fn check_rustc_for_preparing_sysroot(
320 builder: &Builder<'_>,
321 prepare: &PrepareRustcRmetaSysroot,
322 ) -> BuildStamp {
323 builder.ensure(Rustc {
324 check_kind: CheckKind::Check,
326 build_compiler: prepare.build_compiler.clone(),
327 target: prepare.target,
328 crates: vec![],
329 })
330 }
331}
332
333impl CommandLineStep for Rustc {
334 type Output = BuildStamp;
335 const IS_HOST: bool = true;
336
337 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
338 run.crate_or_deps("rustc-main").path("compiler")
339 }
340
341 fn is_default_step(_builder: &Builder<'_>) -> bool {
342 true
343 }
344
345 fn make_run(run: RunConfig<'_>) {
346 let check_kind = match run.builder.kind {
347 Kind::Check => CheckKind::Check,
348 Kind::Fix => CheckKind::Fix,
349 kind => panic!("unexpected kind for `check::Rustc`: {kind:?}"),
350 };
351
352 let target = run.target;
353 let build_compiler = prepare_compiler_for_check(run.builder, target, Mode::Rustc);
354 let crates = run.make_run_crates(Alias::Compiler);
355
356 run.builder.ensure(Rustc { check_kind, build_compiler, target, crates });
357 }
358
359 fn run(self, builder: &Builder<'_>) -> Self::Output {
367 let build_compiler = self.build_compiler.build_compiler;
368 let target = self.target;
369
370 let mut cargo = builder::Cargo::new(
371 builder,
372 build_compiler,
373 Mode::Rustc,
374 SourceType::InTree,
375 target,
376 self.check_kind.to_kind(),
377 );
378
379 rustc_cargo(builder, &mut cargo, target, &build_compiler, &self.crates);
380 self.build_compiler.configure_cargo(&mut cargo);
381
382 for krate in &*self.crates {
386 cargo.arg("-p").arg(krate);
387 }
388 if !self.crates.is_empty() && builder.sess.config.cmd.check_all_targets() {
396 cargo.arg("--all-targets");
397 }
398
399 let _guard = builder.msg(
400 self.check_kind.to_kind(),
401 format_args!("compiler artifacts{}", crate_description(&self.crates)),
402 Mode::Rustc,
403 self.build_compiler.build_compiler(),
404 target,
405 );
406
407 let stamp =
408 build_stamp::librustc_stamp(builder, build_compiler, target).with_prefix("check");
409
410 run_cargo(
411 builder,
412 cargo,
413 builder.config.free_args.clone(),
414 &stamp,
415 vec![],
416 ArtifactKeepMode::OnlyRmeta,
417 );
418
419 stamp
420 }
421
422 fn metadata(&self) -> Option<StepMetadata> {
423 let mut metadata = StepMetadata::new("rustc", self.target, self.check_kind.to_kind())
424 .built_by(self.build_compiler.build_compiler());
425 if !self.crates.is_empty() {
426 metadata = metadata.with_metadata(format!("({} crates)", self.crates.len()));
427 }
428 Some(metadata)
429 }
430}
431
432#[derive(Debug, Clone, PartialEq, Eq, Hash)]
441pub struct CompilerForCheck {
442 build_compiler: Compiler,
443 rustc_rmeta_sysroot: Option<RmetaSysroot>,
444 std_rmeta_sysroot: Option<RmetaSysroot>,
445}
446
447impl CompilerForCheck {
448 pub fn build_compiler(&self) -> Compiler {
449 self.build_compiler
450 }
451
452 pub fn configure_cargo(&self, cargo: &mut Cargo) {
455 if let Some(sysroot) = &self.rustc_rmeta_sysroot {
456 sysroot.configure_cargo(cargo);
457 }
458 if let Some(sysroot) = &self.std_rmeta_sysroot {
459 sysroot.configure_cargo(cargo);
460 }
461 }
462}
463
464fn prepare_std(
467 builder: &Builder<'_>,
468 build_compiler: Compiler,
469 target: TargetSelection,
470) -> Option<RmetaSysroot> {
471 builder.std(build_compiler, builder.host_target);
474
475 if builder.host_target != target {
479 Some(builder.ensure(PrepareStdRmetaSysroot::new(build_compiler, target)))
480 } else {
481 None
482 }
483}
484
485pub fn prepare_compiler_for_check(
487 builder: &Builder<'_>,
488 target: TargetSelection,
489 mode: Mode,
490) -> CompilerForCheck {
491 let host = builder.host_target;
492
493 let mut rustc_rmeta_sysroot = None;
494 let mut std_rmeta_sysroot = None;
495 let build_compiler = match mode {
496 Mode::ToolBootstrap => builder.compiler(0, host),
497 Mode::ToolTarget => get_tool_target_compiler(builder, ToolTargetBuildMode::Build(target)),
501 Mode::ToolStd => {
502 if builder.config.compile_time_deps {
503 builder.compiler(0, host)
507 } else {
508 let build_compiler = builder.compiler(builder.top_stage, host);
510 std_rmeta_sysroot = prepare_std(builder, build_compiler, target);
511 build_compiler
512 }
513 }
514 Mode::ToolRustcPrivate | Mode::Codegen => {
515 let compiler_for_rustc = prepare_compiler_for_check(builder, target, Mode::Rustc);
520 rustc_rmeta_sysroot = Some(
521 builder.ensure(PrepareRustcRmetaSysroot::new(compiler_for_rustc.clone(), target)),
522 );
523 let build_compiler = compiler_for_rustc.build_compiler();
524
525 std_rmeta_sysroot = prepare_std(builder, build_compiler, target);
527 build_compiler
528 }
529 Mode::Rustc => {
530 let stage = if host == target { builder.top_stage - 1 } else { builder.top_stage };
538 let build_compiler = builder.compiler(stage, host);
539
540 std_rmeta_sysroot = prepare_std(builder, build_compiler, target);
542 build_compiler
543 }
544 Mode::Std => {
545 builder.compiler(builder.top_stage, host)
549 }
550 };
551 CompilerForCheck { build_compiler, rustc_rmeta_sysroot, std_rmeta_sysroot }
552}
553
554#[derive(Debug, Clone, PartialEq, Eq, Hash)]
556pub struct CraneliftCodegenBackend {
557 build_compiler: CompilerForCheck,
558 target: TargetSelection,
559}
560
561impl CommandLineStep for CraneliftCodegenBackend {
562 type Output = ();
563 const IS_HOST: bool = true;
564
565 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
566 run.alias("rustc_codegen_cranelift").alias("cg_clif")
567 }
568
569 fn is_default_step(_builder: &Builder<'_>) -> bool {
570 true
571 }
572
573 fn make_run(run: RunConfig<'_>) {
574 run.builder.ensure(CraneliftCodegenBackend {
575 build_compiler: prepare_compiler_for_check(run.builder, run.target, Mode::Codegen),
576 target: run.target,
577 });
578 }
579
580 fn run(self, builder: &Builder<'_>) {
581 let build_compiler = self.build_compiler.build_compiler();
582 let target = self.target;
583
584 let mut cargo = builder::Cargo::new(
585 builder,
586 build_compiler,
587 Mode::Codegen,
588 SourceType::InTree,
589 target,
590 builder.kind,
591 );
592
593 cargo
594 .arg("--manifest-path")
595 .arg(builder.src.join("compiler/rustc_codegen_cranelift/Cargo.toml"));
596 self.build_compiler.configure_cargo(&mut cargo);
597
598 let _guard = builder.msg(
599 Kind::Check,
600 "rustc_codegen_cranelift",
601 Mode::Codegen,
602 build_compiler,
603 target,
604 );
605
606 let stamp = build_stamp::codegen_backend_stamp(
607 builder,
608 build_compiler,
609 target,
610 &CodegenBackendKind::Cranelift,
611 )
612 .with_prefix("check");
613
614 run_cargo(
615 builder,
616 cargo,
617 builder.config.free_args.clone(),
618 &stamp,
619 vec![],
620 ArtifactKeepMode::OnlyRmeta,
621 );
622 }
623
624 fn metadata(&self) -> Option<StepMetadata> {
625 Some(
626 StepMetadata::check("rustc_codegen_cranelift", self.target)
627 .built_by(self.build_compiler.build_compiler()),
628 )
629 }
630}
631
632#[derive(Debug, Clone, PartialEq, Eq, Hash)]
634pub struct GccCodegenBackend {
635 build_compiler: CompilerForCheck,
636 target: TargetSelection,
637}
638
639impl CommandLineStep for GccCodegenBackend {
640 type Output = ();
641 const IS_HOST: bool = true;
642
643 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
644 run.alias("rustc_codegen_gcc").alias("cg_gcc")
645 }
646
647 fn is_default_step(_builder: &Builder<'_>) -> bool {
648 true
649 }
650
651 fn make_run(run: RunConfig<'_>) {
652 run.builder.ensure(GccCodegenBackend {
653 build_compiler: prepare_compiler_for_check(run.builder, run.target, Mode::Codegen),
654 target: run.target,
655 });
656 }
657
658 fn run(self, builder: &Builder<'_>) {
659 if builder.sess.config.vendor {
661 println!("Skipping checking of `rustc_codegen_gcc` with vendoring enabled.");
662 return;
663 }
664
665 let build_compiler = self.build_compiler.build_compiler();
666 let target = self.target;
667
668 let mut cargo = builder::Cargo::new(
669 builder,
670 build_compiler,
671 Mode::Codegen,
672 SourceType::InTree,
673 target,
674 builder.kind,
675 );
676
677 cargo.arg("--manifest-path").arg(builder.src.join("compiler/rustc_codegen_gcc/Cargo.toml"));
678 self.build_compiler.configure_cargo(&mut cargo);
679
680 let _guard =
681 builder.msg(Kind::Check, "rustc_codegen_gcc", Mode::Codegen, build_compiler, target);
682
683 let stamp = build_stamp::codegen_backend_stamp(
684 builder,
685 build_compiler,
686 target,
687 &CodegenBackendKind::Gcc,
688 )
689 .with_prefix("check");
690
691 run_cargo(
692 builder,
693 cargo,
694 builder.config.free_args.clone(),
695 &stamp,
696 vec![],
697 ArtifactKeepMode::OnlyRmeta,
698 );
699 }
700
701 fn metadata(&self) -> Option<StepMetadata> {
702 Some(
703 StepMetadata::check("rustc_codegen_gcc", self.target)
704 .built_by(self.build_compiler.build_compiler()),
705 )
706 }
707}
708
709macro_rules! tool_check_step {
710 (
711 $name:ident {
712 path: $path:literal
714 $(, alt_path: $alt_path:literal )*
715 , mode: $mode:expr
717 $(, allow_features: $allow_features:expr )?
719 $(, enable_features: [$($enable_features:expr),*] )?
721 $(, default_features: $default_features:expr )?
722 $(, default: $default:literal )?
723 $( , )?
724 }
725 ) => {
726 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
727 pub struct $name {
728 compiler: CompilerForCheck,
729 target: TargetSelection,
730 }
731
732 impl CommandLineStep for $name {
733 type Output = ();
734 const IS_HOST: bool = true;
735
736 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
737 run.multi_path(&[$path $(, $alt_path )*])
738 }
739
740 fn is_default_step(_builder: &Builder<'_>) -> bool {
741 true $( && const { $default } )?
743 }
744
745 fn make_run(run: RunConfig<'_>) {
746 let target = run.target;
747 let mode: Mode = $mode;
748
749 let compiler = prepare_compiler_for_check(run.builder, target, mode);
750
751 if mode == Mode::ToolBootstrap && target != run.builder.host_target {
753 println!("WARNING: not checking bootstrap tool {} for target {target} as it is a bootstrap (host-only) tool", stringify!($path));
754 return;
755 };
756
757 run.builder.ensure($name { target, compiler });
758 }
759
760 fn run(self, builder: &Builder<'_>) {
761 let Self { target, compiler } = self;
762 let allow_features = {
763 let mut _value = "";
764 $( _value = $allow_features; )?
765 _value
766 };
767 let extra_features: &[&str] = &[$($($enable_features),*)?];
768 let default_features = {
769 let mut _value = true;
770 $( _value = $default_features; )?
771 _value
772 };
773 let mode: Mode = $mode;
774 run_tool_check_step(builder, compiler, target, $path, mode, allow_features, extra_features, default_features);
775 }
776
777 fn metadata(&self) -> Option<StepMetadata> {
778 Some(StepMetadata::check(stringify!($name), self.target).built_by(self.compiler.build_compiler))
779 }
780 }
781 }
782}
783
784#[allow(clippy::too_many_arguments)]
786fn run_tool_check_step(
787 builder: &Builder<'_>,
788 compiler: CompilerForCheck,
789 target: TargetSelection,
790 path: &str,
791 mode: Mode,
792 allow_features: &str,
793 extra_features: &[&str],
794 default_features: bool,
795) {
796 let display_name = path.rsplit('/').next().unwrap();
797
798 let build_compiler = compiler.build_compiler();
799
800 let extra_features = extra_features.iter().map(|f| f.to_string()).collect::<Vec<String>>();
801 let mut cargo = prepare_tool_cargo(
802 builder,
803 build_compiler,
804 mode,
805 target,
806 builder.kind,
807 path,
808 SourceType::InTree,
813 &extra_features,
814 );
815 cargo.allow_features(allow_features);
816 compiler.configure_cargo(&mut cargo);
817
818 if display_name == "rust-analyzer" {
821 cargo.arg("--bins");
822 cargo.arg("--tests");
823 cargo.arg("--benches");
824 } else {
825 cargo.arg("--all-targets");
826 }
827
828 if !default_features {
829 cargo.arg("--no-default-features");
830 }
831
832 let stamp = BuildStamp::new(&builder.cargo_out(build_compiler, mode, target))
833 .with_prefix(&format!("{display_name}-check"));
834
835 let _guard = builder.msg(builder.kind, display_name, mode, build_compiler, target);
836 run_cargo(
837 builder,
838 cargo,
839 builder.config.free_args.clone(),
840 &stamp,
841 vec![],
842 ArtifactKeepMode::OnlyRmeta,
843 );
844}
845
846tool_check_step!(Rustdoc {
847 path: "src/tools/rustdoc",
848 alt_path: "src/librustdoc",
849 mode: Mode::ToolRustcPrivate
850});
851tool_check_step!(Clippy { path: "src/tools/clippy", mode: Mode::ToolRustcPrivate });
856tool_check_step!(Miri {
857 path: "src/tools/miri",
858 mode: Mode::ToolRustcPrivate,
859 enable_features: ["check_only"],
860});
861tool_check_step!(CargoMiri { path: "src/tools/miri/cargo-miri", mode: Mode::ToolRustcPrivate });
862tool_check_step!(Priroda { path: "src/tools/miri/priroda", mode: Mode::ToolRustcPrivate });
863tool_check_step!(Rustfmt { path: "src/tools/rustfmt", mode: Mode::ToolRustcPrivate });
864tool_check_step!(RustAnalyzer {
865 path: "src/tools/rust-analyzer",
866 mode: Mode::ToolRustcPrivate,
867 allow_features: tool::RustAnalyzer::ALLOW_FEATURES,
868 enable_features: ["in-rust-tree"],
869});
870tool_check_step!(MiroptTestTools {
871 path: "src/tools/miropt-test-tools",
872 mode: Mode::ToolBootstrap
873});
874tool_check_step!(TestFloatParse {
876 path: "src/tools/test-float-parse",
877 mode: Mode::ToolStd,
878 allow_features: TEST_FLOAT_PARSE_ALLOW_FEATURES
879});
880tool_check_step!(FeaturesStatusDump {
881 path: "src/tools/features-status-dump",
882 mode: Mode::ToolBootstrap
883});
884
885tool_check_step!(Bootstrap { path: "src/bootstrap", mode: Mode::ToolBootstrap, default: false });
886
887tool_check_step!(RunMakeSupport {
890 path: "src/tools/run-make-support",
891 mode: Mode::ToolBootstrap,
892 default: false
893});
894
895tool_check_step!(CoverageDump {
896 path: "src/tools/coverage-dump",
897 mode: Mode::ToolBootstrap,
898 default: false
899});
900
901tool_check_step!(Compiletest {
904 path: "src/tools/compiletest",
905 mode: Mode::ToolBootstrap,
906 default: false,
907});
908
909tool_check_step!(RustdocGuiTest {
913 path: "src/tools/rustdoc-gui-test",
914 mode: Mode::ToolBootstrap,
915 default: false,
916});
917
918tool_check_step!(Linkchecker {
919 path: "src/tools/linkchecker",
920 mode: Mode::ToolBootstrap,
921 default: false
922});
923
924tool_check_step!(BumpStage0 {
925 path: "src/tools/bump-stage0",
926 mode: Mode::ToolBootstrap,
927 default: false
928});
929
930tool_check_step!(Tidy { path: "src/tools/tidy", mode: Mode::ToolBootstrap, default: false });