1use std::ffi::OsStr;
13use std::path::PathBuf;
14use std::{env, fs};
15
16#[cfg(feature = "tracing")]
17use tracing::instrument;
18
19use crate::core::build_steps::compile::is_lto_stage;
20use crate::core::build_steps::toolstate::ToolState;
21use crate::core::build_steps::{compile, llvm};
22use crate::core::builder;
23use crate::core::builder::{
24 Builder, Cargo as CargoCommand, RunConfig, ShouldRun, Step, StepMetadata, cargo_profile_var,
25};
26use crate::core::config::{DebuginfoLevel, RustcLto, TargetSelection};
27use crate::utils::exec::{BootstrapCommand, command};
28use crate::utils::helpers::{add_dylib_path, exe, t};
29use crate::{Compiler, FileType, Kind, Mode};
30
31#[derive(Debug, Clone, Hash, PartialEq, Eq)]
32pub enum SourceType {
33 InTree,
34 Submodule,
35}
36
37#[derive(Debug, Clone, Hash, PartialEq, Eq)]
38pub enum ToolArtifactKind {
39 Binary,
40 Library,
41}
42
43#[derive(Debug, Clone, Hash, PartialEq, Eq)]
44struct ToolBuild {
45 build_compiler: Compiler,
47 target: TargetSelection,
48 tool: &'static str,
49 path: &'static str,
50 mode: Mode,
51 source_type: SourceType,
52 extra_features: Vec<String>,
53 allow_features: &'static str,
55 cargo_args: Vec<String>,
57 artifact_kind: ToolArtifactKind,
59}
60
61#[derive(Clone)]
64pub struct ToolBuildResult {
65 pub tool_path: PathBuf,
67 pub build_compiler: Compiler,
69}
70
71impl Step for ToolBuild {
72 type Output = ToolBuildResult;
73
74 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
75 run.never()
76 }
77
78 fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
83 let target = self.target;
84 let mut tool = self.tool;
85 let path = self.path;
86
87 match self.mode {
88 Mode::ToolRustc => {
89 if !self.build_compiler.is_forced_compiler() && builder.download_rustc() {
91 builder.std(self.build_compiler, self.build_compiler.host);
92 builder.ensure(compile::Rustc::new(self.build_compiler, target));
93 }
94 }
95 Mode::ToolStd => {
96 if !self.build_compiler.is_forced_compiler() {
98 builder.std(self.build_compiler, target);
99 }
100 }
101 Mode::ToolBootstrap | Mode::ToolTarget => {} _ => panic!("unexpected Mode for tool build"),
103 }
104
105 let mut cargo = prepare_tool_cargo(
106 builder,
107 self.build_compiler,
108 self.mode,
109 target,
110 Kind::Build,
111 path,
112 self.source_type,
113 &self.extra_features,
114 );
115
116 if let Some(ref ccache) = builder.config.ccache
121 && matches!(self.mode, Mode::ToolBootstrap)
122 && !builder.config.incremental
123 {
124 cargo.env("RUSTC_WRAPPER", ccache);
125 }
126
127 if self.mode == Mode::ToolRustc && is_lto_stage(&self.build_compiler) {
130 let lto = match builder.config.rust_lto {
131 RustcLto::Off => Some("off"),
132 RustcLto::Thin => Some("thin"),
133 RustcLto::Fat => Some("fat"),
134 RustcLto::ThinLocal => None,
135 };
136 if let Some(lto) = lto {
137 cargo.env(cargo_profile_var("LTO", &builder.config), lto);
138 }
139 }
140
141 if !self.allow_features.is_empty() {
142 cargo.allow_features(self.allow_features);
143 }
144
145 cargo.args(self.cargo_args);
146
147 let _guard =
148 builder.msg(Kind::Build, self.tool, self.mode, self.build_compiler, self.target);
149
150 let build_success = compile::stream_cargo(builder, cargo, vec![], &mut |_| {});
152
153 builder.save_toolstate(
154 tool,
155 if build_success { ToolState::TestFail } else { ToolState::BuildFail },
156 );
157
158 if !build_success {
159 crate::exit!(1);
160 } else {
161 if tool == "tidy" {
165 tool = "rust-tidy";
166 }
167 let tool_path = match self.artifact_kind {
168 ToolArtifactKind::Binary => {
169 copy_link_tool_bin(builder, self.build_compiler, self.target, self.mode, tool)
170 }
171 ToolArtifactKind::Library => builder
172 .cargo_out(self.build_compiler, self.mode, self.target)
173 .join(format!("lib{tool}.rlib")),
174 };
175
176 ToolBuildResult { tool_path, build_compiler: self.build_compiler }
177 }
178 }
179}
180
181#[expect(clippy::too_many_arguments)] pub fn prepare_tool_cargo(
183 builder: &Builder<'_>,
184 compiler: Compiler,
185 mode: Mode,
186 target: TargetSelection,
187 cmd_kind: Kind,
188 path: &str,
189 source_type: SourceType,
190 extra_features: &[String],
191) -> CargoCommand {
192 let mut cargo = builder::Cargo::new(builder, compiler, mode, source_type, target, cmd_kind);
193
194 let path = PathBuf::from(path);
195 let dir = builder.src.join(&path);
196 cargo.arg("--manifest-path").arg(dir.join("Cargo.toml"));
197
198 let mut features = extra_features.to_vec();
199 if builder.build.config.cargo_native_static {
200 if path.ends_with("cargo")
201 || path.ends_with("clippy")
202 || path.ends_with("miri")
203 || path.ends_with("rustfmt")
204 {
205 cargo.env("LIBZ_SYS_STATIC", "1");
206 }
207 if path.ends_with("cargo") {
208 features.push("all-static".to_string());
209 }
210 }
211
212 builder
218 .config
219 .tool
220 .iter()
221 .filter(|(tool_name, _)| path.file_name().and_then(OsStr::to_str) == Some(tool_name))
222 .for_each(|(_, tool)| features.extend(tool.features.clone().unwrap_or_default()));
223
224 cargo.env("SYSROOT", builder.sysroot(compiler));
227
228 cargo.env("LZMA_API_STATIC", "1");
231
232 cargo.env("CFG_RELEASE", builder.rust_release());
236 cargo.env("CFG_RELEASE_CHANNEL", &builder.config.channel);
237 cargo.env("CFG_VERSION", builder.rust_version());
238 cargo.env("CFG_RELEASE_NUM", &builder.version);
239 cargo.env("DOC_RUST_LANG_ORG_CHANNEL", builder.doc_rust_lang_org_channel());
240
241 if let Some(ref ver_date) = builder.rust_info().commit_date() {
242 cargo.env("CFG_VER_DATE", ver_date);
243 }
244
245 if let Some(ref ver_hash) = builder.rust_info().sha() {
246 cargo.env("CFG_VER_HASH", ver_hash);
247 }
248
249 if let Some(description) = &builder.config.description {
250 cargo.env("CFG_VER_DESCRIPTION", description);
251 }
252
253 let info = builder.config.git_info(builder.config.omit_git_hash, &dir);
254 if let Some(sha) = info.sha() {
255 cargo.env("CFG_COMMIT_HASH", sha);
256 }
257
258 if let Some(sha_short) = info.sha_short() {
259 cargo.env("CFG_SHORT_COMMIT_HASH", sha_short);
260 }
261
262 if let Some(date) = info.commit_date() {
263 cargo.env("CFG_COMMIT_DATE", date);
264 }
265
266 if !features.is_empty() {
267 cargo.arg("--features").arg(features.join(", "));
268 }
269
270 cargo.rustflag("-Zunstable-options");
278
279 if !path.ends_with("cargo") {
296 cargo.env("FORCE_ON_BROKEN_PIPE_KILL", "-Zon-broken-pipe=kill");
301 }
302
303 cargo
304}
305
306pub enum ToolTargetBuildMode {
309 Build(TargetSelection),
312 Dist(Compiler),
316}
317
318pub(crate) fn get_tool_target_compiler(
320 builder: &Builder<'_>,
321 mode: ToolTargetBuildMode,
322) -> Compiler {
323 let (target, build_compiler_stage) = match mode {
324 ToolTargetBuildMode::Build(target) => {
325 assert!(builder.top_stage > 0);
326 (target, builder.top_stage - 1)
328 }
329 ToolTargetBuildMode::Dist(target_compiler) => {
330 assert!(target_compiler.stage > 0);
331 (target_compiler.host, target_compiler.stage - 1)
334 }
335 };
336
337 let compiler = if builder.host_target == target {
338 builder.compiler(build_compiler_stage, builder.host_target)
339 } else {
340 let build_compiler = builder.compiler(build_compiler_stage.max(1), builder.host_target);
343 builder.std(build_compiler, builder.host_target);
345 build_compiler
346 };
347 builder.std(compiler, target);
348 compiler
349}
350
351fn copy_link_tool_bin(
354 builder: &Builder<'_>,
355 build_compiler: Compiler,
356 target: TargetSelection,
357 mode: Mode,
358 name: &str,
359) -> PathBuf {
360 let cargo_out = builder.cargo_out(build_compiler, mode, target).join(exe(name, target));
361 let bin = builder.tools_dir(build_compiler).join(exe(name, target));
362 builder.copy_link(&cargo_out, &bin, FileType::Executable);
363 bin
364}
365
366macro_rules! bootstrap_tool {
367 ($(
368 $name:ident, $path:expr, $tool_name:expr
369 $(,is_external_tool = $external:expr)*
370 $(,is_unstable_tool = $unstable:expr)*
371 $(,allow_features = $allow_features:expr)?
372 $(,submodules = $submodules:expr)?
373 $(,artifact_kind = $artifact_kind:expr)?
374 ;
375 )+) => {
376 #[derive(PartialEq, Eq, Clone)]
377 pub enum Tool {
378 $(
379 $name,
380 )+
381 }
382
383 impl<'a> Builder<'a> {
384 pub fn tool_exe(&self, tool: Tool) -> PathBuf {
385 match tool {
386 $(Tool::$name =>
387 self.ensure($name {
388 compiler: self.compiler(0, self.config.host_target),
389 target: self.config.host_target,
390 }).tool_path,
391 )+
392 }
393 }
394 }
395
396 $(
397 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
398 pub struct $name {
399 pub compiler: Compiler,
400 pub target: TargetSelection,
401 }
402
403 impl Step for $name {
404 type Output = ToolBuildResult;
405
406 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
407 run.path($path)
408 }
409
410 fn make_run(run: RunConfig<'_>) {
411 run.builder.ensure($name {
412 compiler: run.builder.compiler(0, run.builder.config.host_target),
414 target: run.target,
415 });
416 }
417
418 #[cfg_attr(
419 feature = "tracing",
420 instrument(
421 level = "debug",
422 name = $tool_name,
423 skip_all,
424 ),
425 )]
426 fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
427 $(
428 for submodule in $submodules {
429 builder.require_submodule(submodule, None);
430 }
431 )*
432
433 let is_unstable = false $(|| $unstable)*;
434 let compiletest_wants_stage0 = $tool_name == "compiletest" && builder.config.compiletest_use_stage0_libtest;
435
436 builder.ensure(ToolBuild {
437 build_compiler: self.compiler,
438 target: self.target,
439 tool: $tool_name,
440 mode: if is_unstable && !compiletest_wants_stage0 {
441 Mode::ToolStd
443 } else {
444 Mode::ToolBootstrap
445 },
446 path: $path,
447 source_type: if false $(|| $external)* {
448 SourceType::Submodule
449 } else {
450 SourceType::InTree
451 },
452 extra_features: vec![],
453 allow_features: {
454 let mut _value = "";
455 $( _value = $allow_features; )?
456 _value
457 },
458 cargo_args: vec![],
459 artifact_kind: if false $(|| $artifact_kind == ToolArtifactKind::Library)* {
460 ToolArtifactKind::Library
461 } else {
462 ToolArtifactKind::Binary
463 }
464 })
465 }
466
467 fn metadata(&self) -> Option<StepMetadata> {
468 Some(
469 StepMetadata::build(stringify!($name), self.target)
470 .built_by(self.compiler)
471 )
472 }
473 }
474 )+
475 }
476}
477
478pub(crate) const COMPILETEST_ALLOW_FEATURES: &str = "internal_output_capture";
479
480bootstrap_tool!(
481 Rustbook, "src/tools/rustbook", "rustbook", is_external_tool = true, submodules = SUBMODULES_FOR_RUSTBOOK;
486 UnstableBookGen, "src/tools/unstable-book-gen", "unstable-book-gen";
487 Tidy, "src/tools/tidy", "tidy";
488 Linkchecker, "src/tools/linkchecker", "linkchecker";
489 CargoTest, "src/tools/cargotest", "cargotest";
490 Compiletest, "src/tools/compiletest", "compiletest", is_unstable_tool = true, allow_features = COMPILETEST_ALLOW_FEATURES;
491 BuildManifest, "src/tools/build-manifest", "build-manifest";
492 RemoteTestClient, "src/tools/remote-test-client", "remote-test-client";
493 RustInstaller, "src/tools/rust-installer", "rust-installer";
494 RustdocTheme, "src/tools/rustdoc-themes", "rustdoc-themes";
495 LintDocs, "src/tools/lint-docs", "lint-docs";
496 JsonDocCk, "src/tools/jsondocck", "jsondocck";
497 JsonDocLint, "src/tools/jsondoclint", "jsondoclint";
498 HtmlChecker, "src/tools/html-checker", "html-checker";
499 BumpStage0, "src/tools/bump-stage0", "bump-stage0";
500 ReplaceVersionPlaceholder, "src/tools/replace-version-placeholder", "replace-version-placeholder";
501 CollectLicenseMetadata, "src/tools/collect-license-metadata", "collect-license-metadata";
502 GenerateCopyright, "src/tools/generate-copyright", "generate-copyright";
503 GenerateWindowsSys, "src/tools/generate-windows-sys", "generate-windows-sys";
504 RustdocGUITest, "src/tools/rustdoc-gui-test", "rustdoc-gui-test", is_unstable_tool = true, allow_features = COMPILETEST_ALLOW_FEATURES;
506 CoverageDump, "src/tools/coverage-dump", "coverage-dump";
507 UnicodeTableGenerator, "src/tools/unicode-table-generator", "unicode-table-generator";
508 FeaturesStatusDump, "src/tools/features-status-dump", "features-status-dump";
509 OptimizedDist, "src/tools/opt-dist", "opt-dist", submodules = &["src/tools/rustc-perf"];
510 RunMakeSupport, "src/tools/run-make-support", "run_make_support", artifact_kind = ToolArtifactKind::Library;
511);
512
513pub static SUBMODULES_FOR_RUSTBOOK: &[&str] = &["src/doc/book", "src/doc/reference"];
516
517#[derive(Debug, Clone, Hash, PartialEq, Eq)]
520pub struct RustcPerf {
521 pub compiler: Compiler,
522 pub target: TargetSelection,
523}
524
525impl Step for RustcPerf {
526 type Output = ToolBuildResult;
528
529 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
530 run.path("src/tools/rustc-perf")
531 }
532
533 fn make_run(run: RunConfig<'_>) {
534 run.builder.ensure(RustcPerf {
535 compiler: run.builder.compiler(0, run.builder.config.host_target),
536 target: run.target,
537 });
538 }
539
540 fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
541 builder.require_submodule("src/tools/rustc-perf", None);
543
544 let tool = ToolBuild {
545 build_compiler: self.compiler,
546 target: self.target,
547 tool: "collector",
548 mode: Mode::ToolBootstrap,
549 path: "src/tools/rustc-perf",
550 source_type: SourceType::Submodule,
551 extra_features: Vec::new(),
552 allow_features: "",
553 cargo_args: vec!["-p".to_string(), "collector".to_string()],
556 artifact_kind: ToolArtifactKind::Binary,
557 };
558 let res = builder.ensure(tool.clone());
559 copy_link_tool_bin(builder, tool.build_compiler, tool.target, tool.mode, "rustc-fake");
562
563 res
564 }
565}
566
567#[derive(Debug, Clone, Hash, PartialEq, Eq)]
568pub struct ErrorIndex {
569 compilers: RustcPrivateCompilers,
570}
571
572impl ErrorIndex {
573 pub fn command(builder: &Builder<'_>, compilers: RustcPrivateCompilers) -> BootstrapCommand {
574 let mut cmd = command(builder.ensure(ErrorIndex { compilers }).tool_path);
577
578 let target_compiler = compilers.target_compiler();
579 let mut dylib_paths = builder.rustc_lib_paths(target_compiler);
580 dylib_paths.push(builder.sysroot_target_libdir(target_compiler, target_compiler.host));
581 add_dylib_path(dylib_paths, &mut cmd);
582 cmd
583 }
584}
585
586impl Step for ErrorIndex {
587 type Output = ToolBuildResult;
588
589 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
590 run.path("src/tools/error_index_generator")
591 }
592
593 fn make_run(run: RunConfig<'_>) {
594 run.builder.ensure(ErrorIndex {
600 compilers: RustcPrivateCompilers::new(
601 run.builder,
602 run.builder.top_stage,
603 run.builder.host_target,
604 ),
605 });
606 }
607
608 fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
609 builder.ensure(ToolBuild {
610 build_compiler: self.compilers.build_compiler,
611 target: self.compilers.target(),
612 tool: "error_index_generator",
613 mode: Mode::ToolRustc,
614 path: "src/tools/error_index_generator",
615 source_type: SourceType::InTree,
616 extra_features: Vec::new(),
617 allow_features: "",
618 cargo_args: Vec::new(),
619 artifact_kind: ToolArtifactKind::Binary,
620 })
621 }
622
623 fn metadata(&self) -> Option<StepMetadata> {
624 Some(
625 StepMetadata::build("error-index", self.compilers.target())
626 .built_by(self.compilers.build_compiler),
627 )
628 }
629}
630
631#[derive(Debug, Clone, Hash, PartialEq, Eq)]
632pub struct RemoteTestServer {
633 pub build_compiler: Compiler,
634 pub target: TargetSelection,
635}
636
637impl Step for RemoteTestServer {
638 type Output = ToolBuildResult;
639
640 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
641 run.path("src/tools/remote-test-server")
642 }
643
644 fn make_run(run: RunConfig<'_>) {
645 run.builder.ensure(RemoteTestServer {
646 build_compiler: get_tool_target_compiler(
647 run.builder,
648 ToolTargetBuildMode::Build(run.target),
649 ),
650 target: run.target,
651 });
652 }
653
654 fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
655 builder.ensure(ToolBuild {
656 build_compiler: self.build_compiler,
657 target: self.target,
658 tool: "remote-test-server",
659 mode: Mode::ToolTarget,
660 path: "src/tools/remote-test-server",
661 source_type: SourceType::InTree,
662 extra_features: Vec::new(),
663 allow_features: "",
664 cargo_args: Vec::new(),
665 artifact_kind: ToolArtifactKind::Binary,
666 })
667 }
668
669 fn metadata(&self) -> Option<StepMetadata> {
670 Some(StepMetadata::build("remote-test-server", self.target).built_by(self.build_compiler))
671 }
672}
673
674#[derive(Debug, Clone, Hash, PartialEq, Eq)]
679pub struct Rustdoc {
680 pub target_compiler: Compiler,
683}
684
685impl Step for Rustdoc {
686 type Output = PathBuf;
688
689 const DEFAULT: bool = true;
690 const ONLY_HOSTS: bool = true;
691
692 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
693 run.path("src/tools/rustdoc").path("src/librustdoc")
694 }
695
696 fn make_run(run: RunConfig<'_>) {
697 run.builder.ensure(Rustdoc {
698 target_compiler: run.builder.compiler(run.builder.top_stage, run.target),
699 });
700 }
701
702 fn run(self, builder: &Builder<'_>) -> Self::Output {
703 let target_compiler = self.target_compiler;
704 let target = target_compiler.host;
705
706 if target_compiler.stage == 0 {
708 if !target_compiler.is_snapshot(builder) {
709 panic!("rustdoc in stage 0 must be snapshot rustdoc");
710 }
711
712 return builder.initial_rustdoc.clone();
713 }
714
715 let bin_rustdoc = || {
717 let sysroot = builder.sysroot(target_compiler);
718 let bindir = sysroot.join("bin");
719 t!(fs::create_dir_all(&bindir));
720 let bin_rustdoc = bindir.join(exe("rustdoc", target_compiler.host));
721 let _ = fs::remove_file(&bin_rustdoc);
722 bin_rustdoc
723 };
724
725 if builder.download_rustc() && builder.rust_info().is_managed_git_subrepository() {
728 let files_to_track = &["src/librustdoc", "src/tools/rustdoc", "src/rustdoc-json-types"];
729
730 if !builder.config.has_changes_from_upstream(files_to_track) {
732 let precompiled_rustdoc = builder
733 .config
734 .ci_rustc_dir()
735 .join("bin")
736 .join(exe("rustdoc", target_compiler.host));
737
738 let bin_rustdoc = bin_rustdoc();
739 builder.copy_link(&precompiled_rustdoc, &bin_rustdoc, FileType::Executable);
740 return bin_rustdoc;
741 }
742 }
743
744 let mut extra_features = Vec::new();
752 if builder.config.jemalloc(target) {
753 extra_features.push("jemalloc".to_string());
754 }
755
756 let compilers = RustcPrivateCompilers::from_target_compiler(builder, target_compiler);
757 let tool_path = builder
758 .ensure(ToolBuild {
759 build_compiler: compilers.build_compiler,
760 target,
761 tool: "rustdoc_tool_binary",
765 mode: Mode::ToolRustc,
766 path: "src/tools/rustdoc",
767 source_type: SourceType::InTree,
768 extra_features,
769 allow_features: "",
770 cargo_args: Vec::new(),
771 artifact_kind: ToolArtifactKind::Binary,
772 })
773 .tool_path;
774
775 if builder.config.rust_debuginfo_level_tools == DebuginfoLevel::None {
776 compile::strip_debug(builder, target, &tool_path);
779 }
780 let bin_rustdoc = bin_rustdoc();
781 builder.copy_link(&tool_path, &bin_rustdoc, FileType::Executable);
782 bin_rustdoc
783 }
784
785 fn metadata(&self) -> Option<StepMetadata> {
786 Some(
787 StepMetadata::build("rustdoc", self.target_compiler.host)
788 .stage(self.target_compiler.stage),
789 )
790 }
791}
792
793#[derive(Debug, Clone, Hash, PartialEq, Eq)]
796pub struct Cargo {
797 build_compiler: Compiler,
798 target: TargetSelection,
799}
800
801impl Cargo {
802 pub fn from_build_compiler(build_compiler: Compiler, target: TargetSelection) -> Self {
805 Self { build_compiler, target }
806 }
807}
808
809impl Step for Cargo {
810 type Output = ToolBuildResult;
811 const DEFAULT: bool = true;
812 const ONLY_HOSTS: bool = true;
813
814 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
815 let builder = run.builder;
816 run.path("src/tools/cargo").default_condition(builder.tool_enabled("cargo"))
817 }
818
819 fn make_run(run: RunConfig<'_>) {
820 run.builder.ensure(Cargo {
821 build_compiler: get_tool_target_compiler(
822 run.builder,
823 ToolTargetBuildMode::Build(run.target),
824 ),
825 target: run.target,
826 });
827 }
828
829 fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
830 builder.build.require_submodule("src/tools/cargo", None);
831
832 builder.std(self.build_compiler, builder.host_target);
833 builder.std(self.build_compiler, self.target);
834
835 builder.ensure(ToolBuild {
836 build_compiler: self.build_compiler,
837 target: self.target,
838 tool: "cargo",
839 mode: Mode::ToolTarget,
840 path: "src/tools/cargo",
841 source_type: SourceType::Submodule,
842 extra_features: Vec::new(),
843 allow_features: "min_specialization,specialization",
848 cargo_args: Vec::new(),
849 artifact_kind: ToolArtifactKind::Binary,
850 })
851 }
852
853 fn metadata(&self) -> Option<StepMetadata> {
854 Some(StepMetadata::build("cargo", self.target).built_by(self.build_compiler))
855 }
856}
857
858#[derive(Clone)]
861pub struct BuiltLldWrapper {
862 tool: ToolBuildResult,
863 lld_dir: PathBuf,
864}
865
866#[derive(Debug, Clone, Hash, PartialEq, Eq)]
867pub struct LldWrapper {
868 pub build_compiler: Compiler,
869 pub target: TargetSelection,
870}
871
872impl LldWrapper {
873 pub fn for_use_by_compiler(builder: &Builder<'_>, target_compiler: Compiler) -> Self {
875 Self {
876 build_compiler: get_tool_target_compiler(
877 builder,
878 ToolTargetBuildMode::Dist(target_compiler),
879 ),
880 target: target_compiler.host,
881 }
882 }
883}
884
885impl Step for LldWrapper {
886 type Output = BuiltLldWrapper;
887
888 const ONLY_HOSTS: bool = true;
889
890 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
891 run.path("src/tools/lld-wrapper")
892 }
893
894 fn make_run(run: RunConfig<'_>) {
895 run.builder.ensure(LldWrapper {
896 build_compiler: get_tool_target_compiler(
897 run.builder,
898 ToolTargetBuildMode::Build(run.target),
899 ),
900 target: run.target,
901 });
902 }
903
904 #[cfg_attr(
905 feature = "tracing",
906 instrument(
907 level = "debug",
908 name = "LldWrapper::run",
909 skip_all,
910 fields(build_compiler = ?self.build_compiler),
911 ),
912 )]
913 fn run(self, builder: &Builder<'_>) -> Self::Output {
914 let lld_dir = builder.ensure(llvm::Lld { target: self.target });
915 let tool = builder.ensure(ToolBuild {
916 build_compiler: self.build_compiler,
917 target: self.target,
918 tool: "lld-wrapper",
919 mode: Mode::ToolTarget,
920 path: "src/tools/lld-wrapper",
921 source_type: SourceType::InTree,
922 extra_features: Vec::new(),
923 allow_features: "",
924 cargo_args: Vec::new(),
925 artifact_kind: ToolArtifactKind::Binary,
926 });
927 BuiltLldWrapper { tool, lld_dir }
928 }
929
930 fn metadata(&self) -> Option<StepMetadata> {
931 Some(StepMetadata::build("LldWrapper", self.target).built_by(self.build_compiler))
932 }
933}
934
935pub(crate) fn copy_lld_artifacts(
936 builder: &Builder<'_>,
937 lld_wrapper: BuiltLldWrapper,
938 target_compiler: Compiler,
939) {
940 let target = target_compiler.host;
941
942 let libdir_bin = builder.sysroot_target_bindir(target_compiler, target);
943 t!(fs::create_dir_all(&libdir_bin));
944
945 let src_exe = exe("lld", target);
946 let dst_exe = exe("rust-lld", target);
947
948 builder.copy_link(
949 &lld_wrapper.lld_dir.join("bin").join(src_exe),
950 &libdir_bin.join(dst_exe),
951 FileType::Executable,
952 );
953 let self_contained_lld_dir = libdir_bin.join("gcc-ld");
954 t!(fs::create_dir_all(&self_contained_lld_dir));
955
956 for name in crate::LLD_FILE_NAMES {
957 builder.copy_link(
958 &lld_wrapper.tool.tool_path,
959 &self_contained_lld_dir.join(exe(name, target)),
960 FileType::Executable,
961 );
962 }
963}
964
965#[derive(Debug, Clone, Hash, PartialEq, Eq)]
968pub struct WasmComponentLd {
969 build_compiler: Compiler,
970 target: TargetSelection,
971}
972
973impl WasmComponentLd {
974 pub fn for_use_by_compiler(builder: &Builder<'_>, target_compiler: Compiler) -> Self {
976 Self {
977 build_compiler: get_tool_target_compiler(
978 builder,
979 ToolTargetBuildMode::Dist(target_compiler),
980 ),
981 target: target_compiler.host,
982 }
983 }
984}
985
986impl Step for WasmComponentLd {
987 type Output = ToolBuildResult;
988
989 const ONLY_HOSTS: bool = true;
990
991 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
992 run.path("src/tools/wasm-component-ld")
993 }
994
995 fn make_run(run: RunConfig<'_>) {
996 run.builder.ensure(WasmComponentLd {
997 build_compiler: get_tool_target_compiler(
998 run.builder,
999 ToolTargetBuildMode::Build(run.target),
1000 ),
1001 target: run.target,
1002 });
1003 }
1004
1005 #[cfg_attr(
1006 feature = "tracing",
1007 instrument(
1008 level = "debug",
1009 name = "WasmComponentLd::run",
1010 skip_all,
1011 fields(build_compiler = ?self.build_compiler),
1012 ),
1013 )]
1014 fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
1015 builder.ensure(ToolBuild {
1016 build_compiler: self.build_compiler,
1017 target: self.target,
1018 tool: "wasm-component-ld",
1019 mode: Mode::ToolTarget,
1020 path: "src/tools/wasm-component-ld",
1021 source_type: SourceType::InTree,
1022 extra_features: vec![],
1023 allow_features: "",
1024 cargo_args: vec![],
1025 artifact_kind: ToolArtifactKind::Binary,
1026 })
1027 }
1028
1029 fn metadata(&self) -> Option<StepMetadata> {
1030 Some(StepMetadata::build("WasmComponentLd", self.target).built_by(self.build_compiler))
1031 }
1032}
1033
1034#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1035pub struct RustAnalyzer {
1036 compilers: RustcPrivateCompilers,
1037}
1038
1039impl RustAnalyzer {
1040 pub fn from_compilers(compilers: RustcPrivateCompilers) -> Self {
1041 Self { compilers }
1042 }
1043}
1044
1045impl RustAnalyzer {
1046 pub const ALLOW_FEATURES: &'static str = "rustc_private,proc_macro_internals,proc_macro_diagnostic,proc_macro_span,proc_macro_span_shrink,proc_macro_def_site";
1047}
1048
1049impl Step for RustAnalyzer {
1050 type Output = ToolBuildResult;
1051 const DEFAULT: bool = true;
1052 const ONLY_HOSTS: bool = true;
1053
1054 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1055 let builder = run.builder;
1056 run.path("src/tools/rust-analyzer").default_condition(builder.tool_enabled("rust-analyzer"))
1057 }
1058
1059 fn make_run(run: RunConfig<'_>) {
1060 run.builder.ensure(RustAnalyzer {
1061 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1062 });
1063 }
1064
1065 fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
1066 let build_compiler = self.compilers.build_compiler;
1067 let target = self.compilers.target();
1068 builder.ensure(ToolBuild {
1069 build_compiler,
1070 target,
1071 tool: "rust-analyzer",
1072 mode: Mode::ToolRustc,
1073 path: "src/tools/rust-analyzer",
1074 extra_features: vec!["in-rust-tree".to_owned()],
1075 source_type: SourceType::InTree,
1076 allow_features: RustAnalyzer::ALLOW_FEATURES,
1077 cargo_args: Vec::new(),
1078 artifact_kind: ToolArtifactKind::Binary,
1079 })
1080 }
1081
1082 fn metadata(&self) -> Option<StepMetadata> {
1083 Some(
1084 StepMetadata::build("rust-analyzer", self.compilers.target())
1085 .built_by(self.compilers.build_compiler),
1086 )
1087 }
1088}
1089
1090#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1091pub struct RustAnalyzerProcMacroSrv {
1092 compilers: RustcPrivateCompilers,
1093}
1094
1095impl RustAnalyzerProcMacroSrv {
1096 pub fn from_compilers(compilers: RustcPrivateCompilers) -> Self {
1097 Self { compilers }
1098 }
1099}
1100
1101impl Step for RustAnalyzerProcMacroSrv {
1102 type Output = ToolBuildResult;
1103
1104 const DEFAULT: bool = true;
1105 const ONLY_HOSTS: bool = true;
1106
1107 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1108 let builder = run.builder;
1109 run.path("src/tools/rust-analyzer")
1111 .path("src/tools/rust-analyzer/crates/proc-macro-srv-cli")
1112 .default_condition(
1113 builder.tool_enabled("rust-analyzer")
1114 || builder.tool_enabled("rust-analyzer-proc-macro-srv"),
1115 )
1116 }
1117
1118 fn make_run(run: RunConfig<'_>) {
1119 run.builder.ensure(RustAnalyzerProcMacroSrv {
1120 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1121 });
1122 }
1123
1124 fn run(self, builder: &Builder<'_>) -> Self::Output {
1125 let tool_result = builder.ensure(ToolBuild {
1126 build_compiler: self.compilers.build_compiler,
1127 target: self.compilers.target(),
1128 tool: "rust-analyzer-proc-macro-srv",
1129 mode: Mode::ToolRustc,
1130 path: "src/tools/rust-analyzer/crates/proc-macro-srv-cli",
1131 extra_features: vec!["in-rust-tree".to_owned()],
1132 source_type: SourceType::InTree,
1133 allow_features: RustAnalyzer::ALLOW_FEATURES,
1134 cargo_args: Vec::new(),
1135 artifact_kind: ToolArtifactKind::Binary,
1136 });
1137
1138 let libexec_path = builder.sysroot(self.compilers.target_compiler).join("libexec");
1141 t!(fs::create_dir_all(&libexec_path));
1142 builder.copy_link(
1143 &tool_result.tool_path,
1144 &libexec_path.join("rust-analyzer-proc-macro-srv"),
1145 FileType::Executable,
1146 );
1147
1148 tool_result
1149 }
1150
1151 fn metadata(&self) -> Option<StepMetadata> {
1152 Some(
1153 StepMetadata::build("rust-analyzer-proc-macro-srv", self.compilers.target())
1154 .built_by(self.compilers.build_compiler),
1155 )
1156 }
1157}
1158
1159#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1160pub struct LlvmBitcodeLinker {
1161 build_compiler: Compiler,
1162 target: TargetSelection,
1163}
1164
1165impl LlvmBitcodeLinker {
1166 pub fn from_build_compiler(build_compiler: Compiler, target: TargetSelection) -> Self {
1169 Self { build_compiler, target }
1170 }
1171
1172 pub fn from_target_compiler(builder: &Builder<'_>, target_compiler: Compiler) -> Self {
1174 Self {
1175 build_compiler: get_tool_target_compiler(
1176 builder,
1177 ToolTargetBuildMode::Dist(target_compiler),
1178 ),
1179 target: target_compiler.host,
1180 }
1181 }
1182
1183 pub fn get_build_compiler_for_target(
1185 builder: &Builder<'_>,
1186 target: TargetSelection,
1187 ) -> Compiler {
1188 get_tool_target_compiler(builder, ToolTargetBuildMode::Build(target))
1189 }
1190}
1191
1192impl Step for LlvmBitcodeLinker {
1193 type Output = ToolBuildResult;
1194 const DEFAULT: bool = true;
1195 const ONLY_HOSTS: bool = true;
1196
1197 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1198 let builder = run.builder;
1199 run.path("src/tools/llvm-bitcode-linker")
1200 .default_condition(builder.tool_enabled("llvm-bitcode-linker"))
1201 }
1202
1203 fn make_run(run: RunConfig<'_>) {
1204 run.builder.ensure(LlvmBitcodeLinker {
1205 build_compiler: Self::get_build_compiler_for_target(run.builder, run.target),
1206 target: run.target,
1207 });
1208 }
1209
1210 #[cfg_attr(
1211 feature = "tracing",
1212 instrument(level = "debug", name = "LlvmBitcodeLinker::run", skip_all)
1213 )]
1214 fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
1215 builder.ensure(ToolBuild {
1216 build_compiler: self.build_compiler,
1217 target: self.target,
1218 tool: "llvm-bitcode-linker",
1219 mode: Mode::ToolTarget,
1220 path: "src/tools/llvm-bitcode-linker",
1221 source_type: SourceType::InTree,
1222 extra_features: vec![],
1223 allow_features: "",
1224 cargo_args: Vec::new(),
1225 artifact_kind: ToolArtifactKind::Binary,
1226 })
1227 }
1228
1229 fn metadata(&self) -> Option<StepMetadata> {
1230 Some(StepMetadata::build("LlvmBitcodeLinker", self.target).built_by(self.build_compiler))
1231 }
1232}
1233
1234#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1235pub struct LibcxxVersionTool {
1236 pub target: TargetSelection,
1237}
1238
1239#[expect(dead_code)]
1240#[derive(Debug, Clone)]
1241pub enum LibcxxVersion {
1242 Gnu(usize),
1243 Llvm(usize),
1244}
1245
1246impl Step for LibcxxVersionTool {
1247 type Output = LibcxxVersion;
1248 const DEFAULT: bool = false;
1249 const ONLY_HOSTS: bool = true;
1250
1251 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1252 run.never()
1253 }
1254
1255 fn run(self, builder: &Builder<'_>) -> LibcxxVersion {
1256 let out_dir = builder.out.join(self.target.to_string()).join("libcxx-version");
1257 let executable = out_dir.join(exe("libcxx-version", self.target));
1258
1259 if !executable.exists() {
1264 if !out_dir.exists() {
1265 t!(fs::create_dir_all(&out_dir));
1266 }
1267
1268 let compiler = builder.cxx(self.target).unwrap();
1269 let mut cmd = command(compiler);
1270
1271 cmd.arg("-o")
1272 .arg(&executable)
1273 .arg(builder.src.join("src/tools/libcxx-version/main.cpp"));
1274
1275 cmd.run(builder);
1276
1277 if !executable.exists() {
1278 panic!("Something went wrong. {} is not present", executable.display());
1279 }
1280 }
1281
1282 let version_output = command(executable).run_capture_stdout(builder).stdout();
1283
1284 let version_str = version_output.split_once("version:").unwrap().1;
1285 let version = version_str.trim().parse::<usize>().unwrap();
1286
1287 if version_output.starts_with("libstdc++") {
1288 LibcxxVersion::Gnu(version)
1289 } else if version_output.starts_with("libc++") {
1290 LibcxxVersion::Llvm(version)
1291 } else {
1292 panic!("Coudln't recognize the standard library version.");
1293 }
1294 }
1295}
1296
1297#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
1309pub struct RustcPrivateCompilers {
1310 build_compiler: Compiler,
1312 target_compiler: Compiler,
1315}
1316
1317impl RustcPrivateCompilers {
1318 pub fn new(builder: &Builder<'_>, stage: u32, target: TargetSelection) -> Self {
1321 let build_compiler = Self::build_compiler_from_stage(builder, stage);
1322
1323 let target_compiler = builder.compiler(build_compiler.stage + 1, target);
1326
1327 Self { build_compiler, target_compiler }
1328 }
1329
1330 pub fn from_build_and_target_compiler(
1331 build_compiler: Compiler,
1332 target_compiler: Compiler,
1333 ) -> Self {
1334 Self { build_compiler, target_compiler }
1335 }
1336
1337 pub fn from_build_compiler(
1339 builder: &Builder<'_>,
1340 build_compiler: Compiler,
1341 target: TargetSelection,
1342 ) -> Self {
1343 let target_compiler = builder.compiler(build_compiler.stage + 1, target);
1344 Self { build_compiler, target_compiler }
1345 }
1346
1347 pub fn from_target_compiler(builder: &Builder<'_>, target_compiler: Compiler) -> Self {
1349 Self {
1350 build_compiler: Self::build_compiler_from_stage(builder, target_compiler.stage),
1351 target_compiler,
1352 }
1353 }
1354
1355 fn build_compiler_from_stage(builder: &Builder<'_>, stage: u32) -> Compiler {
1356 assert!(stage > 0);
1357
1358 if builder.download_rustc() && stage == 1 {
1359 builder.compiler(1, builder.config.host_target)
1361 } else {
1362 builder.compiler(stage - 1, builder.config.host_target)
1363 }
1364 }
1365
1366 pub fn build_compiler(&self) -> Compiler {
1367 self.build_compiler
1368 }
1369
1370 pub fn target_compiler(&self) -> Compiler {
1371 self.target_compiler
1372 }
1373
1374 pub fn target(&self) -> TargetSelection {
1376 self.target_compiler.host
1377 }
1378}
1379
1380macro_rules! tool_rustc_extended {
1383 (
1384 $name:ident {
1385 path: $path:expr,
1386 tool_name: $tool_name:expr,
1387 stable: $stable:expr
1388 $( , add_bins_to_sysroot: $add_bins_to_sysroot:expr )?
1389 $( , add_features: $add_features:expr )?
1390 $( , cargo_args: $cargo_args:expr )?
1391 $( , )?
1392 }
1393 ) => {
1394 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
1395 pub struct $name {
1396 compilers: RustcPrivateCompilers,
1397 }
1398
1399 impl $name {
1400 pub fn from_compilers(compilers: RustcPrivateCompilers) -> Self {
1401 Self {
1402 compilers,
1403 }
1404 }
1405 }
1406
1407 impl Step for $name {
1408 type Output = ToolBuildResult;
1409 const DEFAULT: bool = true; const ONLY_HOSTS: bool = true;
1411
1412 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1413 should_run_extended_rustc_tool(
1414 run,
1415 $tool_name,
1416 $path,
1417 $stable,
1418 )
1419 }
1420
1421 fn make_run(run: RunConfig<'_>) {
1422 run.builder.ensure($name {
1423 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1424 });
1425 }
1426
1427 fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
1428 let Self { compilers } = self;
1429 build_extended_rustc_tool(
1430 builder,
1431 compilers,
1432 $tool_name,
1433 $path,
1434 None $( .or(Some(&$add_bins_to_sysroot)) )?,
1435 None $( .or(Some($add_features)) )?,
1436 None $( .or(Some($cargo_args)) )?,
1437 )
1438 }
1439
1440 fn metadata(&self) -> Option<StepMetadata> {
1441 Some(
1442 StepMetadata::build($tool_name, self.compilers.target())
1443 .built_by(self.compilers.build_compiler)
1444 )
1445 }
1446 }
1447 }
1448}
1449
1450fn should_run_extended_rustc_tool<'a>(
1451 run: ShouldRun<'a>,
1452 tool_name: &'static str,
1453 path: &'static str,
1454 stable: bool,
1455) -> ShouldRun<'a> {
1456 let builder = run.builder;
1457 run.path(path).default_condition(
1458 builder.config.extended
1459 && builder.config.tools.as_ref().map_or(
1460 stable || builder.build.unstable_features(),
1463 |tools| {
1465 tools.iter().any(|tool| match tool.as_ref() {
1466 "clippy" => tool_name == "clippy-driver",
1467 x => tool_name == x,
1468 })
1469 },
1470 ),
1471 )
1472}
1473
1474fn build_extended_rustc_tool(
1475 builder: &Builder<'_>,
1476 compilers: RustcPrivateCompilers,
1477 tool_name: &'static str,
1478 path: &'static str,
1479 add_bins_to_sysroot: Option<&[&str]>,
1480 add_features: Option<fn(&Builder<'_>, TargetSelection, &mut Vec<String>)>,
1481 cargo_args: Option<&[&'static str]>,
1482) -> ToolBuildResult {
1483 let target = compilers.target();
1484 let mut extra_features = Vec::new();
1485 if let Some(func) = add_features {
1486 func(builder, target, &mut extra_features);
1487 }
1488
1489 let build_compiler = compilers.build_compiler;
1490 let ToolBuildResult { tool_path, .. } = builder.ensure(ToolBuild {
1491 build_compiler,
1492 target,
1493 tool: tool_name,
1494 mode: Mode::ToolRustc,
1495 path,
1496 extra_features,
1497 source_type: SourceType::InTree,
1498 allow_features: "",
1499 cargo_args: cargo_args.unwrap_or_default().iter().map(|s| String::from(*s)).collect(),
1500 artifact_kind: ToolArtifactKind::Binary,
1501 });
1502
1503 let target_compiler = compilers.target_compiler;
1504 if let Some(add_bins_to_sysroot) = add_bins_to_sysroot
1505 && !add_bins_to_sysroot.is_empty()
1506 {
1507 let bindir = builder.sysroot(target_compiler).join("bin");
1508 t!(fs::create_dir_all(&bindir));
1509
1510 for add_bin in add_bins_to_sysroot {
1511 let bin_destination = bindir.join(exe(add_bin, target_compiler.host));
1512 builder.copy_link(&tool_path, &bin_destination, FileType::Executable);
1513 }
1514
1515 let path = bindir.join(exe(tool_name, target_compiler.host));
1517 ToolBuildResult { tool_path: path, build_compiler }
1518 } else {
1519 ToolBuildResult { tool_path, build_compiler }
1520 }
1521}
1522
1523tool_rustc_extended!(Cargofmt {
1524 path: "src/tools/rustfmt",
1525 tool_name: "cargo-fmt",
1526 stable: true,
1527 add_bins_to_sysroot: ["cargo-fmt"]
1528});
1529tool_rustc_extended!(CargoClippy {
1530 path: "src/tools/clippy",
1531 tool_name: "cargo-clippy",
1532 stable: true,
1533 add_bins_to_sysroot: ["cargo-clippy"]
1534});
1535tool_rustc_extended!(Clippy {
1536 path: "src/tools/clippy",
1537 tool_name: "clippy-driver",
1538 stable: true,
1539 add_bins_to_sysroot: ["clippy-driver"],
1540 add_features: |builder, target, features| {
1541 if builder.config.jemalloc(target) {
1542 features.push("jemalloc".to_string());
1543 }
1544 }
1545});
1546tool_rustc_extended!(Miri {
1547 path: "src/tools/miri",
1548 tool_name: "miri",
1549 stable: false,
1550 add_bins_to_sysroot: ["miri"],
1551 cargo_args: &["--all-targets"],
1553});
1554tool_rustc_extended!(CargoMiri {
1555 path: "src/tools/miri/cargo-miri",
1556 tool_name: "cargo-miri",
1557 stable: false,
1558 add_bins_to_sysroot: ["cargo-miri"]
1559});
1560tool_rustc_extended!(Rustfmt {
1561 path: "src/tools/rustfmt",
1562 tool_name: "rustfmt",
1563 stable: true,
1564 add_bins_to_sysroot: ["rustfmt"]
1565});
1566
1567#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1568pub struct TestFloatParse {
1569 pub host: TargetSelection,
1570}
1571
1572impl TestFloatParse {
1573 pub const ALLOW_FEATURES: &'static str = "f16,cfg_target_has_reliable_f16_f128";
1574}
1575
1576impl Step for TestFloatParse {
1577 type Output = ToolBuildResult;
1578 const ONLY_HOSTS: bool = true;
1579 const DEFAULT: bool = false;
1580
1581 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1582 run.path("src/tools/test-float-parse")
1583 }
1584
1585 fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
1586 let bootstrap_host = builder.config.host_target;
1587 let compiler = builder.compiler(builder.top_stage, bootstrap_host);
1588
1589 builder.ensure(ToolBuild {
1590 build_compiler: compiler,
1591 target: bootstrap_host,
1592 tool: "test-float-parse",
1593 mode: Mode::ToolStd,
1594 path: "src/tools/test-float-parse",
1595 source_type: SourceType::InTree,
1596 extra_features: Vec::new(),
1597 allow_features: Self::ALLOW_FEATURES,
1598 cargo_args: Vec::new(),
1599 artifact_kind: ToolArtifactKind::Binary,
1600 })
1601 }
1602}
1603
1604impl Builder<'_> {
1605 pub fn tool_cmd(&self, tool: Tool) -> BootstrapCommand {
1608 let mut cmd = command(self.tool_exe(tool));
1609 let compiler = self.compiler(0, self.config.host_target);
1610 let host = &compiler.host;
1611 let mut lib_paths: Vec<PathBuf> =
1616 vec![self.cargo_out(compiler, Mode::ToolBootstrap, *host).join("deps")];
1617
1618 if compiler.host.is_msvc() {
1622 let curpaths = env::var_os("PATH").unwrap_or_default();
1623 let curpaths = env::split_paths(&curpaths).collect::<Vec<_>>();
1624 for (k, v) in self.cc[&compiler.host].env() {
1625 if k != "PATH" {
1626 continue;
1627 }
1628 for path in env::split_paths(v) {
1629 if !curpaths.contains(&path) {
1630 lib_paths.push(path);
1631 }
1632 }
1633 }
1634 }
1635
1636 add_dylib_path(lib_paths, &mut cmd);
1637
1638 cmd.env("RUSTC", &self.initial_rustc);
1640
1641 cmd
1642 }
1643}