]> git.lizzy.rs Git - rust.git/blob - src/bootstrap/builder.rs
Rollup merge of #60234 - tesaguri:cursor-default, r=Amanieu
[rust.git] / src / bootstrap / builder.rs
1 use std::any::Any;
2 use std::cell::{Cell, RefCell};
3 use std::collections::BTreeSet;
4 use std::collections::HashMap;
5 use std::env;
6 use std::fmt::Debug;
7 use std::fs;
8 use std::hash::Hash;
9 use std::ops::Deref;
10 use std::path::{Path, PathBuf};
11 use std::process::Command;
12 use std::time::{Duration, Instant};
13
14 use crate::cache::{Cache, Interned, INTERNER};
15 use crate::check;
16 use crate::compile;
17 use crate::dist;
18 use crate::doc;
19 use crate::flags::Subcommand;
20 use crate::install;
21 use crate::native;
22 use crate::test;
23 use crate::tool;
24 use crate::util::{self, add_lib_path, exe, libdir};
25 use crate::{Build, DocTests, Mode, GitRepo};
26
27 pub use crate::Compiler;
28
29 use petgraph::graph::NodeIndex;
30 use petgraph::Graph;
31
32 pub struct Builder<'a> {
33     pub build: &'a Build,
34     pub top_stage: u32,
35     pub kind: Kind,
36     cache: Cache,
37     stack: RefCell<Vec<Box<dyn Any>>>,
38     time_spent_on_dependencies: Cell<Duration>,
39     pub paths: Vec<PathBuf>,
40     graph_nodes: RefCell<HashMap<String, NodeIndex>>,
41     graph: RefCell<Graph<String, bool>>,
42     parent: Cell<Option<NodeIndex>>,
43 }
44
45 impl<'a> Deref for Builder<'a> {
46     type Target = Build;
47
48     fn deref(&self) -> &Self::Target {
49         self.build
50     }
51 }
52
53 pub trait Step: 'static + Clone + Debug + PartialEq + Eq + Hash {
54     /// `PathBuf` when directories are created or to return a `Compiler` once
55     /// it's been assembled.
56     type Output: Clone;
57
58     const DEFAULT: bool = false;
59
60     /// Run this rule for all hosts without cross compiling.
61     const ONLY_HOSTS: bool = false;
62
63     /// Primary function to execute this rule. Can call `builder.ensure()`
64     /// with other steps to run those.
65     fn run(self, builder: &Builder<'_>) -> Self::Output;
66
67     /// When bootstrap is passed a set of paths, this controls whether this rule
68     /// will execute. However, it does not get called in a "default" context
69     /// when we are not passed any paths; in that case, `make_run` is called
70     /// directly.
71     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_>;
72
73     /// Builds up a "root" rule, either as a default rule or from a path passed
74     /// to us.
75     ///
76     /// When path is `None`, we are executing in a context where no paths were
77     /// passed. When `./x.py build` is run, for example, this rule could get
78     /// called if it is in the correct list below with a path of `None`.
79     fn make_run(_run: RunConfig<'_>) {
80         // It is reasonable to not have an implementation of make_run for rules
81         // who do not want to get called from the root context. This means that
82         // they are likely dependencies (e.g., sysroot creation) or similar, and
83         // as such calling them from ./x.py isn't logical.
84         unimplemented!()
85     }
86 }
87
88 pub struct RunConfig<'a> {
89     pub builder: &'a Builder<'a>,
90     pub host: Interned<String>,
91     pub target: Interned<String>,
92     pub path: PathBuf,
93 }
94
95 struct StepDescription {
96     default: bool,
97     only_hosts: bool,
98     should_run: fn(ShouldRun<'_>) -> ShouldRun<'_>,
99     make_run: fn(RunConfig<'_>),
100     name: &'static str,
101 }
102
103 #[derive(Debug, Clone, PartialOrd, Ord, PartialEq, Eq)]
104 pub enum PathSet {
105     Set(BTreeSet<PathBuf>),
106     Suite(PathBuf),
107 }
108
109 impl PathSet {
110     fn empty() -> PathSet {
111         PathSet::Set(BTreeSet::new())
112     }
113
114     fn one<P: Into<PathBuf>>(path: P) -> PathSet {
115         let mut set = BTreeSet::new();
116         set.insert(path.into());
117         PathSet::Set(set)
118     }
119
120     fn has(&self, needle: &Path) -> bool {
121         match self {
122             PathSet::Set(set) => set.iter().any(|p| p.ends_with(needle)),
123             PathSet::Suite(suite) => suite.ends_with(needle),
124         }
125     }
126
127     fn path(&self, builder: &Builder<'_>) -> PathBuf {
128         match self {
129             PathSet::Set(set) => set
130                 .iter()
131                 .next()
132                 .unwrap_or(&builder.build.src)
133                 .to_path_buf(),
134             PathSet::Suite(path) => PathBuf::from(path),
135         }
136     }
137 }
138
139 impl StepDescription {
140     fn from<S: Step>() -> StepDescription {
141         StepDescription {
142             default: S::DEFAULT,
143             only_hosts: S::ONLY_HOSTS,
144             should_run: S::should_run,
145             make_run: S::make_run,
146             name: unsafe { ::std::intrinsics::type_name::<S>() },
147         }
148     }
149
150     fn maybe_run(&self, builder: &Builder<'_>, pathset: &PathSet) {
151         if builder.config.exclude.iter().any(|e| pathset.has(e)) {
152             eprintln!("Skipping {:?} because it is excluded", pathset);
153             return;
154         } else if !builder.config.exclude.is_empty() {
155             eprintln!(
156                 "{:?} not skipped for {:?} -- not in {:?}",
157                 pathset, self.name, builder.config.exclude
158             );
159         }
160         let hosts = &builder.hosts;
161
162         // Determine the targets participating in this rule.
163         let targets = if self.only_hosts {
164             if !builder.config.run_host_only {
165                 return; // don't run anything
166             } else {
167                 &builder.hosts
168             }
169         } else {
170             &builder.targets
171         };
172
173         for host in hosts {
174             for target in targets {
175                 let run = RunConfig {
176                     builder,
177                     path: pathset.path(builder),
178                     host: *host,
179                     target: *target,
180                 };
181                 (self.make_run)(run);
182             }
183         }
184     }
185
186     fn run(v: &[StepDescription], builder: &Builder<'_>, paths: &[PathBuf]) {
187         let should_runs = v
188             .iter()
189             .map(|desc| (desc.should_run)(ShouldRun::new(builder)))
190             .collect::<Vec<_>>();
191
192         // sanity checks on rules
193         for (desc, should_run) in v.iter().zip(&should_runs) {
194             assert!(
195                 !should_run.paths.is_empty(),
196                 "{:?} should have at least one pathset",
197                 desc.name
198             );
199         }
200
201         if paths.is_empty() {
202             for (desc, should_run) in v.iter().zip(should_runs) {
203                 if desc.default && should_run.is_really_default {
204                     for pathset in &should_run.paths {
205                         desc.maybe_run(builder, pathset);
206                     }
207                 }
208             }
209         } else {
210             for path in paths {
211                 // strip CurDir prefix if present
212                 let path = match path.strip_prefix(".") {
213                     Ok(p) => p,
214                     Err(_) => path,
215                 };
216
217                 let mut attempted_run = false;
218                 for (desc, should_run) in v.iter().zip(&should_runs) {
219                     if let Some(suite) = should_run.is_suite_path(path) {
220                         attempted_run = true;
221                         desc.maybe_run(builder, suite);
222                     } else if let Some(pathset) = should_run.pathset_for_path(path) {
223                         attempted_run = true;
224                         desc.maybe_run(builder, pathset);
225                     }
226                 }
227
228                 if !attempted_run {
229                     panic!("Error: no rules matched {}.", path.display());
230                 }
231             }
232         }
233     }
234 }
235
236 #[derive(Clone)]
237 pub struct ShouldRun<'a> {
238     pub builder: &'a Builder<'a>,
239     // use a BTreeSet to maintain sort order
240     paths: BTreeSet<PathSet>,
241
242     // If this is a default rule, this is an additional constraint placed on
243     // its run. Generally something like compiler docs being enabled.
244     is_really_default: bool,
245 }
246
247 impl<'a> ShouldRun<'a> {
248     fn new(builder: &'a Builder<'_>) -> ShouldRun<'a> {
249         ShouldRun {
250             builder,
251             paths: BTreeSet::new(),
252             is_really_default: true, // by default no additional conditions
253         }
254     }
255
256     pub fn default_condition(mut self, cond: bool) -> Self {
257         self.is_really_default = cond;
258         self
259     }
260
261     // Unlike `krate` this will create just one pathset. As such, it probably shouldn't actually
262     // ever be used, but as we transition to having all rules properly handle passing krate(...) by
263     // actually doing something different for every crate passed.
264     pub fn all_krates(mut self, name: &str) -> Self {
265         let mut set = BTreeSet::new();
266         for krate in self.builder.in_tree_crates(name) {
267             set.insert(PathBuf::from(&krate.path));
268         }
269         self.paths.insert(PathSet::Set(set));
270         self
271     }
272
273     pub fn krate(mut self, name: &str) -> Self {
274         for krate in self.builder.in_tree_crates(name) {
275             self.paths.insert(PathSet::one(&krate.path));
276         }
277         self
278     }
279
280     // single, non-aliased path
281     pub fn path(self, path: &str) -> Self {
282         self.paths(&[path])
283     }
284
285     // multiple aliases for the same job
286     pub fn paths(mut self, paths: &[&str]) -> Self {
287         self.paths
288             .insert(PathSet::Set(paths.iter().map(PathBuf::from).collect()));
289         self
290     }
291
292     pub fn is_suite_path(&self, path: &Path) -> Option<&PathSet> {
293         self.paths.iter().find(|pathset| match pathset {
294             PathSet::Suite(p) => path.starts_with(p),
295             PathSet::Set(_) => false,
296         })
297     }
298
299     pub fn suite_path(mut self, suite: &str) -> Self {
300         self.paths.insert(PathSet::Suite(PathBuf::from(suite)));
301         self
302     }
303
304     // allows being more explicit about why should_run in Step returns the value passed to it
305     pub fn never(mut self) -> ShouldRun<'a> {
306         self.paths.insert(PathSet::empty());
307         self
308     }
309
310     fn pathset_for_path(&self, path: &Path) -> Option<&PathSet> {
311         self.paths.iter().find(|pathset| pathset.has(path))
312     }
313 }
314
315 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
316 pub enum Kind {
317     Build,
318     Check,
319     Test,
320     Bench,
321     Dist,
322     Doc,
323     Install,
324 }
325
326 impl<'a> Builder<'a> {
327     fn get_step_descriptions(kind: Kind) -> Vec<StepDescription> {
328         macro_rules! describe {
329             ($($rule:ty),+ $(,)?) => {{
330                 vec![$(StepDescription::from::<$rule>()),+]
331             }};
332         }
333         match kind {
334             Kind::Build => describe!(
335                 compile::Std,
336                 compile::Test,
337                 compile::Rustc,
338                 compile::CodegenBackend,
339                 compile::StartupObjects,
340                 tool::BuildManifest,
341                 tool::Rustbook,
342                 tool::ErrorIndex,
343                 tool::UnstableBookGen,
344                 tool::Tidy,
345                 tool::Linkchecker,
346                 tool::CargoTest,
347                 tool::Compiletest,
348                 tool::RemoteTestServer,
349                 tool::RemoteTestClient,
350                 tool::RustInstaller,
351                 tool::Cargo,
352                 tool::Rls,
353                 tool::Rustdoc,
354                 tool::Clippy,
355                 native::Llvm,
356                 tool::Rustfmt,
357                 tool::Miri,
358                 native::Lld
359             ),
360             Kind::Check => describe!(
361                 check::Std,
362                 check::Test,
363                 check::Rustc,
364                 check::CodegenBackend,
365                 check::Rustdoc
366             ),
367             Kind::Test => describe!(
368                 test::Tidy,
369                 test::Ui,
370                 test::RunPass,
371                 test::CompileFail,
372                 test::RunFail,
373                 test::RunPassValgrind,
374                 test::MirOpt,
375                 test::Codegen,
376                 test::CodegenUnits,
377                 test::Assembly,
378                 test::Incremental,
379                 test::Debuginfo,
380                 test::UiFullDeps,
381                 test::RunPassFullDeps,
382                 test::Rustdoc,
383                 test::Pretty,
384                 test::RunPassPretty,
385                 test::RunFailPretty,
386                 test::RunPassValgrindPretty,
387                 test::Crate,
388                 test::CrateLibrustc,
389                 test::CrateRustdoc,
390                 test::Linkcheck,
391                 test::Cargotest,
392                 test::Cargo,
393                 test::Rls,
394                 test::ErrorIndex,
395                 test::Distcheck,
396                 test::RunMakeFullDeps,
397                 test::Nomicon,
398                 test::Reference,
399                 test::RustdocBook,
400                 test::RustByExample,
401                 test::TheBook,
402                 test::UnstableBook,
403                 test::RustcBook,
404                 test::EmbeddedBook,
405                 test::EditionGuide,
406                 test::Rustfmt,
407                 test::Miri,
408                 test::Clippy,
409                 test::CompiletestTest,
410                 test::RustdocJSStd,
411                 test::RustdocJSNotStd,
412                 test::RustdocTheme,
413                 test::RustdocUi,
414                 // Run bootstrap close to the end as it's unlikely to fail
415                 test::Bootstrap,
416                 // Run run-make last, since these won't pass without make on Windows
417                 test::RunMake,
418             ),
419             Kind::Bench => describe!(test::Crate, test::CrateLibrustc),
420             Kind::Doc => describe!(
421                 doc::UnstableBook,
422                 doc::UnstableBookGen,
423                 doc::TheBook,
424                 doc::Standalone,
425                 doc::Std,
426                 doc::Test,
427                 doc::WhitelistedRustc,
428                 doc::Rustc,
429                 doc::Rustdoc,
430                 doc::ErrorIndex,
431                 doc::Nomicon,
432                 doc::Reference,
433                 doc::RustdocBook,
434                 doc::RustByExample,
435                 doc::RustcBook,
436                 doc::CargoBook,
437                 doc::EmbeddedBook,
438                 doc::EditionGuide,
439             ),
440             Kind::Dist => describe!(
441                 dist::Docs,
442                 dist::RustcDocs,
443                 dist::Mingw,
444                 dist::Rustc,
445                 dist::DebuggerScripts,
446                 dist::Std,
447                 dist::Analysis,
448                 dist::Src,
449                 dist::PlainSourceTarball,
450                 dist::Cargo,
451                 dist::Rls,
452                 dist::Rustfmt,
453                 dist::Clippy,
454                 dist::Miri,
455                 dist::LlvmTools,
456                 dist::Lldb,
457                 dist::Extended,
458                 dist::HashSign
459             ),
460             Kind::Install => describe!(
461                 install::Docs,
462                 install::Std,
463                 install::Cargo,
464                 install::Rls,
465                 install::Rustfmt,
466                 install::Clippy,
467                 install::Miri,
468                 install::Analysis,
469                 install::Src,
470                 install::Rustc
471             ),
472         }
473     }
474
475     pub fn get_help(build: &Build, subcommand: &str) -> Option<String> {
476         let kind = match subcommand {
477             "build" => Kind::Build,
478             "doc" => Kind::Doc,
479             "test" => Kind::Test,
480             "bench" => Kind::Bench,
481             "dist" => Kind::Dist,
482             "install" => Kind::Install,
483             _ => return None,
484         };
485
486         let builder = Builder {
487             build,
488             top_stage: build.config.stage.unwrap_or(2),
489             kind,
490             cache: Cache::new(),
491             stack: RefCell::new(Vec::new()),
492             time_spent_on_dependencies: Cell::new(Duration::new(0, 0)),
493             paths: vec![],
494             graph_nodes: RefCell::new(HashMap::new()),
495             graph: RefCell::new(Graph::new()),
496             parent: Cell::new(None),
497         };
498
499         let builder = &builder;
500         let mut should_run = ShouldRun::new(builder);
501         for desc in Builder::get_step_descriptions(builder.kind) {
502             should_run = (desc.should_run)(should_run);
503         }
504         let mut help = String::from("Available paths:\n");
505         for pathset in should_run.paths {
506             if let PathSet::Set(set) = pathset {
507                 set.iter().for_each(|path| {
508                     help.push_str(
509                         format!("    ./x.py {} {}\n", subcommand, path.display()).as_str(),
510                     )
511                 })
512             }
513         }
514         Some(help)
515     }
516
517     pub fn new(build: &Build) -> Builder<'_> {
518         let (kind, paths) = match build.config.cmd {
519             Subcommand::Build { ref paths } => (Kind::Build, &paths[..]),
520             Subcommand::Check { ref paths } => (Kind::Check, &paths[..]),
521             Subcommand::Doc { ref paths } => (Kind::Doc, &paths[..]),
522             Subcommand::Test { ref paths, .. } => (Kind::Test, &paths[..]),
523             Subcommand::Bench { ref paths, .. } => (Kind::Bench, &paths[..]),
524             Subcommand::Dist { ref paths } => (Kind::Dist, &paths[..]),
525             Subcommand::Install { ref paths } => (Kind::Install, &paths[..]),
526             Subcommand::Clean { .. } => panic!(),
527         };
528
529         let builder = Builder {
530             build,
531             top_stage: build.config.stage.unwrap_or(2),
532             kind,
533             cache: Cache::new(),
534             stack: RefCell::new(Vec::new()),
535             time_spent_on_dependencies: Cell::new(Duration::new(0, 0)),
536             paths: paths.to_owned(),
537             graph_nodes: RefCell::new(HashMap::new()),
538             graph: RefCell::new(Graph::new()),
539             parent: Cell::new(None),
540         };
541
542         if kind == Kind::Dist {
543             assert!(
544                 !builder.config.test_miri,
545                 "Do not distribute with miri enabled.\n\
546                 The distributed libraries would include all MIR (increasing binary size).
547                 The distributed MIR would include validation statements."
548             );
549         }
550
551         builder
552     }
553
554     pub fn execute_cli(&self) -> Graph<String, bool> {
555         self.run_step_descriptions(&Builder::get_step_descriptions(self.kind), &self.paths);
556         self.graph.borrow().clone()
557     }
558
559     pub fn default_doc(&self, paths: Option<&[PathBuf]>) {
560         let paths = paths.unwrap_or(&[]);
561         self.run_step_descriptions(&Builder::get_step_descriptions(Kind::Doc), paths);
562     }
563
564     fn run_step_descriptions(&self, v: &[StepDescription], paths: &[PathBuf]) {
565         StepDescription::run(v, self, paths);
566     }
567
568     /// Obtain a compiler at a given stage and for a given host. Explicitly does
569     /// not take `Compiler` since all `Compiler` instances are meant to be
570     /// obtained through this function, since it ensures that they are valid
571     /// (i.e., built and assembled).
572     pub fn compiler(&self, stage: u32, host: Interned<String>) -> Compiler {
573         self.ensure(compile::Assemble {
574             target_compiler: Compiler { stage, host },
575         })
576     }
577
578     pub fn sysroot(&self, compiler: Compiler) -> Interned<PathBuf> {
579         self.ensure(compile::Sysroot { compiler })
580     }
581
582     /// Returns the libdir where the standard library and other artifacts are
583     /// found for a compiler's sysroot.
584     pub fn sysroot_libdir(
585         &self,
586         compiler: Compiler,
587         target: Interned<String>,
588     ) -> Interned<PathBuf> {
589         #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
590         struct Libdir {
591             compiler: Compiler,
592             target: Interned<String>,
593         }
594         impl Step for Libdir {
595             type Output = Interned<PathBuf>;
596
597             fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
598                 run.never()
599             }
600
601             fn run(self, builder: &Builder<'_>) -> Interned<PathBuf> {
602                 let compiler = self.compiler;
603                 let config = &builder.build.config;
604                 let lib = if compiler.stage >= 1 && config.libdir_relative().is_some() {
605                     builder.build.config.libdir_relative().unwrap()
606                 } else {
607                     Path::new("lib")
608                 };
609                 let sysroot = builder
610                     .sysroot(self.compiler)
611                     .join(lib)
612                     .join("rustlib")
613                     .join(self.target)
614                     .join("lib");
615                 let _ = fs::remove_dir_all(&sysroot);
616                 t!(fs::create_dir_all(&sysroot));
617                 INTERNER.intern_path(sysroot)
618             }
619         }
620         self.ensure(Libdir { compiler, target })
621     }
622
623     pub fn sysroot_codegen_backends(&self, compiler: Compiler) -> PathBuf {
624         self.sysroot_libdir(compiler, compiler.host)
625             .with_file_name(self.config.rust_codegen_backends_dir.clone())
626     }
627
628     /// Returns the compiler's libdir where it stores the dynamic libraries that
629     /// it itself links against.
630     ///
631     /// For example this returns `<sysroot>/lib` on Unix and `<sysroot>/bin` on
632     /// Windows.
633     pub fn rustc_libdir(&self, compiler: Compiler) -> PathBuf {
634         if compiler.is_snapshot(self) {
635             self.rustc_snapshot_libdir()
636         } else {
637             match self.config.libdir_relative() {
638                 Some(relative_libdir) if compiler.stage >= 1
639                     => self.sysroot(compiler).join(relative_libdir),
640                 _ => self.sysroot(compiler).join(libdir(&compiler.host))
641             }
642         }
643     }
644
645     /// Returns the compiler's relative libdir where it stores the dynamic libraries that
646     /// it itself links against.
647     ///
648     /// For example this returns `lib` on Unix and `bin` on
649     /// Windows.
650     pub fn libdir_relative(&self, compiler: Compiler) -> &Path {
651         if compiler.is_snapshot(self) {
652             libdir(&self.config.build).as_ref()
653         } else {
654             match self.config.libdir_relative() {
655                 Some(relative_libdir) if compiler.stage >= 1
656                     => relative_libdir,
657                 _ => libdir(&compiler.host).as_ref()
658             }
659         }
660     }
661
662     /// Adds the compiler's directory of dynamic libraries to `cmd`'s dynamic
663     /// library lookup path.
664     pub fn add_rustc_lib_path(&self, compiler: Compiler, cmd: &mut Command) {
665         // Windows doesn't need dylib path munging because the dlls for the
666         // compiler live next to the compiler and the system will find them
667         // automatically.
668         if cfg!(windows) {
669             return;
670         }
671
672         add_lib_path(vec![self.rustc_libdir(compiler)], cmd);
673     }
674
675     /// Gets a path to the compiler specified.
676     pub fn rustc(&self, compiler: Compiler) -> PathBuf {
677         if compiler.is_snapshot(self) {
678             self.initial_rustc.clone()
679         } else {
680             self.sysroot(compiler)
681                 .join("bin")
682                 .join(exe("rustc", &compiler.host))
683         }
684     }
685
686     /// Gets the paths to all of the compiler's codegen backends.
687     fn codegen_backends(&self, compiler: Compiler) -> impl Iterator<Item = PathBuf> {
688         fs::read_dir(self.sysroot_codegen_backends(compiler))
689             .into_iter()
690             .flatten()
691             .filter_map(Result::ok)
692             .map(|entry| entry.path())
693     }
694
695     pub fn rustdoc(&self, compiler: Compiler) -> PathBuf {
696         self.ensure(tool::Rustdoc { compiler })
697     }
698
699     pub fn rustdoc_cmd(&self, compiler: Compiler) -> Command {
700         let mut cmd = Command::new(&self.out.join("bootstrap/debug/rustdoc"));
701         cmd.env("RUSTC_STAGE", compiler.stage.to_string())
702             .env("RUSTC_SYSROOT", self.sysroot(compiler))
703             // Note that this is *not* the sysroot_libdir because rustdoc must be linked
704             // equivalently to rustc.
705             .env("RUSTDOC_LIBDIR", self.rustc_libdir(compiler))
706             .env("CFG_RELEASE_CHANNEL", &self.config.channel)
707             .env("RUSTDOC_REAL", self.rustdoc(compiler))
708             .env("RUSTDOC_CRATE_VERSION", self.rust_version())
709             .env("RUSTC_BOOTSTRAP", "1");
710
711         // Remove make-related flags that can cause jobserver problems.
712         cmd.env_remove("MAKEFLAGS");
713         cmd.env_remove("MFLAGS");
714
715         if let Some(linker) = self.linker(compiler.host) {
716             cmd.env("RUSTC_TARGET_LINKER", linker);
717         }
718         cmd
719     }
720
721     /// Prepares an invocation of `cargo` to be run.
722     ///
723     /// This will create a `Command` that represents a pending execution of
724     /// Cargo. This cargo will be configured to use `compiler` as the actual
725     /// rustc compiler, its output will be scoped by `mode`'s output directory,
726     /// it will pass the `--target` flag for the specified `target`, and will be
727     /// executing the Cargo command `cmd`.
728     pub fn cargo(
729         &self,
730         compiler: Compiler,
731         mode: Mode,
732         target: Interned<String>,
733         cmd: &str,
734     ) -> Command {
735         let mut cargo = Command::new(&self.initial_cargo);
736         let out_dir = self.stage_out(compiler, mode);
737
738         // command specific path, we call clear_if_dirty with this
739         let mut my_out = match cmd {
740             "build" => self.cargo_out(compiler, mode, target),
741
742             // This is the intended out directory for crate documentation.
743             "doc" | "rustdoc" =>  self.crate_doc_out(target),
744
745             _ => self.stage_out(compiler, mode),
746         };
747
748         // This is for the original compiler, but if we're forced to use stage 1, then
749         // std/test/rustc stamps won't exist in stage 2, so we need to get those from stage 1, since
750         // we copy the libs forward.
751         let cmp = if self.force_use_stage1(compiler, target) {
752             self.compiler(1, compiler.host)
753         } else {
754             compiler
755         };
756
757         let libstd_stamp = match cmd {
758             "check" => check::libstd_stamp(self, cmp, target),
759             _ => compile::libstd_stamp(self, cmp, target),
760         };
761
762         let libtest_stamp = match cmd {
763             "check" => check::libtest_stamp(self, cmp, target),
764             _ => compile::libstd_stamp(self, cmp, target),
765         };
766
767         let librustc_stamp = match cmd {
768             "check" => check::librustc_stamp(self, cmp, target),
769             _ => compile::librustc_stamp(self, cmp, target),
770         };
771
772         if cmd == "doc" || cmd == "rustdoc" {
773             if mode == Mode::Rustc || mode == Mode::ToolRustc || mode == Mode::Codegen {
774                 // This is the intended out directory for compiler documentation.
775                 my_out = self.compiler_doc_out(target);
776             }
777             let rustdoc = self.rustdoc(compiler);
778             self.clear_if_dirty(&my_out, &rustdoc);
779         } else if cmd != "test" {
780             match mode {
781                 Mode::Std => {
782                     self.clear_if_dirty(&my_out, &self.rustc(compiler));
783                     for backend in self.codegen_backends(compiler) {
784                         self.clear_if_dirty(&my_out, &backend);
785                     }
786                 },
787                 Mode::Test => {
788                     self.clear_if_dirty(&my_out, &libstd_stamp);
789                 },
790                 Mode::Rustc => {
791                     self.clear_if_dirty(&my_out, &self.rustc(compiler));
792                     self.clear_if_dirty(&my_out, &libstd_stamp);
793                     self.clear_if_dirty(&my_out, &libtest_stamp);
794                 },
795                 Mode::Codegen => {
796                     self.clear_if_dirty(&my_out, &librustc_stamp);
797                 },
798                 Mode::ToolBootstrap => { },
799                 Mode::ToolStd => {
800                     self.clear_if_dirty(&my_out, &libstd_stamp);
801                 },
802                 Mode::ToolTest => {
803                     self.clear_if_dirty(&my_out, &libstd_stamp);
804                     self.clear_if_dirty(&my_out, &libtest_stamp);
805                 },
806                 Mode::ToolRustc => {
807                     self.clear_if_dirty(&my_out, &libstd_stamp);
808                     self.clear_if_dirty(&my_out, &libtest_stamp);
809                     self.clear_if_dirty(&my_out, &librustc_stamp);
810                 },
811             }
812         }
813
814         cargo
815             .env("CARGO_TARGET_DIR", out_dir)
816             .arg(cmd);
817
818         // See comment in librustc_llvm/build.rs for why this is necessary, largely llvm-config
819         // needs to not accidentally link to libLLVM in stage0/lib.
820         cargo.env("REAL_LIBRARY_PATH_VAR", &util::dylib_path_var());
821         if let Some(e) = env::var_os(util::dylib_path_var()) {
822             cargo.env("REAL_LIBRARY_PATH", e);
823         }
824
825         if cmd != "install" {
826             cargo.arg("--target")
827                  .arg(target);
828         } else {
829             assert_eq!(target, compiler.host);
830         }
831
832         // Set a flag for `check` so that certain build scripts can do less work
833         // (e.g., not building/requiring LLVM).
834         if cmd == "check" {
835             cargo.env("RUST_CHECK", "1");
836         }
837
838         match mode {
839             Mode::Std | Mode::Test | Mode::ToolBootstrap | Mode::ToolStd | Mode::ToolTest=> {},
840             Mode::Rustc | Mode::Codegen | Mode::ToolRustc => {
841                 // Build proc macros both for the host and the target
842                 if target != compiler.host && cmd != "check" {
843                     cargo.arg("-Zdual-proc-macros");
844                     cargo.env("RUST_DUAL_PROC_MACROS", "1");
845                 }
846             },
847         }
848
849         cargo.arg("-j").arg(self.jobs().to_string());
850         // Remove make-related flags to ensure Cargo can correctly set things up
851         cargo.env_remove("MAKEFLAGS");
852         cargo.env_remove("MFLAGS");
853
854         // FIXME: Temporary fix for https://github.com/rust-lang/cargo/issues/3005
855         // Force cargo to output binaries with disambiguating hashes in the name
856         let mut metadata = if compiler.stage == 0 {
857             // Treat stage0 like a special channel, whether it's a normal prior-
858             // release rustc or a local rebuild with the same version, so we
859             // never mix these libraries by accident.
860             "bootstrap".to_string()
861         } else {
862             self.config.channel.to_string()
863         };
864         // We want to make sure that none of the dependencies between
865         // std/test/rustc unify with one another. This is done for weird linkage
866         // reasons but the gist of the problem is that if librustc, libtest, and
867         // libstd all depend on libc from crates.io (which they actually do) we
868         // want to make sure they all get distinct versions. Things get really
869         // weird if we try to unify all these dependencies right now, namely
870         // around how many times the library is linked in dynamic libraries and
871         // such. If rustc were a static executable or if we didn't ship dylibs
872         // this wouldn't be a problem, but we do, so it is. This is in general
873         // just here to make sure things build right. If you can remove this and
874         // things still build right, please do!
875         match mode {
876             Mode::Std => metadata.push_str("std"),
877             Mode::Test => metadata.push_str("test"),
878             _ => {},
879         }
880         cargo.env("__CARGO_DEFAULT_LIB_METADATA", &metadata);
881
882         let stage;
883         if compiler.stage == 0 && self.local_rebuild {
884             // Assume the local-rebuild rustc already has stage1 features.
885             stage = 1;
886         } else {
887             stage = compiler.stage;
888         }
889
890         let mut extra_args = env::var(&format!("RUSTFLAGS_STAGE_{}", stage)).unwrap_or_default();
891         if stage != 0 {
892             let s = env::var("RUSTFLAGS_STAGE_NOT_0").unwrap_or_default();
893             if !extra_args.is_empty() {
894                 extra_args.push_str(" ");
895             }
896             extra_args.push_str(&s);
897         }
898
899         if !extra_args.is_empty() {
900             cargo.env(
901                 "RUSTFLAGS",
902                 format!(
903                     "{} {}",
904                     env::var("RUSTFLAGS").unwrap_or_default(),
905                     extra_args
906                 ),
907             );
908         }
909
910         let want_rustdoc = self.doc_tests != DocTests::No;
911
912         // We synthetically interpret a stage0 compiler used to build tools as a
913         // "raw" compiler in that it's the exact snapshot we download. Normally
914         // the stage0 build means it uses libraries build by the stage0
915         // compiler, but for tools we just use the precompiled libraries that
916         // we've downloaded
917         let use_snapshot = mode == Mode::ToolBootstrap;
918         assert!(!use_snapshot || stage == 0 || self.local_rebuild);
919
920         let maybe_sysroot = self.sysroot(compiler);
921         let sysroot = if use_snapshot {
922             self.rustc_snapshot_sysroot()
923         } else {
924             &maybe_sysroot
925         };
926         let libdir = self.rustc_libdir(compiler);
927
928         // Customize the compiler we're running. Specify the compiler to cargo
929         // as our shim and then pass it some various options used to configure
930         // how the actual compiler itself is called.
931         //
932         // These variables are primarily all read by
933         // src/bootstrap/bin/{rustc.rs,rustdoc.rs}
934         cargo
935             .env("RUSTBUILD_NATIVE_DIR", self.native_dir(target))
936             .env("RUSTC", self.out.join("bootstrap/debug/rustc"))
937             .env("RUSTC_REAL", self.rustc(compiler))
938             .env("RUSTC_STAGE", stage.to_string())
939             .env(
940                 "RUSTC_DEBUG_ASSERTIONS",
941                 self.config.rust_debug_assertions.to_string(),
942             )
943             .env("RUSTC_SYSROOT", &sysroot)
944             .env("RUSTC_LIBDIR", &libdir)
945             .env("RUSTC_RPATH", self.config.rust_rpath.to_string())
946             .env("RUSTDOC", self.out.join("bootstrap/debug/rustdoc"))
947             .env(
948                 "RUSTDOC_REAL",
949                 if cmd == "doc" || cmd == "rustdoc" || (cmd == "test" && want_rustdoc) {
950                     self.rustdoc(compiler)
951                 } else {
952                     PathBuf::from("/path/to/nowhere/rustdoc/not/required")
953                 },
954             )
955             .env("TEST_MIRI", self.config.test_miri.to_string())
956             .env("RUSTC_ERROR_METADATA_DST", self.extended_error_dir());
957
958         if let Some(host_linker) = self.linker(compiler.host) {
959             cargo.env("RUSTC_HOST_LINKER", host_linker);
960         }
961         if let Some(target_linker) = self.linker(target) {
962             cargo.env("RUSTC_TARGET_LINKER", target_linker);
963         }
964         if let Some(ref error_format) = self.config.rustc_error_format {
965             cargo.env("RUSTC_ERROR_FORMAT", error_format);
966         }
967         if cmd != "build" && cmd != "check" && cmd != "rustc" && want_rustdoc {
968             cargo.env("RUSTDOC_LIBDIR", self.rustc_libdir(compiler));
969         }
970
971         if mode.is_tool() {
972             // Tools like cargo and rls don't get debuginfo by default right now, but this can be
973             // enabled in the config.  Adding debuginfo makes them several times larger.
974             if self.config.rust_debuginfo_tools {
975                 cargo.env("RUSTC_DEBUGINFO", self.config.rust_debuginfo.to_string());
976                 cargo.env(
977                     "RUSTC_DEBUGINFO_LINES",
978                     self.config.rust_debuginfo_lines.to_string(),
979                 );
980             }
981         } else {
982             cargo.env("RUSTC_DEBUGINFO", self.config.rust_debuginfo.to_string());
983             cargo.env(
984                 "RUSTC_DEBUGINFO_LINES",
985                 self.config.rust_debuginfo_lines.to_string(),
986             );
987             cargo.env("RUSTC_FORCE_UNSTABLE", "1");
988
989             // Currently the compiler depends on crates from crates.io, and
990             // then other crates can depend on the compiler (e.g., proc-macro
991             // crates). Let's say, for example that rustc itself depends on the
992             // bitflags crate. If an external crate then depends on the
993             // bitflags crate as well, we need to make sure they don't
994             // conflict, even if they pick the same version of bitflags. We'll
995             // want to make sure that e.g., a plugin and rustc each get their
996             // own copy of bitflags.
997
998             // Cargo ensures that this works in general through the -C metadata
999             // flag. This flag will frob the symbols in the binary to make sure
1000             // they're different, even though the source code is the exact
1001             // same. To solve this problem for the compiler we extend Cargo's
1002             // already-passed -C metadata flag with our own. Our rustc.rs
1003             // wrapper around the actual rustc will detect -C metadata being
1004             // passed and frob it with this extra string we're passing in.
1005             cargo.env("RUSTC_METADATA_SUFFIX", "rustc");
1006         }
1007
1008         if let Some(x) = self.crt_static(target) {
1009             cargo.env("RUSTC_CRT_STATIC", x.to_string());
1010         }
1011
1012         if let Some(x) = self.crt_static(compiler.host) {
1013             cargo.env("RUSTC_HOST_CRT_STATIC", x.to_string());
1014         }
1015
1016         if let Some(map) = self.build.debuginfo_map(GitRepo::Rustc) {
1017             cargo.env("RUSTC_DEBUGINFO_MAP", map);
1018         }
1019
1020         // Enable usage of unstable features
1021         cargo.env("RUSTC_BOOTSTRAP", "1");
1022         self.add_rust_test_threads(&mut cargo);
1023
1024         // Almost all of the crates that we compile as part of the bootstrap may
1025         // have a build script, including the standard library. To compile a
1026         // build script, however, it itself needs a standard library! This
1027         // introduces a bit of a pickle when we're compiling the standard
1028         // library itself.
1029         //
1030         // To work around this we actually end up using the snapshot compiler
1031         // (stage0) for compiling build scripts of the standard library itself.
1032         // The stage0 compiler is guaranteed to have a libstd available for use.
1033         //
1034         // For other crates, however, we know that we've already got a standard
1035         // library up and running, so we can use the normal compiler to compile
1036         // build scripts in that situation.
1037         if mode == Mode::Std {
1038             cargo
1039                 .env("RUSTC_SNAPSHOT", &self.initial_rustc)
1040                 .env("RUSTC_SNAPSHOT_LIBDIR", self.rustc_snapshot_libdir());
1041         } else {
1042             cargo
1043                 .env("RUSTC_SNAPSHOT", self.rustc(compiler))
1044                 .env("RUSTC_SNAPSHOT_LIBDIR", self.rustc_libdir(compiler));
1045         }
1046
1047         if self.config.incremental {
1048             cargo.env("CARGO_INCREMENTAL", "1");
1049         } else {
1050             // Don't rely on any default setting for incr. comp. in Cargo
1051             cargo.env("CARGO_INCREMENTAL", "0");
1052         }
1053
1054         if let Some(ref on_fail) = self.config.on_fail {
1055             cargo.env("RUSTC_ON_FAIL", on_fail);
1056         }
1057
1058         if self.config.print_step_timings {
1059             cargo.env("RUSTC_PRINT_STEP_TIMINGS", "1");
1060         }
1061
1062         if self.config.backtrace_on_ice {
1063             cargo.env("RUSTC_BACKTRACE_ON_ICE", "1");
1064         }
1065
1066         cargo.env("RUSTC_VERBOSE", self.verbosity.to_string());
1067
1068         if self.config.deny_warnings {
1069             cargo.env("RUSTC_DENY_WARNINGS", "1");
1070         }
1071
1072         // Throughout the build Cargo can execute a number of build scripts
1073         // compiling C/C++ code and we need to pass compilers, archivers, flags, etc
1074         // obtained previously to those build scripts.
1075         // Build scripts use either the `cc` crate or `configure/make` so we pass
1076         // the options through environment variables that are fetched and understood by both.
1077         //
1078         // FIXME: the guard against msvc shouldn't need to be here
1079         if target.contains("msvc") {
1080             if let Some(ref cl) = self.config.llvm_clang_cl {
1081                 cargo.env("CC", cl).env("CXX", cl);
1082             }
1083         } else {
1084             let ccache = self.config.ccache.as_ref();
1085             let ccacheify = |s: &Path| {
1086                 let ccache = match ccache {
1087                     Some(ref s) => s,
1088                     None => return s.display().to_string(),
1089                 };
1090                 // FIXME: the cc-rs crate only recognizes the literal strings
1091                 // `ccache` and `sccache` when doing caching compilations, so we
1092                 // mirror that here. It should probably be fixed upstream to
1093                 // accept a new env var or otherwise work with custom ccache
1094                 // vars.
1095                 match &ccache[..] {
1096                     "ccache" | "sccache" => format!("{} {}", ccache, s.display()),
1097                     _ => s.display().to_string(),
1098                 }
1099             };
1100             let cc = ccacheify(&self.cc(target));
1101             cargo.env(format!("CC_{}", target), &cc);
1102
1103             let cflags = self.cflags(target, GitRepo::Rustc).join(" ");
1104             cargo
1105                 .env(format!("CFLAGS_{}", target), cflags.clone());
1106
1107             if let Some(ar) = self.ar(target) {
1108                 let ranlib = format!("{} s", ar.display());
1109                 cargo
1110                     .env(format!("AR_{}", target), ar)
1111                     .env(format!("RANLIB_{}", target), ranlib);
1112             }
1113
1114             if let Ok(cxx) = self.cxx(target) {
1115                 let cxx = ccacheify(&cxx);
1116                 cargo
1117                     .env(format!("CXX_{}", target), &cxx)
1118                     .env(format!("CXXFLAGS_{}", target), cflags);
1119             }
1120         }
1121
1122         if (cmd == "build" || cmd == "rustc")
1123             && mode == Mode::Std
1124             && self.config.extended
1125             && compiler.is_final_stage(self)
1126         {
1127             cargo.env("RUSTC_SAVE_ANALYSIS", "api".to_string());
1128         }
1129
1130         // For `cargo doc` invocations, make rustdoc print the Rust version into the docs
1131         cargo.env("RUSTDOC_CRATE_VERSION", self.rust_version());
1132
1133         // Environment variables *required* throughout the build
1134         //
1135         // FIXME: should update code to not require this env var
1136         cargo.env("CFG_COMPILER_HOST_TRIPLE", target);
1137
1138         // Set this for all builds to make sure doc builds also get it.
1139         cargo.env("CFG_RELEASE_CHANNEL", &self.config.channel);
1140
1141         // This one's a bit tricky. As of the time of this writing the compiler
1142         // links to the `winapi` crate on crates.io. This crate provides raw
1143         // bindings to Windows system functions, sort of like libc does for
1144         // Unix. This crate also, however, provides "import libraries" for the
1145         // MinGW targets. There's an import library per dll in the windows
1146         // distribution which is what's linked to. These custom import libraries
1147         // are used because the winapi crate can reference Windows functions not
1148         // present in the MinGW import libraries.
1149         //
1150         // For example MinGW may ship libdbghelp.a, but it may not have
1151         // references to all the functions in the dbghelp dll. Instead the
1152         // custom import library for dbghelp in the winapi crates has all this
1153         // information.
1154         //
1155         // Unfortunately for us though the import libraries are linked by
1156         // default via `-ldylib=winapi_foo`. That is, they're linked with the
1157         // `dylib` type with a `winapi_` prefix (so the winapi ones don't
1158         // conflict with the system MinGW ones). This consequently means that
1159         // the binaries we ship of things like rustc_codegen_llvm (aka the rustc_codegen_llvm
1160         // DLL) when linked against *again*, for example with procedural macros
1161         // or plugins, will trigger the propagation logic of `-ldylib`, passing
1162         // `-lwinapi_foo` to the linker again. This isn't actually available in
1163         // our distribution, however, so the link fails.
1164         //
1165         // To solve this problem we tell winapi to not use its bundled import
1166         // libraries. This means that it will link to the system MinGW import
1167         // libraries by default, and the `-ldylib=foo` directives will still get
1168         // passed to the final linker, but they'll look like `-lfoo` which can
1169         // be resolved because MinGW has the import library. The downside is we
1170         // don't get newer functions from Windows, but we don't use any of them
1171         // anyway.
1172         if !mode.is_tool() {
1173             cargo.env("WINAPI_NO_BUNDLED_LIBRARIES", "1");
1174         }
1175
1176         for _ in 1..self.verbosity {
1177             cargo.arg("-v");
1178         }
1179
1180         match (mode, self.config.rust_codegen_units_std, self.config.rust_codegen_units) {
1181             (Mode::Std, Some(n), _) |
1182             (Mode::Test, Some(n), _) |
1183             (_, _, Some(n)) => {
1184                 cargo.env("RUSTC_CODEGEN_UNITS", n.to_string());
1185             }
1186             _ => {
1187                 // Don't set anything
1188             }
1189         }
1190
1191         if self.config.rust_optimize {
1192             // FIXME: cargo bench/install do not accept `--release`
1193             if cmd != "bench" && cmd != "install" {
1194                 cargo.arg("--release");
1195             }
1196         }
1197
1198         if self.config.locked_deps {
1199             cargo.arg("--locked");
1200         }
1201         if self.config.vendor || self.is_sudo {
1202             cargo.arg("--frozen");
1203         }
1204
1205         self.ci_env.force_coloring_in_ci(&mut cargo);
1206
1207         cargo
1208     }
1209
1210     /// Ensure that a given step is built, returning its output. This will
1211     /// cache the step, so it is safe (and good!) to call this as often as
1212     /// needed to ensure that all dependencies are built.
1213     pub fn ensure<S: Step>(&'a self, step: S) -> S::Output {
1214         {
1215             let mut stack = self.stack.borrow_mut();
1216             for stack_step in stack.iter() {
1217                 // should skip
1218                 if stack_step
1219                     .downcast_ref::<S>()
1220                     .map_or(true, |stack_step| *stack_step != step)
1221                 {
1222                     continue;
1223                 }
1224                 let mut out = String::new();
1225                 out += &format!("\n\nCycle in build detected when adding {:?}\n", step);
1226                 for el in stack.iter().rev() {
1227                     out += &format!("\t{:?}\n", el);
1228                 }
1229                 panic!(out);
1230             }
1231             if let Some(out) = self.cache.get(&step) {
1232                 self.verbose(&format!("{}c {:?}", "  ".repeat(stack.len()), step));
1233
1234                 {
1235                     let mut graph = self.graph.borrow_mut();
1236                     let parent = self.parent.get();
1237                     let us = *self
1238                         .graph_nodes
1239                         .borrow_mut()
1240                         .entry(format!("{:?}", step))
1241                         .or_insert_with(|| graph.add_node(format!("{:?}", step)));
1242                     if let Some(parent) = parent {
1243                         graph.add_edge(parent, us, false);
1244                     }
1245                 }
1246
1247                 return out;
1248             }
1249             self.verbose(&format!("{}> {:?}", "  ".repeat(stack.len()), step));
1250             stack.push(Box::new(step.clone()));
1251         }
1252
1253         let prev_parent = self.parent.get();
1254
1255         {
1256             let mut graph = self.graph.borrow_mut();
1257             let parent = self.parent.get();
1258             let us = *self
1259                 .graph_nodes
1260                 .borrow_mut()
1261                 .entry(format!("{:?}", step))
1262                 .or_insert_with(|| graph.add_node(format!("{:?}", step)));
1263             self.parent.set(Some(us));
1264             if let Some(parent) = parent {
1265                 graph.add_edge(parent, us, true);
1266             }
1267         }
1268
1269         let (out, dur) = {
1270             let start = Instant::now();
1271             let zero = Duration::new(0, 0);
1272             let parent = self.time_spent_on_dependencies.replace(zero);
1273             let out = step.clone().run(self);
1274             let dur = start.elapsed();
1275             let deps = self.time_spent_on_dependencies.replace(parent + dur);
1276             (out, dur - deps)
1277         };
1278
1279         self.parent.set(prev_parent);
1280
1281         if self.config.print_step_timings && dur > Duration::from_millis(100) {
1282             println!(
1283                 "[TIMING] {:?} -- {}.{:03}",
1284                 step,
1285                 dur.as_secs(),
1286                 dur.subsec_nanos() / 1_000_000
1287             );
1288         }
1289
1290         {
1291             let mut stack = self.stack.borrow_mut();
1292             let cur_step = stack.pop().expect("step stack empty");
1293             assert_eq!(cur_step.downcast_ref(), Some(&step));
1294         }
1295         self.verbose(&format!(
1296             "{}< {:?}",
1297             "  ".repeat(self.stack.borrow().len()),
1298             step
1299         ));
1300         self.cache.put(step, out.clone());
1301         out
1302     }
1303 }
1304
1305 #[cfg(test)]
1306 mod __test {
1307     use super::*;
1308     use crate::config::Config;
1309     use std::thread;
1310
1311     fn configure(host: &[&str], target: &[&str]) -> Config {
1312         let mut config = Config::default_opts();
1313         // don't save toolstates
1314         config.save_toolstates = None;
1315         config.run_host_only = true;
1316         config.dry_run = true;
1317         // try to avoid spurious failures in dist where we create/delete each others file
1318         let dir = config.out.join("tmp-rustbuild-tests").join(
1319             &thread::current()
1320                 .name()
1321                 .unwrap_or("unknown")
1322                 .replace(":", "-"),
1323         );
1324         t!(fs::create_dir_all(&dir));
1325         config.out = dir;
1326         config.build = INTERNER.intern_str("A");
1327         config.hosts = vec![config.build]
1328             .clone()
1329             .into_iter()
1330             .chain(host.iter().map(|s| INTERNER.intern_str(s)))
1331             .collect::<Vec<_>>();
1332         config.targets = config
1333             .hosts
1334             .clone()
1335             .into_iter()
1336             .chain(target.iter().map(|s| INTERNER.intern_str(s)))
1337             .collect::<Vec<_>>();
1338         config
1339     }
1340
1341     fn first<A, B>(v: Vec<(A, B)>) -> Vec<A> {
1342         v.into_iter().map(|(a, _)| a).collect::<Vec<_>>()
1343     }
1344
1345     #[test]
1346     fn dist_baseline() {
1347         let build = Build::new(configure(&[], &[]));
1348         let mut builder = Builder::new(&build);
1349         builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]);
1350
1351         let a = INTERNER.intern_str("A");
1352
1353         assert_eq!(
1354             first(builder.cache.all::<dist::Docs>()),
1355             &[dist::Docs { stage: 2, host: a },]
1356         );
1357         assert_eq!(
1358             first(builder.cache.all::<dist::Mingw>()),
1359             &[dist::Mingw { host: a },]
1360         );
1361         assert_eq!(
1362             first(builder.cache.all::<dist::Rustc>()),
1363             &[dist::Rustc {
1364                 compiler: Compiler { host: a, stage: 2 }
1365             },]
1366         );
1367         assert_eq!(
1368             first(builder.cache.all::<dist::Std>()),
1369             &[dist::Std {
1370                 compiler: Compiler { host: a, stage: 2 },
1371                 target: a,
1372             },]
1373         );
1374         assert_eq!(first(builder.cache.all::<dist::Src>()), &[dist::Src]);
1375     }
1376
1377     #[test]
1378     fn dist_with_targets() {
1379         let build = Build::new(configure(&[], &["B"]));
1380         let mut builder = Builder::new(&build);
1381         builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]);
1382
1383         let a = INTERNER.intern_str("A");
1384         let b = INTERNER.intern_str("B");
1385
1386         assert_eq!(
1387             first(builder.cache.all::<dist::Docs>()),
1388             &[
1389                 dist::Docs { stage: 2, host: a },
1390                 dist::Docs { stage: 2, host: b },
1391             ]
1392         );
1393         assert_eq!(
1394             first(builder.cache.all::<dist::Mingw>()),
1395             &[dist::Mingw { host: a }, dist::Mingw { host: b },]
1396         );
1397         assert_eq!(
1398             first(builder.cache.all::<dist::Rustc>()),
1399             &[dist::Rustc {
1400                 compiler: Compiler { host: a, stage: 2 }
1401             },]
1402         );
1403         assert_eq!(
1404             first(builder.cache.all::<dist::Std>()),
1405             &[
1406                 dist::Std {
1407                     compiler: Compiler { host: a, stage: 2 },
1408                     target: a,
1409                 },
1410                 dist::Std {
1411                     compiler: Compiler { host: a, stage: 2 },
1412                     target: b,
1413                 },
1414             ]
1415         );
1416         assert_eq!(first(builder.cache.all::<dist::Src>()), &[dist::Src]);
1417     }
1418
1419     #[test]
1420     fn dist_with_hosts() {
1421         let build = Build::new(configure(&["B"], &[]));
1422         let mut builder = Builder::new(&build);
1423         builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]);
1424
1425         let a = INTERNER.intern_str("A");
1426         let b = INTERNER.intern_str("B");
1427
1428         assert_eq!(
1429             first(builder.cache.all::<dist::Docs>()),
1430             &[
1431                 dist::Docs { stage: 2, host: a },
1432                 dist::Docs { stage: 2, host: b },
1433             ]
1434         );
1435         assert_eq!(
1436             first(builder.cache.all::<dist::Mingw>()),
1437             &[dist::Mingw { host: a }, dist::Mingw { host: b },]
1438         );
1439         assert_eq!(
1440             first(builder.cache.all::<dist::Rustc>()),
1441             &[
1442                 dist::Rustc {
1443                     compiler: Compiler { host: a, stage: 2 }
1444                 },
1445                 dist::Rustc {
1446                     compiler: Compiler { host: b, stage: 2 }
1447                 },
1448             ]
1449         );
1450         assert_eq!(
1451             first(builder.cache.all::<dist::Std>()),
1452             &[
1453                 dist::Std {
1454                     compiler: Compiler { host: a, stage: 2 },
1455                     target: a,
1456                 },
1457                 dist::Std {
1458                     compiler: Compiler { host: a, stage: 2 },
1459                     target: b,
1460                 },
1461             ]
1462         );
1463         assert_eq!(first(builder.cache.all::<dist::Src>()), &[dist::Src]);
1464     }
1465
1466     #[test]
1467     fn dist_with_targets_and_hosts() {
1468         let build = Build::new(configure(&["B"], &["C"]));
1469         let mut builder = Builder::new(&build);
1470         builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]);
1471
1472         let a = INTERNER.intern_str("A");
1473         let b = INTERNER.intern_str("B");
1474         let c = INTERNER.intern_str("C");
1475
1476         assert_eq!(
1477             first(builder.cache.all::<dist::Docs>()),
1478             &[
1479                 dist::Docs { stage: 2, host: a },
1480                 dist::Docs { stage: 2, host: b },
1481                 dist::Docs { stage: 2, host: c },
1482             ]
1483         );
1484         assert_eq!(
1485             first(builder.cache.all::<dist::Mingw>()),
1486             &[
1487                 dist::Mingw { host: a },
1488                 dist::Mingw { host: b },
1489                 dist::Mingw { host: c },
1490             ]
1491         );
1492         assert_eq!(
1493             first(builder.cache.all::<dist::Rustc>()),
1494             &[
1495                 dist::Rustc {
1496                     compiler: Compiler { host: a, stage: 2 }
1497                 },
1498                 dist::Rustc {
1499                     compiler: Compiler { host: b, stage: 2 }
1500                 },
1501             ]
1502         );
1503         assert_eq!(
1504             first(builder.cache.all::<dist::Std>()),
1505             &[
1506                 dist::Std {
1507                     compiler: Compiler { host: a, stage: 2 },
1508                     target: a,
1509                 },
1510                 dist::Std {
1511                     compiler: Compiler { host: a, stage: 2 },
1512                     target: b,
1513                 },
1514                 dist::Std {
1515                     compiler: Compiler { host: a, stage: 2 },
1516                     target: c,
1517                 },
1518             ]
1519         );
1520         assert_eq!(first(builder.cache.all::<dist::Src>()), &[dist::Src]);
1521     }
1522
1523     #[test]
1524     fn dist_with_target_flag() {
1525         let mut config = configure(&["B"], &["C"]);
1526         config.run_host_only = false; // as-if --target=C was passed
1527         let build = Build::new(config);
1528         let mut builder = Builder::new(&build);
1529         builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]);
1530
1531         let a = INTERNER.intern_str("A");
1532         let b = INTERNER.intern_str("B");
1533         let c = INTERNER.intern_str("C");
1534
1535         assert_eq!(
1536             first(builder.cache.all::<dist::Docs>()),
1537             &[
1538                 dist::Docs { stage: 2, host: a },
1539                 dist::Docs { stage: 2, host: b },
1540                 dist::Docs { stage: 2, host: c },
1541             ]
1542         );
1543         assert_eq!(
1544             first(builder.cache.all::<dist::Mingw>()),
1545             &[
1546                 dist::Mingw { host: a },
1547                 dist::Mingw { host: b },
1548                 dist::Mingw { host: c },
1549             ]
1550         );
1551         assert_eq!(first(builder.cache.all::<dist::Rustc>()), &[]);
1552         assert_eq!(
1553             first(builder.cache.all::<dist::Std>()),
1554             &[
1555                 dist::Std {
1556                     compiler: Compiler { host: a, stage: 2 },
1557                     target: a,
1558                 },
1559                 dist::Std {
1560                     compiler: Compiler { host: a, stage: 2 },
1561                     target: b,
1562                 },
1563                 dist::Std {
1564                     compiler: Compiler { host: a, stage: 2 },
1565                     target: c,
1566                 },
1567             ]
1568         );
1569         assert_eq!(first(builder.cache.all::<dist::Src>()), &[]);
1570     }
1571
1572     #[test]
1573     fn dist_with_same_targets_and_hosts() {
1574         let build = Build::new(configure(&["B"], &["B"]));
1575         let mut builder = Builder::new(&build);
1576         builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]);
1577
1578         let a = INTERNER.intern_str("A");
1579         let b = INTERNER.intern_str("B");
1580
1581         assert_eq!(
1582             first(builder.cache.all::<dist::Docs>()),
1583             &[
1584                 dist::Docs { stage: 2, host: a },
1585                 dist::Docs { stage: 2, host: b },
1586             ]
1587         );
1588         assert_eq!(
1589             first(builder.cache.all::<dist::Mingw>()),
1590             &[dist::Mingw { host: a }, dist::Mingw { host: b },]
1591         );
1592         assert_eq!(
1593             first(builder.cache.all::<dist::Rustc>()),
1594             &[
1595                 dist::Rustc {
1596                     compiler: Compiler { host: a, stage: 2 }
1597                 },
1598                 dist::Rustc {
1599                     compiler: Compiler { host: b, stage: 2 }
1600                 },
1601             ]
1602         );
1603         assert_eq!(
1604             first(builder.cache.all::<dist::Std>()),
1605             &[
1606                 dist::Std {
1607                     compiler: Compiler { host: a, stage: 2 },
1608                     target: a,
1609                 },
1610                 dist::Std {
1611                     compiler: Compiler { host: a, stage: 2 },
1612                     target: b,
1613                 },
1614             ]
1615         );
1616         assert_eq!(first(builder.cache.all::<dist::Src>()), &[dist::Src]);
1617         assert_eq!(
1618             first(builder.cache.all::<compile::Std>()),
1619             &[
1620                 compile::Std {
1621                     compiler: Compiler { host: a, stage: 0 },
1622                     target: a,
1623                 },
1624                 compile::Std {
1625                     compiler: Compiler { host: a, stage: 1 },
1626                     target: a,
1627                 },
1628                 compile::Std {
1629                     compiler: Compiler { host: a, stage: 2 },
1630                     target: a,
1631                 },
1632                 compile::Std {
1633                     compiler: Compiler { host: a, stage: 1 },
1634                     target: b,
1635                 },
1636                 compile::Std {
1637                     compiler: Compiler { host: a, stage: 2 },
1638                     target: b,
1639                 },
1640             ]
1641         );
1642         assert_eq!(
1643             first(builder.cache.all::<compile::Test>()),
1644             &[
1645                 compile::Test {
1646                     compiler: Compiler { host: a, stage: 0 },
1647                     target: a,
1648                 },
1649                 compile::Test {
1650                     compiler: Compiler { host: a, stage: 1 },
1651                     target: a,
1652                 },
1653                 compile::Test {
1654                     compiler: Compiler { host: a, stage: 2 },
1655                     target: a,
1656                 },
1657                 compile::Test {
1658                     compiler: Compiler { host: a, stage: 1 },
1659                     target: b,
1660                 },
1661                 compile::Test {
1662                     compiler: Compiler { host: a, stage: 2 },
1663                     target: b,
1664                 },
1665             ]
1666         );
1667         assert_eq!(
1668             first(builder.cache.all::<compile::Assemble>()),
1669             &[
1670                 compile::Assemble {
1671                     target_compiler: Compiler { host: a, stage: 0 },
1672                 },
1673                 compile::Assemble {
1674                     target_compiler: Compiler { host: a, stage: 1 },
1675                 },
1676                 compile::Assemble {
1677                     target_compiler: Compiler { host: a, stage: 2 },
1678                 },
1679                 compile::Assemble {
1680                     target_compiler: Compiler { host: b, stage: 2 },
1681                 },
1682             ]
1683         );
1684     }
1685
1686     #[test]
1687     fn build_default() {
1688         let build = Build::new(configure(&["B"], &["C"]));
1689         let mut builder = Builder::new(&build);
1690         builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Build), &[]);
1691
1692         let a = INTERNER.intern_str("A");
1693         let b = INTERNER.intern_str("B");
1694         let c = INTERNER.intern_str("C");
1695
1696         assert!(!builder.cache.all::<compile::Std>().is_empty());
1697         assert!(!builder.cache.all::<compile::Assemble>().is_empty());
1698         assert_eq!(
1699             first(builder.cache.all::<compile::Rustc>()),
1700             &[
1701                 compile::Rustc {
1702                     compiler: Compiler { host: a, stage: 0 },
1703                     target: a,
1704                 },
1705                 compile::Rustc {
1706                     compiler: Compiler { host: a, stage: 1 },
1707                     target: a,
1708                 },
1709                 compile::Rustc {
1710                     compiler: Compiler { host: a, stage: 2 },
1711                     target: a,
1712                 },
1713                 compile::Rustc {
1714                     compiler: Compiler { host: b, stage: 2 },
1715                     target: a,
1716                 },
1717                 compile::Rustc {
1718                     compiler: Compiler { host: a, stage: 0 },
1719                     target: b,
1720                 },
1721                 compile::Rustc {
1722                     compiler: Compiler { host: a, stage: 1 },
1723                     target: b,
1724                 },
1725                 compile::Rustc {
1726                     compiler: Compiler { host: a, stage: 2 },
1727                     target: b,
1728                 },
1729                 compile::Rustc {
1730                     compiler: Compiler { host: b, stage: 2 },
1731                     target: b,
1732                 },
1733             ]
1734         );
1735
1736         assert_eq!(
1737             first(builder.cache.all::<compile::Test>()),
1738             &[
1739                 compile::Test {
1740                     compiler: Compiler { host: a, stage: 0 },
1741                     target: a,
1742                 },
1743                 compile::Test {
1744                     compiler: Compiler { host: a, stage: 1 },
1745                     target: a,
1746                 },
1747                 compile::Test {
1748                     compiler: Compiler { host: a, stage: 2 },
1749                     target: a,
1750                 },
1751                 compile::Test {
1752                     compiler: Compiler { host: b, stage: 2 },
1753                     target: a,
1754                 },
1755                 compile::Test {
1756                     compiler: Compiler { host: a, stage: 0 },
1757                     target: b,
1758                 },
1759                 compile::Test {
1760                     compiler: Compiler { host: a, stage: 1 },
1761                     target: b,
1762                 },
1763                 compile::Test {
1764                     compiler: Compiler { host: a, stage: 2 },
1765                     target: b,
1766                 },
1767                 compile::Test {
1768                     compiler: Compiler { host: b, stage: 2 },
1769                     target: b,
1770                 },
1771                 compile::Test {
1772                     compiler: Compiler { host: a, stage: 2 },
1773                     target: c,
1774                 },
1775                 compile::Test {
1776                     compiler: Compiler { host: b, stage: 2 },
1777                     target: c,
1778                 },
1779             ]
1780         );
1781     }
1782
1783     #[test]
1784     fn build_with_target_flag() {
1785         let mut config = configure(&["B"], &["C"]);
1786         config.run_host_only = false;
1787         let build = Build::new(config);
1788         let mut builder = Builder::new(&build);
1789         builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Build), &[]);
1790
1791         let a = INTERNER.intern_str("A");
1792         let b = INTERNER.intern_str("B");
1793         let c = INTERNER.intern_str("C");
1794
1795         assert!(!builder.cache.all::<compile::Std>().is_empty());
1796         assert_eq!(
1797             first(builder.cache.all::<compile::Assemble>()),
1798             &[
1799                 compile::Assemble {
1800                     target_compiler: Compiler { host: a, stage: 0 },
1801                 },
1802                 compile::Assemble {
1803                     target_compiler: Compiler { host: a, stage: 1 },
1804                 },
1805                 compile::Assemble {
1806                     target_compiler: Compiler { host: b, stage: 1 },
1807                 },
1808                 compile::Assemble {
1809                     target_compiler: Compiler { host: a, stage: 2 },
1810                 },
1811                 compile::Assemble {
1812                     target_compiler: Compiler { host: b, stage: 2 },
1813                 },
1814             ]
1815         );
1816         assert_eq!(
1817             first(builder.cache.all::<compile::Rustc>()),
1818             &[
1819                 compile::Rustc {
1820                     compiler: Compiler { host: a, stage: 0 },
1821                     target: a,
1822                 },
1823                 compile::Rustc {
1824                     compiler: Compiler { host: a, stage: 1 },
1825                     target: a,
1826                 },
1827                 compile::Rustc {
1828                     compiler: Compiler { host: a, stage: 0 },
1829                     target: b,
1830                 },
1831                 compile::Rustc {
1832                     compiler: Compiler { host: a, stage: 1 },
1833                     target: b,
1834                 },
1835             ]
1836         );
1837
1838         assert_eq!(
1839             first(builder.cache.all::<compile::Test>()),
1840             &[
1841                 compile::Test {
1842                     compiler: Compiler { host: a, stage: 0 },
1843                     target: a,
1844                 },
1845                 compile::Test {
1846                     compiler: Compiler { host: a, stage: 1 },
1847                     target: a,
1848                 },
1849                 compile::Test {
1850                     compiler: Compiler { host: a, stage: 2 },
1851                     target: a,
1852                 },
1853                 compile::Test {
1854                     compiler: Compiler { host: b, stage: 2 },
1855                     target: a,
1856                 },
1857                 compile::Test {
1858                     compiler: Compiler { host: a, stage: 0 },
1859                     target: b,
1860                 },
1861                 compile::Test {
1862                     compiler: Compiler { host: a, stage: 1 },
1863                     target: b,
1864                 },
1865                 compile::Test {
1866                     compiler: Compiler { host: a, stage: 2 },
1867                     target: b,
1868                 },
1869                 compile::Test {
1870                     compiler: Compiler { host: b, stage: 2 },
1871                     target: b,
1872                 },
1873                 compile::Test {
1874                     compiler: Compiler { host: a, stage: 2 },
1875                     target: c,
1876                 },
1877                 compile::Test {
1878                     compiler: Compiler { host: b, stage: 2 },
1879                     target: c,
1880                 },
1881             ]
1882         );
1883     }
1884
1885     #[test]
1886     fn test_with_no_doc_stage0() {
1887         let mut config = configure(&[], &[]);
1888         config.stage = Some(0);
1889         config.cmd = Subcommand::Test {
1890             paths: vec!["src/libstd".into()],
1891             test_args: vec![],
1892             rustc_args: vec![],
1893             fail_fast: true,
1894             doc_tests: DocTests::No,
1895             bless: false,
1896             compare_mode: None,
1897             rustfix_coverage: false,
1898         };
1899
1900         let build = Build::new(config);
1901         let mut builder = Builder::new(&build);
1902
1903         let host = INTERNER.intern_str("A");
1904
1905         builder.run_step_descriptions(
1906             &[StepDescription::from::<test::Crate>()],
1907             &["src/libstd".into()],
1908         );
1909
1910         // Ensure we don't build any compiler artifacts.
1911         assert!(!builder.cache.contains::<compile::Rustc>());
1912         assert_eq!(
1913             first(builder.cache.all::<test::Crate>()),
1914             &[test::Crate {
1915                 compiler: Compiler { host, stage: 0 },
1916                 target: host,
1917                 mode: Mode::Std,
1918                 test_kind: test::TestKind::Test,
1919                 krate: INTERNER.intern_str("std"),
1920             },]
1921         );
1922     }
1923
1924     #[test]
1925     fn test_exclude() {
1926         let mut config = configure(&[], &[]);
1927         config.exclude = vec![
1928             "src/test/run-pass".into(),
1929             "src/tools/tidy".into(),
1930         ];
1931         config.cmd = Subcommand::Test {
1932             paths: Vec::new(),
1933             test_args: Vec::new(),
1934             rustc_args: Vec::new(),
1935             fail_fast: true,
1936             doc_tests: DocTests::No,
1937             bless: false,
1938             compare_mode: None,
1939             rustfix_coverage: false,
1940         };
1941
1942         let build = Build::new(config);
1943         let builder = Builder::new(&build);
1944         builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Test), &[]);
1945
1946         // Ensure we have really excluded run-pass & tidy
1947         assert!(!builder.cache.contains::<test::RunPass>());
1948         assert!(!builder.cache.contains::<test::Tidy>());
1949
1950         // Ensure other tests are not affected.
1951         assert!(builder.cache.contains::<test::RunPassFullDeps>());
1952         assert!(builder.cache.contains::<test::RustdocUi>());
1953     }
1954 }