Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add tools to sysroot after build. #102010

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 27 additions & 18 deletions src/bootstrap/builder.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::any::{type_name, Any};
use std::cell::{Cell, RefCell};
use std::collections::BTreeSet;
use std::collections::{BTreeSet, HashSet};
use std::env;
use std::ffi::{OsStr, OsString};
use std::fmt::{Debug, Write};
Expand Down Expand Up @@ -197,28 +197,29 @@ impl PathSet {
}
}

/// Return all `TaskPath`s in `Self` that contain any of the `needles`, removing the
/// matched needles.
/// Return all `TaskPath`s in `Self` that contain any of the `needles`, as well as the matched
/// needles.
///
/// This is used for `StepDescription::krate`, which passes all matching crates at once to
/// `Step::make_run`, rather than calling it many times with a single crate.
/// See `tests.rs` for examples.
fn intersection_removing_matches(
fn intersection_with_matches<'p>(
&self,
needles: &mut Vec<&Path>,
needles: &[&'p Path],
module: Option<Kind>,
) -> PathSet {
) -> (PathSet, Vec<&'p Path>) {
let mut matched_paths = vec![];
let mut check = |p| {
for (i, n) in needles.iter().enumerate() {
for n in needles {
let matched = Self::check(p, n, module);
if matched {
needles.remove(i);
matched_paths.push(*n);
return true;
}
}
false
};
match self {
let pathset = match self {
PathSet::Set(set) => PathSet::Set(set.iter().filter(|&p| check(p)).cloned().collect()),
PathSet::Suite(suite) => {
if check(suite) {
Expand All @@ -227,7 +228,8 @@ impl PathSet {
PathSet::empty()
}
}
}
};
(pathset, matched_paths)
}

/// A convenience wrapper for Steps which know they have no aliases and all their sets contain only a single path.
Expand Down Expand Up @@ -315,6 +317,7 @@ impl StepDescription {

// Handle all test suite paths.
// (This is separate from the loop below to avoid having to handle multiple paths in `is_suite_path` somehow.)
// Note that unlike below, we don't allow multiple suite paths to share the same path.
paths.retain(|path| {
for (desc, should_run) in v.iter().zip(&should_runs) {
if let Some(suite) = should_run.is_suite_path(&path) {
Expand All @@ -330,15 +333,19 @@ impl StepDescription {
}

// Handle all PathSets.
let mut seen_paths = HashSet::new();
for (desc, should_run) in v.iter().zip(&should_runs) {
let pathsets = should_run.pathset_for_paths_removing_matches(&mut paths, desc.kind);
let (pathsets, matched) = should_run.pathset_for_paths_with_matches(&paths, desc.kind);
if !pathsets.is_empty() {
seen_paths.extend(matched);
desc.maybe_run(builder, pathsets);
}
}

if !paths.is_empty() {
eprintln!("error: no `{}` rules matched {:?}", builder.kind.as_str(), paths,);
let cli_paths: HashSet<_> = paths.into_iter().collect();
let missing_paths: Vec<_> = cli_paths.difference(&seen_paths).collect();
if !missing_paths.is_empty() {
eprintln!("error: no `{}` rules matched {:?}", builder.kind.as_str(), missing_paths);
eprintln!(
"help: run `x.py {} --help --verbose` to show a list of available paths",
builder.kind.as_str()
Expand Down Expand Up @@ -500,19 +507,21 @@ impl<'a> ShouldRun<'a> {
///
/// The reason we return PathSet instead of PathBuf is to allow for aliases that mean the same thing
/// (for now, just `all_krates` and `paths`, but we may want to add an `aliases` function in the future?)
fn pathset_for_paths_removing_matches(
fn pathset_for_paths_with_matches<'p>(
&self,
paths: &mut Vec<&Path>,
paths: &[&'p Path],
kind: Kind,
) -> Vec<PathSet> {
) -> (Vec<PathSet>, HashSet<&'p Path>) {
let mut all_matched_paths = HashSet::new();
let mut sets = vec![];
for pathset in &self.paths {
let subset = pathset.intersection_removing_matches(paths, Some(kind));
let (subset, matched_paths) = pathset.intersection_with_matches(paths, Some(kind));
if subset != PathSet::empty() {
sets.push(subset);
all_matched_paths.extend(matched_paths);
}
}
sets
(sets, all_matched_paths)
}
}

Expand Down
6 changes: 3 additions & 3 deletions src/bootstrap/builder/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,14 +93,14 @@ fn test_intersection() {
let set = PathSet::Set(
["library/core", "library/alloc", "library/std"].into_iter().map(TaskPath::parse).collect(),
);
let mut command_paths =
let command_paths =
vec![Path::new("library/core"), Path::new("library/alloc"), Path::new("library/stdarch")];
let subset = set.intersection_removing_matches(&mut command_paths, None);
let (subset, matched_paths) = set.intersection_with_matches(&command_paths, None);
assert_eq!(
subset,
PathSet::Set(["library/core", "library/alloc"].into_iter().map(TaskPath::parse).collect())
);
assert_eq!(command_paths, vec![Path::new("library/stdarch")]);
assert_eq!(matched_paths, vec![Path::new("library/alloc"), Path::new("library/core")]);
}

#[test]
Expand Down
28 changes: 20 additions & 8 deletions src/bootstrap/tool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -796,6 +796,7 @@ macro_rules! tool_extended {
$tool_name:expr,
stable = $stable:expr
$(,tool_std = $tool_std:literal)?
$(,add_to_sysroot = $add_to_sysroot:literal)?
;)+) => {
$(
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
Expand Down Expand Up @@ -838,7 +839,7 @@ macro_rules! tool_extended {

#[allow(unused_mut)]
fn run(mut $sel, $builder: &Builder<'_>) -> Option<PathBuf> {
$builder.ensure(ToolBuild {
let tool = $builder.ensure(ToolBuild {
compiler: $sel.compiler,
target: $sel.target,
tool: $tool_name,
Expand All @@ -847,7 +848,18 @@ macro_rules! tool_extended {
extra_features: $sel.extra_features,
is_optional_tool: true,
source_type: SourceType::InTree,
})
})?;

if (false $(|| $add_to_sysroot)?) && $sel.compiler.stage > 0 {
let bin_dir = $builder.sysroot($sel.compiler).join("bin");
t!(fs::create_dir_all(&bin_dir));
let bin_tool = bin_dir.join(exe($tool_name, $sel.compiler.host));
let _ = fs::remove_file(&bin_tool);
$builder.copy(&tool, &bin_tool);
Some(bin_tool)
jyn514 marked this conversation as resolved.
Show resolved Hide resolved
} else {
Some(tool)
}
}
}
)+
Expand All @@ -859,17 +871,17 @@ macro_rules! tool_extended {
// Note: Most submodule updates for tools are handled by bootstrap.py, since they're needed just to
// invoke Cargo to build bootstrap. See the comment there for more details.
tool_extended!((self, builder),
Cargofmt, "src/tools/rustfmt", "cargo-fmt", stable=true;
CargoClippy, "src/tools/clippy", "cargo-clippy", stable=true;
Clippy, "src/tools/clippy", "clippy-driver", stable=true;
Miri, "src/tools/miri", "miri", stable=false;
CargoMiri, "src/tools/miri/cargo-miri", "cargo-miri", stable=true;
Cargofmt, "src/tools/rustfmt", "cargo-fmt", stable=true, add_to_sysroot=true;
CargoClippy, "src/tools/clippy", "cargo-clippy", stable=true, add_to_sysroot=true;
Clippy, "src/tools/clippy", "clippy-driver", stable=true, add_to_sysroot=true;
Miri, "src/tools/miri", "miri", stable=false, add_to_sysroot=true;
CargoMiri, "src/tools/miri/cargo-miri", "cargo-miri", stable=false, add_to_sysroot=true;
// FIXME: tool_std is not quite right, we shouldn't allow nightly features.
// But `builder.cargo` doesn't know how to handle ToolBootstrap in stages other than 0,
// and this is close enough for now.
Rls, "src/tools/rls", "rls", stable=true, tool_std=true;
RustDemangler, "src/tools/rust-demangler", "rust-demangler", stable=false, tool_std=true;
Rustfmt, "src/tools/rustfmt", "rustfmt", stable=true;
Rustfmt, "src/tools/rustfmt", "rustfmt", stable=true, add_to_sysroot=true;
);

impl<'a> Builder<'a> {
Expand Down