1 use std
::collections
::HashSet
;
4 use std
::path
::{Path, PathBuf}
;
5 use std
::process
::{exit, Command}
;
9 use crate::builder
::{Builder, Cargo as CargoCommand, RunConfig, ShouldRun, Step}
;
10 use crate::channel
::GitInfo
;
12 use crate::config
::TargetSelection
;
13 use crate::toolstate
::ToolState
;
14 use crate::util
::{add_dylib_path, exe}
;
18 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
24 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
27 target
: TargetSelection
,
31 is_optional_tool
: bool
,
32 source_type
: SourceType
,
33 extra_features
: Vec
<String
>,
36 impl Step
for ToolBuild
{
37 type Output
= Option
<PathBuf
>;
39 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
43 /// Builds a tool in `src/tools`
45 /// This will build the specified tool with the specified `host` compiler in
46 /// `stage` into the normal cargo output directory.
47 fn run(self, builder
: &Builder
<'_
>) -> Option
<PathBuf
> {
48 let compiler
= self.compiler
;
49 let target
= self.target
;
50 let mut tool
= self.tool
;
52 let is_optional_tool
= self.is_optional_tool
;
56 builder
.ensure(compile
::Std { compiler, target: compiler.host }
);
57 builder
.ensure(compile
::Rustc { compiler, target }
);
59 Mode
::ToolStd
=> builder
.ensure(compile
::Std { compiler, target }
),
60 Mode
::ToolBootstrap
=> {}
// uses downloaded stage0 compiler libs
61 _
=> panic
!("unexpected Mode for tool build"),
64 let cargo
= prepare_tool_cargo(
75 builder
.info(&format
!("Building stage{} tool {} ({})", compiler
.stage
, tool
, target
));
76 let mut duplicates
= Vec
::new();
77 let is_expected
= compile
::stream_cargo(builder
, cargo
, vec
![], &mut |msg
| {
78 // Only care about big things like the RLS/Cargo for now
80 "rls" | "cargo" | "clippy-driver" | "miri" | "rustfmt" => {}
84 let (id
, features
, filenames
) = match msg
{
85 compile
::CargoMessage
::CompilerArtifact
{
90 } => (package_id
, features
, filenames
),
93 let features
= features
.iter().map(|s
| s
.to_string()).collect
::<Vec
<_
>>();
95 for path
in filenames
{
96 let val
= (tool
, PathBuf
::from(&*path
), features
.clone());
97 // we're only interested in deduplicating rlibs for now
98 if val
.1.extension().and_then(|s
| s
.to_str()) != Some("rlib") {
102 // Don't worry about compiles that turn out to be host
103 // dependencies or build scripts. To skip these we look for
104 // anything that goes in `.../release/deps` but *doesn't* go in
105 // `$target/release/deps`. This ensure that outputs in
106 // `$target/release` are still considered candidates for
108 if let Some(parent
) = val
.1.parent() {
109 if parent
.ends_with("release/deps") {
110 let maybe_target
= parent
112 .and_then(|p
| p
.parent())
113 .and_then(|p
| p
.file_name())
114 .and_then(|p
| p
.to_str())
116 if maybe_target
!= &*target
.triple
{
122 // Record that we've built an artifact for `id`, and if one was
123 // already listed then we need to see if we reused the same
124 // artifact or produced a duplicate.
125 let mut artifacts
= builder
.tool_artifacts
.borrow_mut();
126 let prev_artifacts
= artifacts
.entry(target
).or_default();
127 let prev
= match prev_artifacts
.get(&*id
) {
130 prev_artifacts
.insert(id
.to_string(), val
);
135 return; // same path, same artifact
138 // If the paths are different and one of them *isn't* inside of
139 // `release/deps`, then it means it's probably in
140 // `$target/release`, or it's some final artifact like
141 // `libcargo.rlib`. In these situations Cargo probably just
142 // copied it up from `$target/release/deps/libcargo-xxxx.rlib`,
143 // so if the features are equal we can just skip it.
144 let prev_no_hash
= prev
.1.parent().unwrap().ends_with("release/deps");
145 let val_no_hash
= val
.1.parent().unwrap().ends_with("release/deps");
146 if prev
.2 == val
.2 || !prev_no_hash
|| !val_no_hash
{
150 // ... and otherwise this looks like we duplicated some sort of
151 // compilation, so record it to generate an error later.
152 duplicates
.push((id
.to_string(), val
, prev
.clone()));
156 if is_expected
&& !duplicates
.is_empty() {
158 "duplicate artifacts found when compiling a tool, this \
159 typically means that something was recompiled because \
160 a transitive dependency has different features activated \
161 than in a previous build:\n"
164 "the following dependencies are duplicated although they \
165 have the same features enabled:"
167 let (same
, different
): (Vec
<_
>, Vec
<_
>) =
168 duplicates
.into_iter().partition(|(_
, cur
, prev
)| cur
.2 == prev
.2);
169 for (id
, cur
, prev
) in same
{
172 println
!(" `{}` ({:?})\n `{}` ({:?})", cur
.0, cur
.1, prev
.0, prev
.1);
174 println
!("the following dependencies have different features:");
175 for (id
, cur
, prev
) in different
{
177 let cur_features
: HashSet
<_
> = cur
.2.into_iter
().collect();
178 let prev_features
: HashSet
<_
> = prev
.2.into_iter
().collect();
180 " `{}` additionally enabled features {:?} at {:?}",
182 &cur_features
- &prev_features
,
186 " `{}` additionally enabled features {:?} at {:?}",
188 &prev_features
- &cur_features
,
194 "to fix this you will probably want to edit the local \
195 src/tools/rustc-workspace-hack/Cargo.toml crate, as \
196 that will update the dependency graph to ensure that \
197 these crates all share the same feature set"
199 panic
!("tools should not compile multiple copies of the same crate");
202 builder
.save_toolstate(
204 if is_expected { ToolState::TestFail }
else { ToolState::BuildFail }
,
208 if !is_optional_tool
{
214 // HACK(#82501): on Windows, the tools directory gets added to PATH when running tests, and
215 // compiletest confuses HTML tidy with the in-tree tidy. Name the in-tree tidy something
216 // different so the problem doesn't come up.
220 let cargo_out
= builder
.cargo_out(compiler
, self.mode
, target
).join(exe(tool
, target
));
221 let bin
= builder
.tools_dir(compiler
).join(exe(tool
, target
));
222 builder
.copy(&cargo_out
, &bin
);
228 pub fn prepare_tool_cargo(
229 builder
: &Builder
<'_
>,
232 target
: TargetSelection
,
233 command
: &'
static str,
235 source_type
: SourceType
,
236 extra_features
: &[String
],
238 let mut cargo
= builder
.cargo(compiler
, mode
, source_type
, target
, command
);
239 let dir
= builder
.src
.join(path
);
240 cargo
.arg("--manifest-path").arg(dir
.join("Cargo.toml"));
242 let mut features
= extra_features
.to_vec();
243 if builder
.build
.config
.cargo_native_static
{
244 if path
.ends_with("cargo")
245 || path
.ends_with("rls")
246 || path
.ends_with("clippy")
247 || path
.ends_with("miri")
248 || path
.ends_with("rustfmt")
250 cargo
.env("LIBZ_SYS_STATIC", "1");
251 features
.push("rustc-workspace-hack/all-static".to_string());
255 // if tools are using lzma we want to force the build script to build its
257 cargo
.env("LZMA_API_STATIC", "1");
259 // CFG_RELEASE is needed by rustfmt (and possibly other tools) which
260 // import rustc-ap-rustc_attr which requires this to be set for the
261 // `#[cfg(version(...))]` attribute.
262 cargo
.env("CFG_RELEASE", builder
.rust_release());
263 cargo
.env("CFG_RELEASE_CHANNEL", &builder
.config
.channel
);
264 cargo
.env("CFG_VERSION", builder
.rust_version());
265 cargo
.env("CFG_RELEASE_NUM", &builder
.version
);
266 cargo
.env("DOC_RUST_LANG_ORG_CHANNEL", builder
.doc_rust_lang_org_channel());
268 let info
= GitInfo
::new(builder
.config
.ignore_git
, &dir
);
269 if let Some(sha
) = info
.sha() {
270 cargo
.env("CFG_COMMIT_HASH", sha
);
272 if let Some(sha_short
) = info
.sha_short() {
273 cargo
.env("CFG_SHORT_COMMIT_HASH", sha_short
);
275 if let Some(date
) = info
.commit_date() {
276 cargo
.env("CFG_COMMIT_DATE", date
);
278 if !features
.is_empty() {
279 cargo
.arg("--features").arg(&features
.join(", "));
284 macro_rules
! bootstrap_tool
{
286 $name
:ident
, $path
:expr
, $tool_name
:expr
287 $
(,is_external_tool
= $external
:expr
)*
288 $
(,is_unstable_tool
= $unstable
:expr
)*
289 $
(,features
= $features
:expr
)*
292 #[derive(Copy, PartialEq, Eq, Clone)]
299 impl<'a
> Builder
<'a
> {
300 pub fn tool_exe(&self, tool
: Tool
) -> PathBuf
{
304 compiler
: self.compiler(0, self.config
.build
),
305 target
: self.config
.build
,
313 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
315 pub compiler
: Compiler
,
316 pub target
: TargetSelection
,
319 impl Step
for $name
{
320 type Output
= PathBuf
;
322 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
326 fn make_run(run
: RunConfig
<'_
>) {
327 run
.builder
.ensure($name
{
329 compiler
: run
.builder
.compiler(0, run
.builder
.config
.build
),
334 fn run(self, builder
: &Builder
<'_
>) -> PathBuf
{
335 builder
.ensure(ToolBuild
{
336 compiler
: self.compiler
,
339 mode
: if false $
(|| $unstable
)* {
340 // use in-tree libraries for unstable features
346 is_optional_tool
: false,
347 source_type
: if false $
(|| $external
)* {
348 SourceType
::Submodule
353 // FIXME(#60643): avoid this lint by using `_`
354 let mut _tmp
= Vec
::new();
355 $
(_tmp
.extend($features
);)*
358 }).expect("expected to build -- essential tool")
366 Rustbook
, "src/tools/rustbook", "rustbook";
367 UnstableBookGen
, "src/tools/unstable-book-gen", "unstable-book-gen";
368 Tidy
, "src/tools/tidy", "tidy";
369 Linkchecker
, "src/tools/linkchecker", "linkchecker";
370 CargoTest
, "src/tools/cargotest", "cargotest";
371 Compiletest
, "src/tools/compiletest", "compiletest", is_unstable_tool
= true;
372 BuildManifest
, "src/tools/build-manifest", "build-manifest";
373 RemoteTestClient
, "src/tools/remote-test-client", "remote-test-client";
374 RustInstaller
, "src/tools/rust-installer", "fabricate", is_external_tool
= true;
375 RustdocTheme
, "src/tools/rustdoc-themes", "rustdoc-themes";
376 ExpandYamlAnchors
, "src/tools/expand-yaml-anchors", "expand-yaml-anchors";
377 LintDocs
, "src/tools/lint-docs", "lint-docs";
378 JsonDocCk
, "src/tools/jsondocck", "jsondocck";
379 HtmlChecker
, "src/tools/html-checker", "html-checker";
382 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Ord, PartialOrd)]
383 pub struct ErrorIndex
{
384 pub compiler
: Compiler
,
388 pub fn command(builder
: &Builder
<'_
>) -> Command
{
389 // This uses stage-1 to match the behavior of building rustdoc.
390 // Error-index-generator links with the rustdoc library, so we want to
391 // use the same librustdoc to avoid building rustdoc twice (and to
392 // avoid building the compiler an extra time). This uses
393 // saturating_sub to deal with building with stage 0. (Using stage 0
394 // isn't recommended, since it will fail if any new error index tests
395 // use new syntax, but it should work otherwise.)
396 let compiler
= builder
.compiler(builder
.top_stage
.saturating_sub(1), builder
.config
.build
);
397 let mut cmd
= Command
::new(builder
.ensure(ErrorIndex { compiler }
));
400 PathBuf
::from(&builder
.sysroot_libdir(compiler
, compiler
.host
)),
401 PathBuf
::from(builder
.rustc_libdir(compiler
)),
409 impl Step
for ErrorIndex
{
410 type Output
= PathBuf
;
412 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
413 run
.path("src/tools/error_index_generator")
416 fn make_run(run
: RunConfig
<'_
>) {
417 // Compile the error-index in the same stage as rustdoc to avoid
418 // recompiling rustdoc twice if we can.
420 // NOTE: This `make_run` isn't used in normal situations, only if you
421 // manually build the tool with `x.py build
422 // src/tools/error-index-generator` which almost nobody does.
423 // Normally, `x.py test` or `x.py doc` will use the
424 // `ErrorIndex::command` function instead.
426 run
.builder
.compiler(run
.builder
.top_stage
.saturating_sub(1), run
.builder
.config
.build
);
427 run
.builder
.ensure(ErrorIndex { compiler }
);
430 fn run(self, builder
: &Builder
<'_
>) -> PathBuf
{
433 compiler
: self.compiler
,
434 target
: self.compiler
.host
,
435 tool
: "error_index_generator",
436 mode
: Mode
::ToolRustc
,
437 path
: "src/tools/error_index_generator",
438 is_optional_tool
: false,
439 source_type
: SourceType
::InTree
,
440 extra_features
: Vec
::new(),
442 .expect("expected to build -- essential tool")
446 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
447 pub struct RemoteTestServer
{
448 pub compiler
: Compiler
,
449 pub target
: TargetSelection
,
452 impl Step
for RemoteTestServer
{
453 type Output
= PathBuf
;
455 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
456 run
.path("src/tools/remote-test-server")
459 fn make_run(run
: RunConfig
<'_
>) {
460 run
.builder
.ensure(RemoteTestServer
{
461 compiler
: run
.builder
.compiler(run
.builder
.top_stage
, run
.builder
.config
.build
),
466 fn run(self, builder
: &Builder
<'_
>) -> PathBuf
{
469 compiler
: self.compiler
,
471 tool
: "remote-test-server",
473 path
: "src/tools/remote-test-server",
474 is_optional_tool
: false,
475 source_type
: SourceType
::InTree
,
476 extra_features
: Vec
::new(),
478 .expect("expected to build -- essential tool")
482 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Ord, PartialOrd)]
484 /// This should only ever be 0 or 2.
485 /// We sometimes want to reference the "bootstrap" rustdoc, which is why this option is here.
486 pub compiler
: Compiler
,
489 impl Step
for Rustdoc
{
490 type Output
= PathBuf
;
491 const DEFAULT
: bool
= true;
492 const ONLY_HOSTS
: bool
= true;
494 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
495 run
.path("src/tools/rustdoc").path("src/librustdoc")
498 fn make_run(run
: RunConfig
<'_
>) {
499 run
.builder
.ensure(Rustdoc
{
500 // Note: this is somewhat unique in that we actually want a *target*
501 // compiler here, because rustdoc *is* a compiler. We won't be using
502 // this as the compiler to build with, but rather this is "what
503 // compiler are we producing"?
504 compiler
: run
.builder
.compiler(run
.builder
.top_stage
, run
.target
),
508 fn run(self, builder
: &Builder
<'_
>) -> PathBuf
{
509 let target_compiler
= self.compiler
;
510 if target_compiler
.stage
== 0 {
511 if !target_compiler
.is_snapshot(builder
) {
512 panic
!("rustdoc in stage 0 must be snapshot rustdoc");
514 return builder
.initial_rustc
.with_file_name(exe("rustdoc", target_compiler
.host
));
516 let target
= target_compiler
.host
;
517 // Similar to `compile::Assemble`, build with the previous stage's compiler. Otherwise
518 // we'd have stageN/bin/rustc and stageN/bin/rustdoc be effectively different stage
519 // compilers, which isn't what we want. Rustdoc should be linked in the same way as the
520 // rustc compiler it's paired with, so it must be built with the previous stage compiler.
521 let build_compiler
= builder
.compiler(target_compiler
.stage
- 1, builder
.config
.build
);
523 // When using `download-rustc` and a stage0 build_compiler, copying rustc doesn't actually
524 // build stage0 libstd (because the libstd in sysroot has the wrong ABI). Explicitly build
526 builder
.ensure(compile
::Std { compiler: build_compiler, target: target_compiler.host }
);
527 builder
.ensure(compile
::Rustc { compiler: build_compiler, target: target_compiler.host }
);
528 // NOTE: this implies that `download-rustc` is pretty useless when compiling with the stage0
529 // compiler, since you do just as much work.
530 if !builder
.config
.dry_run
&& builder
.config
.download_rustc
&& build_compiler
.stage
== 0 {
532 "warning: `download-rustc` does nothing when building stage1 tools; consider using `--stage 2` instead"
536 // The presence of `target_compiler` ensures that the necessary libraries (codegen backends,
537 // compiler libraries, ...) are built. Rustdoc does not require the presence of any
538 // libraries within sysroot_libdir (i.e., rustlib), though doctests may want it (since
539 // they'll be linked to those libraries). As such, don't explicitly `ensure` any additional
540 // libraries here. The intuition here is that If we've built a compiler, we should be able
543 let mut features
= Vec
::new();
544 if builder
.config
.jemalloc
{
545 features
.push("jemalloc".to_string());
548 let cargo
= prepare_tool_cargo(
559 builder
.info(&format
!(
560 "Building rustdoc for stage{} ({})",
561 target_compiler
.stage
, target_compiler
.host
563 builder
.run(&mut cargo
.into());
565 // Cargo adds a number of paths to the dylib search path on windows, which results in
566 // the wrong rustdoc being executed. To avoid the conflicting rustdocs, we name the "tool"
567 // rustdoc a different name.
568 let tool_rustdoc
= builder
569 .cargo_out(build_compiler
, Mode
::ToolRustc
, target
)
570 .join(exe("rustdoc_tool_binary", target_compiler
.host
));
572 // don't create a stage0-sysroot/bin directory.
573 if target_compiler
.stage
> 0 {
574 let sysroot
= builder
.sysroot(target_compiler
);
575 let bindir
= sysroot
.join("bin");
576 t
!(fs
::create_dir_all(&bindir
));
577 let bin_rustdoc
= bindir
.join(exe("rustdoc", target_compiler
.host
));
578 let _
= fs
::remove_file(&bin_rustdoc
);
579 builder
.copy(&tool_rustdoc
, &bin_rustdoc
);
587 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
589 pub compiler
: Compiler
,
590 pub target
: TargetSelection
,
593 impl Step
for Cargo
{
594 type Output
= PathBuf
;
595 const DEFAULT
: bool
= true;
596 const ONLY_HOSTS
: bool
= true;
598 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
599 let builder
= run
.builder
;
600 run
.path("src/tools/cargo").default_condition(
601 builder
.config
.extended
602 && builder
.config
.tools
.as_ref().map_or(
604 // If `tools` is set, search list for this tool.
605 |tools
| tools
.iter().any(|tool
| tool
== "cargo"),
610 fn make_run(run
: RunConfig
<'_
>) {
611 run
.builder
.ensure(Cargo
{
612 compiler
: run
.builder
.compiler(run
.builder
.top_stage
, run
.builder
.config
.build
),
617 fn run(self, builder
: &Builder
<'_
>) -> PathBuf
{
618 let cargo_bin_path
= builder
620 compiler
: self.compiler
,
623 mode
: Mode
::ToolRustc
,
624 path
: "src/tools/cargo",
625 is_optional_tool
: false,
626 source_type
: SourceType
::Submodule
,
627 extra_features
: Vec
::new(),
629 .expect("expected to build -- essential tool");
631 let build_cred
= |name
, path
| {
632 // These credential helpers are currently experimental.
633 // Any build failures will be ignored.
634 let _
= builder
.ensure(ToolBuild
{
635 compiler
: self.compiler
,
638 mode
: Mode
::ToolRustc
,
640 is_optional_tool
: true,
641 source_type
: SourceType
::Submodule
,
642 extra_features
: Vec
::new(),
646 if self.target
.contains("windows") {
648 "cargo-credential-wincred",
649 "src/tools/cargo/crates/credential/cargo-credential-wincred",
652 if self.target
.contains("apple-darwin") {
654 "cargo-credential-macos-keychain",
655 "src/tools/cargo/crates/credential/cargo-credential-macos-keychain",
659 "cargo-credential-1password",
660 "src/tools/cargo/crates/credential/cargo-credential-1password",
666 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
667 pub struct LldWrapper
{
668 pub compiler
: Compiler
,
669 pub target
: TargetSelection
,
670 pub flavor_feature
: &'
static str,
673 impl Step
for LldWrapper
{
674 type Output
= PathBuf
;
676 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
680 fn run(self, builder
: &Builder
<'_
>) -> PathBuf
{
681 let src_exe
= builder
683 compiler
: self.compiler
,
687 path
: "src/tools/lld-wrapper",
688 is_optional_tool
: false,
689 source_type
: SourceType
::InTree
,
690 extra_features
: vec
![self.flavor_feature
.to_owned()],
692 .expect("expected to build -- essential tool");
698 macro_rules
! tool_extended
{
699 (($sel
:ident
, $builder
:ident
),
704 stable
= $stable
:expr
,
705 $
(in_tree
= $in_tree
:expr
,)?
706 $
(submodule
= $submodule
:literal
,)?
707 $extra_deps
:block
;)+) => {
709 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
711 pub compiler
: Compiler
,
712 pub target
: TargetSelection
,
713 pub extra_features
: Vec
<String
>,
716 impl Step
for $name
{
717 type Output
= Option
<PathBuf
>;
718 const DEFAULT
: bool
= true; // Overwritten below
719 const ONLY_HOSTS
: bool
= true;
721 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
722 let builder
= run
.builder
;
723 run
.path($path
).default_condition(
724 builder
.config
.extended
725 && builder
.config
.tools
.as_ref().map_or(
726 // By default, on nightly/dev enable all tools, else only
727 // build stable tools.
728 $stable
|| builder
.build
.unstable_features(),
729 // If `tools` is set, search list for this tool.
731 tools
.iter().any(|tool
| match tool
.as_ref() {
732 "clippy" => $tool_name
== "clippy-driver",
733 x
=> $tool_name
== x
,
739 fn make_run(run
: RunConfig
<'_
>) {
740 run
.builder
.ensure($name
{
741 compiler
: run
.builder
.compiler(run
.builder
.top_stage
, run
.builder
.config
.build
),
743 extra_features
: Vec
::new(),
748 fn run(mut $sel
, $builder
: &Builder
<'_
>) -> Option
<PathBuf
> {
750 $
( $builder
.update_submodule(&Path
::new("src").join("tools").join($submodule
)); )?
751 $builder
.ensure(ToolBuild
{
752 compiler
: $sel
.compiler
,
755 mode
: Mode
::ToolRustc
,
757 extra_features
: $sel
.extra_features
,
758 is_optional_tool
: true,
759 source_type
: if false $
(|| $in_tree
)* {
762 SourceType
::Submodule
771 // Note: tools need to be also added to `Builder::get_step_descriptions` in `builder.rs`
772 // to make `./x.py build <tool>` work.
773 // Note: Most submodule updates for tools are handled by bootstrap.py, since they're needed just to
774 // invoke Cargo to build bootstrap. See the comment there for more details.
775 tool_extended
!((self, builder
),
776 Cargofmt
, rustfmt
, "src/tools/rustfmt", "cargo-fmt", stable
=true, in_tree
=true, {}
;
777 CargoClippy
, clippy
, "src/tools/clippy", "cargo-clippy", stable
=true, in_tree
=true, {}
;
778 Clippy
, clippy
, "src/tools/clippy", "clippy-driver", stable
=true, in_tree
=true, {}
;
779 Miri
, miri
, "src/tools/miri", "miri", stable
=false, {}
;
780 CargoMiri
, miri
, "src/tools/miri/cargo-miri", "cargo-miri", stable
=false, {}
;
781 Rls
, rls
, "src/tools/rls", "rls", stable
=true, {
782 builder
.ensure(Clippy
{
783 compiler
: self.compiler
,
785 extra_features
: Vec
::new(),
787 self.extra_features
.push("clippy".to_owned());
789 RustDemangler
, rust_demangler
, "src/tools/rust-demangler", "rust-demangler", stable
=false, in_tree
=true, {}
;
790 Rustfmt
, rustfmt
, "src/tools/rustfmt", "rustfmt", stable
=true, in_tree
=true, {}
;
791 RustAnalyzer
, rust_analyzer
, "src/tools/rust-analyzer/crates/rust-analyzer", "rust-analyzer", stable
=false, submodule
="rust-analyzer", {}
;
794 impl<'a
> Builder
<'a
> {
795 /// Gets a `Command` which is ready to run `tool` in `stage` built for
797 pub fn tool_cmd(&self, tool
: Tool
) -> Command
{
798 let mut cmd
= Command
::new(self.tool_exe(tool
));
799 let compiler
= self.compiler(0, self.config
.build
);
800 let host
= &compiler
.host
;
801 // Prepares the `cmd` provided to be able to run the `compiler` provided.
803 // Notably this munges the dynamic library lookup path to point to the
804 // right location to run `compiler`.
805 let mut lib_paths
: Vec
<PathBuf
> = vec
![
806 self.build
.rustc_snapshot_libdir(),
807 self.cargo_out(compiler
, Mode
::ToolBootstrap
, *host
).join("deps"),
810 // On MSVC a tool may invoke a C compiler (e.g., compiletest in run-make
811 // mode) and that C compiler may need some extra PATH modification. Do
813 if compiler
.host
.contains("msvc") {
814 let curpaths
= env
::var_os("PATH").unwrap_or_default();
815 let curpaths
= env
::split_paths(&curpaths
).collect
::<Vec
<_
>>();
816 for &(ref k
, ref v
) in self.cc
[&compiler
.host
].env() {
820 for path
in env
::split_paths(v
) {
821 if !curpaths
.contains(&path
) {
822 lib_paths
.push(path
);
828 add_dylib_path(lib_paths
, &mut cmd
);
830 // Provide a RUSTC for this command to use.
831 cmd
.env("RUSTC", &self.initial_rustc
);