diff --git a/src/bootstrap/src/core/build_steps/clean.rs b/src/bootstrap/src/core/build_steps/clean.rs index 6dc03236053c7..fec4a79de3c75 100644 --- a/src/bootstrap/src/core/build_steps/clean.rs +++ b/src/bootstrap/src/core/build_steps/clean.rs @@ -58,8 +58,7 @@ macro_rules! clean_crate_tree { type Output = (); fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - let crates = run.builder.in_tree_crates($root_crate, None); - run.crates(crates) + run.crate_or_deps($root_crate) } fn make_run(run: RunConfig<'_>) { diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 4f96df6452d78..a1effa38387ca 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -1018,16 +1018,11 @@ impl Step for Rustc { const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - let mut crates = run.builder.in_tree_crates("rustc-main", None); - for (i, krate) in crates.iter().enumerate() { + run.crate_or_deps_filtered("rustc-main", |krate| { // We can't allow `build rustc` as an alias for this Step, because that's reserved by `Assemble`. // Ideally Assemble would use `build compiler` instead, but that seems too confusing to be worth the breaking change. - if krate.name == "rustc-main" { - crates.swap_remove(i); - break; - } - } - run.crates(crates) + krate.name != "rustc-main" + }) } fn is_default_step(_builder: &Builder<'_>) -> bool { diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs index 0d17f0f792a01..b21a2fe77d94f 100644 --- a/src/bootstrap/src/core/builder/mod.rs +++ b/src/bootstrap/src/core/builder/mod.rs @@ -524,22 +524,30 @@ impl<'a> ShouldRun<'a> { ShouldRun { builder, kind, paths: BTreeSet::new(), default_to_suites_only: false } } - /// Indicates it should run if the command-line selects the given crate or - /// any of its (local) dependencies. + /// The corresponding step should run if the bootstrap command-line selects + /// the given crate or any of its (local) dependencies. /// - /// `make_run` will be called a single time with all matching command-line paths. - pub fn crate_or_deps(self, name: &str) -> Self { - let crates = self.builder.in_tree_crates(name, None); - self.crates(crates) + /// Delegates to [`Self::crate_or_deps_filtered`] with a filter that accepts all crates. + pub(crate) fn crate_or_deps(self, root_crate_name: &str) -> Self { + self.crate_or_deps_filtered(root_crate_name, |_: &Crate| true) } - /// Indicates it should run if the command-line selects any of the given crates. + /// The corresponding step should run if the bootstrap command-line selects + /// the given crate or any of its (local) dependencies, not counting any + /// crates rejected by the given filter function. /// /// `make_run` will be called a single time with all matching command-line paths. - /// - /// Prefer [`ShouldRun::crate_or_deps`] to this function where possible. - pub(crate) fn crates(mut self, crates: Vec<&Crate>) -> Self { + pub(crate) fn crate_or_deps_filtered( + mut self, + root_crate_name: &str, + crate_filter_fn: impl Fn(&Crate) -> bool, + ) -> Self { + let crates = self.builder.in_tree_crates(root_crate_name, None); for krate in crates { + if !crate_filter_fn(krate) { + continue; + } + let path = krate.local_path(self.builder); self.paths.insert(PathSet::one(path, self.kind)); } diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index f7ffc682e2bd7..f08346789e7e8 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -1735,7 +1735,9 @@ impl Build { } } } - ret.sort_unstable_by_key(|krate| krate.name.clone()); // reproducible order needed for tests + + // Sort the crates so that bootstrap unit tests can assume a deterministic order. + ret.sort_unstable_by(|a, b| Ord::cmp(&a.name, &b.name)); ret }