1use std::fs;
4use std::path::{Path, PathBuf};
5
6use crate::Mode;
7use crate::core::backend::CodegenBackendKind;
8use crate::core::build_steps::compile::{
9 ArtifactKeepMode, add_to_sysroot, run_cargo, rustc_cargo, rustc_cargo_env, std_cargo,
10 std_crates_for_make_run,
11};
12use crate::core::build_steps::tool;
13use crate::core::build_steps::tool::{
14 SourceType, TEST_FLOAT_PARSE_ALLOW_FEATURES, ToolTargetBuildMode, get_tool_target_compiler,
15 prepare_tool_cargo,
16};
17use crate::core::builder::{
18 self, Alias, Builder, Cargo, CommandLineStep, Kind, RunConfig, ShouldRun, Step, StepMetadata,
19 crate_description,
20};
21use crate::core::compiler::Compiler;
22use crate::core::config::TargetSelection;
23use crate::core::config::flags::Subcommand;
24use crate::utils::build_stamp::{self, BuildStamp};
25use crate::utils::helpers::t;
26
27#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
30enum CheckKind {
31 Check,
32 Fix,
33}
34
35impl CheckKind {
36 fn to_kind(self) -> Kind {
37 match self {
38 CheckKind::Check => Kind::Check,
39 CheckKind::Fix => Kind::Fix,
40 }
41 }
42}
43
44#[derive(Debug, Clone, PartialEq, Eq, Hash)]
45pub struct Std {
46 pub build_compiler: Compiler,
48 pub target: TargetSelection,
49 crates: Vec<String>,
55}
56
57impl Std {
58 const CRATE_OR_DEPS: &[&str] = &["sysroot", "coretests", "alloctests"];
59}
60
61impl CommandLineStep for Std {
62 type Output = BuildStamp;
63
64 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
65 let mut run = run;
66 for c in Std::CRATE_OR_DEPS {
67 run = run.crate_or_deps(c);
68 }
69
70 run.path("library")
71 }
72
73 fn is_default_step(_builder: &Builder<'_>) -> bool {
74 true
75 }
76
77 fn make_run(run: RunConfig<'_>) {
78 if !run.builder.download_rustc() && run.builder.config.skip_std_check_if_no_download_rustc {
79 eprintln!(
80 "WARNING: `--skip-std-check-if-no-download-rustc` flag was passed and `rust.download-rustc` is not available. Skipping."
81 );
82 return;
83 }
84
85 if run.builder.config.compile_time_deps {
86 return;
88 }
89
90 let crates = std_crates_for_make_run(&run);
94 run.builder.ensure(Std {
95 build_compiler: prepare_compiler_for_check(run.builder, run.target, Mode::Std)
96 .build_compiler(),
97 target: run.target,
98 crates,
99 });
100 }
101
102 fn run(self, builder: &Builder<'_>) -> Self::Output {
103 let build_compiler = self.build_compiler;
104 let target = self.target;
105
106 let mut cargo = builder::Cargo::new(
107 builder,
108 build_compiler,
109 Mode::Std,
110 SourceType::InTree,
111 target,
112 builder.kind,
113 );
114
115 std_cargo(builder, target, &mut cargo, &self.crates);
116 if matches!(builder.config.cmd, Subcommand::Fix) {
117 cargo.arg("--lib");
119 }
120
121 let _guard = builder.msg(
122 builder.kind,
123 format_args!("library artifacts{}", crate_description(&self.crates)),
124 Mode::Std,
125 build_compiler,
126 target,
127 );
128
129 let check_stamp =
130 build_stamp::libstd_stamp(builder, build_compiler, target).with_prefix("check");
131 run_cargo(
132 builder,
133 cargo,
134 builder.config.free_args.clone(),
135 &check_stamp,
136 vec![],
137 ArtifactKeepMode::OnlyRmeta,
138 );
139
140 drop(_guard);
141
142 if !self.crates.iter().any(|krate| krate == "test") {
144 return check_stamp;
145 }
146
147 let mut cargo = builder::Cargo::new(
154 builder,
155 build_compiler,
156 Mode::Std,
157 SourceType::InTree,
158 target,
159 Kind::Check,
160 );
161
162 std_cargo(builder, target, &mut cargo, &self.crates);
163
164 let stamp =
165 build_stamp::libstd_stamp(builder, build_compiler, target).with_prefix("check-test");
166 let _guard = builder.msg(
167 Kind::Check,
168 "library test/bench/example targets",
169 Mode::Std,
170 build_compiler,
171 target,
172 );
173 run_cargo(
174 builder,
175 cargo,
176 builder.config.free_args.clone(),
177 &stamp,
178 vec![],
179 ArtifactKeepMode::OnlyRmeta,
180 );
181 check_stamp
182 }
183
184 fn metadata(&self) -> Option<StepMetadata> {
185 Some(StepMetadata::check("std", self.target).built_by(self.build_compiler))
186 }
187}
188
189#[derive(Debug, Clone, PartialEq, Eq, Hash)]
193struct RmetaSysroot {
194 host_dir: PathBuf,
195 target_dir: PathBuf,
196}
197
198impl RmetaSysroot {
199 fn from_stamp(
201 builder: &Builder<'_>,
202 stamp: BuildStamp,
203 target: TargetSelection,
204 directory: &Path,
205 ) -> Self {
206 let host_dir = directory.join("host");
207 let target_dir = directory.join(target);
208 let _ = fs::remove_dir_all(directory);
209 t!(fs::create_dir_all(directory));
210 add_to_sysroot(builder, &target_dir, &host_dir, &stamp);
211
212 Self { host_dir, target_dir }
213 }
214
215 fn configure_cargo(&self, cargo: &mut Cargo) {
218 cargo.append_to_env(
219 "RUSTC_ADDITIONAL_SYSROOT_PATHS",
220 format!("{},{}", self.host_dir.to_str().unwrap(), self.target_dir.to_str().unwrap()),
221 ",",
222 );
223 }
224}
225
226#[derive(Debug, Clone, PartialEq, Eq, Hash)]
233struct PrepareRustcRmetaSysroot {
234 build_compiler: CompilerForCheck,
235 target: TargetSelection,
236}
237
238impl PrepareRustcRmetaSysroot {
239 fn new(build_compiler: CompilerForCheck, target: TargetSelection) -> Self {
240 Self { build_compiler, target }
241 }
242}
243
244impl Step for PrepareRustcRmetaSysroot {
245 type Output = RmetaSysroot;
246
247 fn run(self, builder: &Builder<'_>) -> Self::Output {
248 let stamp = Rustc::check_rustc_for_preparing_sysroot(builder, &self);
250
251 let build_compiler = self.build_compiler.build_compiler();
252
253 let dir = builder
255 .out
256 .join(build_compiler.host)
257 .join(format!("stage{}-rustc-rmeta-artifacts", build_compiler.stage + 1));
258 RmetaSysroot::from_stamp(builder, stamp, self.target, &dir)
259 }
260}
261
262#[derive(Debug, Clone, PartialEq, Eq, Hash)]
269struct PrepareStdRmetaSysroot {
270 build_compiler: Compiler,
271 target: TargetSelection,
272}
273
274impl PrepareStdRmetaSysroot {
275 fn new(build_compiler: Compiler, target: TargetSelection) -> Self {
276 Self { build_compiler, target }
277 }
278}
279
280impl Step for PrepareStdRmetaSysroot {
281 type Output = RmetaSysroot;
282
283 fn run(self, builder: &Builder<'_>) -> Self::Output {
284 let stamp = builder.ensure(Std {
286 build_compiler: self.build_compiler,
287 target: self.target,
288 crates: vec![],
289 });
290
291 let dir = builder
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
389 let _guard = builder.msg(
390 self.check_kind.to_kind(),
391 format_args!("compiler artifacts{}", crate_description(&self.crates)),
392 Mode::Rustc,
393 self.build_compiler.build_compiler(),
394 target,
395 );
396
397 let stamp =
398 build_stamp::librustc_stamp(builder, build_compiler, target).with_prefix("check");
399
400 run_cargo(
401 builder,
402 cargo,
403 builder.config.free_args.clone(),
404 &stamp,
405 vec![],
406 ArtifactKeepMode::OnlyRmeta,
407 );
408
409 stamp
410 }
411
412 fn metadata(&self) -> Option<StepMetadata> {
413 let mut metadata = StepMetadata::new("rustc", self.target, self.check_kind.to_kind())
414 .built_by(self.build_compiler.build_compiler());
415 if !self.crates.is_empty() {
416 metadata = metadata.with_metadata(format!("({} crates)", self.crates.len()));
417 }
418 Some(metadata)
419 }
420}
421
422#[derive(Debug, Clone, PartialEq, Eq, Hash)]
431pub struct CompilerForCheck {
432 build_compiler: Compiler,
433 rustc_rmeta_sysroot: Option<RmetaSysroot>,
434 std_rmeta_sysroot: Option<RmetaSysroot>,
435}
436
437impl CompilerForCheck {
438 pub fn build_compiler(&self) -> Compiler {
439 self.build_compiler
440 }
441
442 pub fn configure_cargo(&self, cargo: &mut Cargo) {
445 if let Some(sysroot) = &self.rustc_rmeta_sysroot {
446 sysroot.configure_cargo(cargo);
447 }
448 if let Some(sysroot) = &self.std_rmeta_sysroot {
449 sysroot.configure_cargo(cargo);
450 }
451 }
452}
453
454fn prepare_std(
457 builder: &Builder<'_>,
458 build_compiler: Compiler,
459 target: TargetSelection,
460) -> Option<RmetaSysroot> {
461 builder.std(build_compiler, builder.host_target);
464
465 if builder.host_target != target {
469 Some(builder.ensure(PrepareStdRmetaSysroot::new(build_compiler, target)))
470 } else {
471 None
472 }
473}
474
475pub fn prepare_compiler_for_check(
477 builder: &Builder<'_>,
478 target: TargetSelection,
479 mode: Mode,
480) -> CompilerForCheck {
481 let host = builder.host_target;
482
483 let mut rustc_rmeta_sysroot = None;
484 let mut std_rmeta_sysroot = None;
485 let build_compiler = match mode {
486 Mode::ToolBootstrap => builder.compiler(0, host),
487 Mode::ToolTarget => get_tool_target_compiler(builder, ToolTargetBuildMode::Build(target)),
491 Mode::ToolStd => {
492 if builder.config.compile_time_deps {
493 builder.compiler(0, host)
497 } else {
498 let build_compiler = builder.compiler(builder.top_stage, host);
500 std_rmeta_sysroot = prepare_std(builder, build_compiler, target);
501 build_compiler
502 }
503 }
504 Mode::ToolRustcPrivate | Mode::Codegen => {
505 let compiler_for_rustc = prepare_compiler_for_check(builder, target, Mode::Rustc);
510 rustc_rmeta_sysroot = Some(
511 builder.ensure(PrepareRustcRmetaSysroot::new(compiler_for_rustc.clone(), target)),
512 );
513 let build_compiler = compiler_for_rustc.build_compiler();
514
515 std_rmeta_sysroot = prepare_std(builder, build_compiler, target);
517 build_compiler
518 }
519 Mode::Rustc => {
520 let stage = if host == target { builder.top_stage - 1 } else { builder.top_stage };
528 let build_compiler = builder.compiler(stage, host);
529
530 std_rmeta_sysroot = prepare_std(builder, build_compiler, target);
532 build_compiler
533 }
534 Mode::Std => {
535 builder.compiler(builder.top_stage, host)
539 }
540 };
541 CompilerForCheck { build_compiler, rustc_rmeta_sysroot, std_rmeta_sysroot }
542}
543
544#[derive(Debug, Clone, PartialEq, Eq, Hash)]
546pub struct CraneliftCodegenBackend {
547 build_compiler: CompilerForCheck,
548 target: TargetSelection,
549}
550
551impl CommandLineStep for CraneliftCodegenBackend {
552 type Output = ();
553 const IS_HOST: bool = true;
554
555 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
556 run.alias("rustc_codegen_cranelift").alias("cg_clif")
557 }
558
559 fn is_default_step(_builder: &Builder<'_>) -> bool {
560 true
561 }
562
563 fn make_run(run: RunConfig<'_>) {
564 run.builder.ensure(CraneliftCodegenBackend {
565 build_compiler: prepare_compiler_for_check(run.builder, run.target, Mode::Codegen),
566 target: run.target,
567 });
568 }
569
570 fn run(self, builder: &Builder<'_>) {
571 let build_compiler = self.build_compiler.build_compiler();
572 let target = self.target;
573
574 let mut cargo = builder::Cargo::new(
575 builder,
576 build_compiler,
577 Mode::Codegen,
578 SourceType::InTree,
579 target,
580 builder.kind,
581 );
582
583 cargo
584 .arg("--manifest-path")
585 .arg(builder.src.join("compiler/rustc_codegen_cranelift/Cargo.toml"));
586 rustc_cargo_env(builder, &mut cargo, target);
587 self.build_compiler.configure_cargo(&mut cargo);
588
589 let _guard = builder.msg(
590 Kind::Check,
591 "rustc_codegen_cranelift",
592 Mode::Codegen,
593 build_compiler,
594 target,
595 );
596
597 let stamp = build_stamp::codegen_backend_stamp(
598 builder,
599 build_compiler,
600 target,
601 &CodegenBackendKind::Cranelift,
602 )
603 .with_prefix("check");
604
605 run_cargo(
606 builder,
607 cargo,
608 builder.config.free_args.clone(),
609 &stamp,
610 vec![],
611 ArtifactKeepMode::OnlyRmeta,
612 );
613 }
614
615 fn metadata(&self) -> Option<StepMetadata> {
616 Some(
617 StepMetadata::check("rustc_codegen_cranelift", self.target)
618 .built_by(self.build_compiler.build_compiler()),
619 )
620 }
621}
622
623#[derive(Debug, Clone, PartialEq, Eq, Hash)]
625pub struct GccCodegenBackend {
626 build_compiler: CompilerForCheck,
627 target: TargetSelection,
628}
629
630impl CommandLineStep for GccCodegenBackend {
631 type Output = ();
632 const IS_HOST: bool = true;
633
634 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
635 run.alias("rustc_codegen_gcc").alias("cg_gcc")
636 }
637
638 fn is_default_step(_builder: &Builder<'_>) -> bool {
639 true
640 }
641
642 fn make_run(run: RunConfig<'_>) {
643 run.builder.ensure(GccCodegenBackend {
644 build_compiler: prepare_compiler_for_check(run.builder, run.target, Mode::Codegen),
645 target: run.target,
646 });
647 }
648
649 fn run(self, builder: &Builder<'_>) {
650 if builder.build.config.vendor {
652 println!("Skipping checking of `rustc_codegen_gcc` with vendoring enabled.");
653 return;
654 }
655
656 let build_compiler = self.build_compiler.build_compiler();
657 let target = self.target;
658
659 let mut cargo = builder::Cargo::new(
660 builder,
661 build_compiler,
662 Mode::Codegen,
663 SourceType::InTree,
664 target,
665 builder.kind,
666 );
667
668 cargo.arg("--manifest-path").arg(builder.src.join("compiler/rustc_codegen_gcc/Cargo.toml"));
669 rustc_cargo_env(builder, &mut cargo, target);
670 self.build_compiler.configure_cargo(&mut cargo);
671
672 let _guard =
673 builder.msg(Kind::Check, "rustc_codegen_gcc", Mode::Codegen, build_compiler, target);
674
675 let stamp = build_stamp::codegen_backend_stamp(
676 builder,
677 build_compiler,
678 target,
679 &CodegenBackendKind::Gcc,
680 )
681 .with_prefix("check");
682
683 run_cargo(
684 builder,
685 cargo,
686 builder.config.free_args.clone(),
687 &stamp,
688 vec![],
689 ArtifactKeepMode::OnlyRmeta,
690 );
691 }
692
693 fn metadata(&self) -> Option<StepMetadata> {
694 Some(
695 StepMetadata::check("rustc_codegen_gcc", self.target)
696 .built_by(self.build_compiler.build_compiler()),
697 )
698 }
699}
700
701macro_rules! tool_check_step {
702 (
703 $name:ident {
704 path: $path:literal
706 $(, alt_path: $alt_path:literal )*
707 , mode: $mode:expr
709 $(, allow_features: $allow_features:expr )?
711 $(, enable_features: [$($enable_features:expr),*] )?
713 $(, default_features: $default_features:expr )?
714 $(, default: $default:literal )?
715 $( , )?
716 }
717 ) => {
718 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
719 pub struct $name {
720 compiler: CompilerForCheck,
721 target: TargetSelection,
722 }
723
724 impl CommandLineStep for $name {
725 type Output = ();
726 const IS_HOST: bool = true;
727
728 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
729 run.multi_path(&[$path $(, $alt_path )*])
730 }
731
732 fn is_default_step(_builder: &Builder<'_>) -> bool {
733 true $( && const { $default } )?
735 }
736
737 fn make_run(run: RunConfig<'_>) {
738 let target = run.target;
739 let mode: Mode = $mode;
740
741 let compiler = prepare_compiler_for_check(run.builder, target, mode);
742
743 if mode == Mode::ToolBootstrap && target != run.builder.host_target {
745 println!("WARNING: not checking bootstrap tool {} for target {target} as it is a bootstrap (host-only) tool", stringify!($path));
746 return;
747 };
748
749 run.builder.ensure($name { target, compiler });
750 }
751
752 fn run(self, builder: &Builder<'_>) {
753 let Self { target, compiler } = self;
754 let allow_features = {
755 let mut _value = "";
756 $( _value = $allow_features; )?
757 _value
758 };
759 let extra_features: &[&str] = &[$($($enable_features),*)?];
760 let default_features = {
761 let mut _value = true;
762 $( _value = $default_features; )?
763 _value
764 };
765 let mode: Mode = $mode;
766 run_tool_check_step(builder, compiler, target, $path, mode, allow_features, extra_features, default_features);
767 }
768
769 fn metadata(&self) -> Option<StepMetadata> {
770 Some(StepMetadata::check(stringify!($name), self.target).built_by(self.compiler.build_compiler))
771 }
772 }
773 }
774}
775
776#[allow(clippy::too_many_arguments)]
778fn run_tool_check_step(
779 builder: &Builder<'_>,
780 compiler: CompilerForCheck,
781 target: TargetSelection,
782 path: &str,
783 mode: Mode,
784 allow_features: &str,
785 extra_features: &[&str],
786 default_features: bool,
787) {
788 let display_name = path.rsplit('/').next().unwrap();
789
790 let build_compiler = compiler.build_compiler();
791
792 let extra_features = extra_features.iter().map(|f| f.to_string()).collect::<Vec<String>>();
793 let mut cargo = prepare_tool_cargo(
794 builder,
795 build_compiler,
796 mode,
797 target,
798 builder.kind,
799 path,
800 SourceType::InTree,
805 &extra_features,
806 );
807 cargo.allow_features(allow_features);
808 compiler.configure_cargo(&mut cargo);
809
810 if display_name == "rust-analyzer" {
813 cargo.arg("--bins");
814 cargo.arg("--tests");
815 cargo.arg("--benches");
816 } else {
817 cargo.arg("--all-targets");
818 }
819
820 if !default_features {
821 cargo.arg("--no-default-features");
822 }
823
824 let stamp = BuildStamp::new(&builder.cargo_out(build_compiler, mode, target))
825 .with_prefix(&format!("{display_name}-check"));
826
827 let _guard = builder.msg(builder.kind, display_name, mode, build_compiler, target);
828 run_cargo(
829 builder,
830 cargo,
831 builder.config.free_args.clone(),
832 &stamp,
833 vec![],
834 ArtifactKeepMode::OnlyRmeta,
835 );
836}
837
838tool_check_step!(Rustdoc {
839 path: "src/tools/rustdoc",
840 alt_path: "src/librustdoc",
841 mode: Mode::ToolRustcPrivate
842});
843tool_check_step!(Clippy { path: "src/tools/clippy", mode: Mode::ToolRustcPrivate });
848tool_check_step!(Miri {
849 path: "src/tools/miri",
850 mode: Mode::ToolRustcPrivate,
851 enable_features: ["check_only"],
852});
853tool_check_step!(CargoMiri { path: "src/tools/miri/cargo-miri", mode: Mode::ToolRustcPrivate });
854tool_check_step!(Priroda { path: "src/tools/miri/priroda", mode: Mode::ToolRustcPrivate });
855tool_check_step!(Rustfmt { path: "src/tools/rustfmt", mode: Mode::ToolRustcPrivate });
856tool_check_step!(RustAnalyzer {
857 path: "src/tools/rust-analyzer",
858 mode: Mode::ToolRustcPrivate,
859 allow_features: tool::RustAnalyzer::ALLOW_FEATURES,
860 enable_features: ["in-rust-tree"],
861});
862tool_check_step!(MiroptTestTools {
863 path: "src/tools/miropt-test-tools",
864 mode: Mode::ToolBootstrap
865});
866tool_check_step!(TestFloatParse {
868 path: "src/tools/test-float-parse",
869 mode: Mode::ToolStd,
870 allow_features: TEST_FLOAT_PARSE_ALLOW_FEATURES
871});
872tool_check_step!(FeaturesStatusDump {
873 path: "src/tools/features-status-dump",
874 mode: Mode::ToolBootstrap
875});
876
877tool_check_step!(Bootstrap { path: "src/bootstrap", mode: Mode::ToolBootstrap, default: false });
878
879tool_check_step!(RunMakeSupport {
882 path: "src/tools/run-make-support",
883 mode: Mode::ToolBootstrap,
884 default: false
885});
886
887tool_check_step!(CoverageDump {
888 path: "src/tools/coverage-dump",
889 mode: Mode::ToolBootstrap,
890 default: false
891});
892
893tool_check_step!(Compiletest {
896 path: "src/tools/compiletest",
897 mode: Mode::ToolBootstrap,
898 default: false,
899});
900
901tool_check_step!(RustdocGuiTest {
905 path: "src/tools/rustdoc-gui-test",
906 mode: Mode::ToolBootstrap,
907 default: false,
908});
909
910tool_check_step!(Linkchecker {
911 path: "src/tools/linkchecker",
912 mode: Mode::ToolBootstrap,
913 default: false
914});
915
916tool_check_step!(BumpStage0 {
917 path: "src/tools/bump-stage0",
918 mode: Mode::ToolBootstrap,
919 default: false
920});
921
922tool_check_step!(Tidy { path: "src/tools/tidy", mode: Mode::ToolBootstrap, default: false });