summaryrefslogtreecommitdiffstats
path: root/src/bootstrap/builder.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/bootstrap/builder.rs')
-rw-r--r--src/bootstrap/builder.rs122
1 files changed, 54 insertions, 68 deletions
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 2fa445506..05b66f947 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -8,7 +8,7 @@ use std::fs::{self, File};
use std::hash::Hash;
use std::io::{BufRead, BufReader};
use std::ops::Deref;
-use std::path::{Component, Path, PathBuf};
+use std::path::{Path, PathBuf};
use std::process::Command;
use std::time::{Duration, Instant};
@@ -103,11 +103,14 @@ impl RunConfig<'_> {
}
/// Return a list of crate names selected by `run.paths`.
+ #[track_caller]
pub fn cargo_crates_in_set(&self) -> Interned<Vec<String>> {
let mut crates = Vec::new();
for krate in &self.paths {
let path = krate.assert_single_path();
- let crate_name = self.builder.crate_paths[&path.path];
+ let Some(crate_name) = self.builder.crate_paths.get(&path.path) else {
+ panic!("missing crate for path {}", path.path.display())
+ };
crates.push(crate_name.to_string());
}
INTERNER.intern_list(crates)
@@ -147,29 +150,6 @@ pub struct TaskPath {
pub kind: Option<Kind>,
}
-impl TaskPath {
- pub fn parse(path: impl Into<PathBuf>) -> TaskPath {
- let mut kind = None;
- let mut path = path.into();
-
- let mut components = path.components();
- if let Some(Component::Normal(os_str)) = components.next() {
- if let Some(str) = os_str.to_str() {
- if let Some((found_kind, found_prefix)) = str.split_once("::") {
- if found_kind.is_empty() {
- panic!("empty kind in task path {}", path.display());
- }
- kind = Kind::parse(found_kind);
- assert!(kind.is_some());
- path = Path::new(found_prefix).join(components.as_path());
- }
- }
- }
-
- TaskPath { path, kind }
- }
-}
-
impl Debug for TaskPath {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if let Some(kind) = &self.kind {
@@ -213,7 +193,7 @@ impl PathSet {
PathSet::Set(set)
}
- fn has(&self, needle: &Path, module: Option<Kind>) -> bool {
+ fn has(&self, needle: &Path, module: Kind) -> bool {
match self {
PathSet::Set(set) => set.iter().any(|p| Self::check(p, needle, module)),
PathSet::Suite(suite) => Self::check(suite, needle, module),
@@ -221,9 +201,9 @@ impl PathSet {
}
// internal use only
- fn check(p: &TaskPath, needle: &Path, module: Option<Kind>) -> bool {
- if let (Some(p_kind), Some(kind)) = (&p.kind, module) {
- p.path.ends_with(needle) && *p_kind == kind
+ fn check(p: &TaskPath, needle: &Path, module: Kind) -> bool {
+ if let Some(p_kind) = &p.kind {
+ p.path.ends_with(needle) && *p_kind == module
} else {
p.path.ends_with(needle)
}
@@ -235,11 +215,7 @@ impl PathSet {
/// 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(
- &self,
- needles: &mut Vec<&Path>,
- module: Option<Kind>,
- ) -> PathSet {
+ fn intersection_removing_matches(&self, needles: &mut Vec<&Path>, module: Kind) -> PathSet {
let mut check = |p| {
for (i, n) in needles.iter().enumerate() {
let matched = Self::check(p, n, module);
@@ -304,7 +280,7 @@ impl StepDescription {
}
fn is_excluded(&self, builder: &Builder<'_>, pathset: &PathSet) -> bool {
- if builder.config.exclude.iter().any(|e| pathset.has(&e.path, e.kind)) {
+ if builder.config.exclude.iter().any(|e| pathset.has(&e, builder.kind)) {
println!("Skipping {:?} because it is excluded", pathset);
return true;
}
@@ -378,7 +354,7 @@ impl StepDescription {
eprintln!(
"note: if you are adding a new Step to bootstrap itself, make sure you register it with `describe!`"
);
- crate::detail_exit(1);
+ crate::detail_exit_macro!(1);
}
}
}
@@ -430,25 +406,6 @@ impl<'a> ShouldRun<'a> {
/// Indicates it should run if the command-line selects the given crate or
/// any of its (local) dependencies.
///
- /// Compared to `krate`, this treats the dependencies as aliases for the
- /// same job. Generally it is preferred to use `krate`, and treat each
- /// individual path separately. For example `./x.py test src/liballoc`
- /// (which uses `krate`) will test just `liballoc`. However, `./x.py check
- /// src/liballoc` (which uses `all_krates`) will check all of `libtest`.
- /// `all_krates` should probably be removed at some point.
- pub fn all_krates(mut self, name: &str) -> Self {
- let mut set = BTreeSet::new();
- for krate in self.builder.in_tree_crates(name, None) {
- let path = krate.local_path(self.builder);
- set.insert(TaskPath { path, kind: Some(self.kind) });
- }
- self.paths.insert(PathSet::Set(set));
- self
- }
-
- /// Indicates it should run if the 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);
@@ -458,6 +415,8 @@ impl<'a> ShouldRun<'a> {
/// Indicates it should run if the command-line selects any of the given crates.
///
/// `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 {
for krate in crates {
let path = krate.local_path(self.builder);
@@ -487,7 +446,15 @@ impl<'a> ShouldRun<'a> {
self.paths(&[path])
}
- // multiple aliases for the same job
+ /// Multiple aliases for the same job.
+ ///
+ /// This differs from [`path`] in that multiple calls to path will end up calling `make_run`
+ /// multiple times, whereas a single call to `paths` will only ever generate a single call to
+ /// `paths`.
+ ///
+ /// This is analogous to `all_krates`, although `all_krates` is gone now. Prefer [`path`] where possible.
+ ///
+ /// [`path`]: ShouldRun::path
pub fn paths(mut self, paths: &[&str]) -> Self {
static SUBMODULES_PATHS: OnceCell<Vec<String>> = OnceCell::new();
@@ -568,7 +535,7 @@ impl<'a> ShouldRun<'a> {
) -> Vec<PathSet> {
let mut sets = vec![];
for pathset in &self.paths {
- let subset = pathset.intersection_removing_matches(paths, Some(kind));
+ let subset = pathset.intersection_removing_matches(paths, kind);
if subset != PathSet::empty() {
sets.push(subset);
}
@@ -577,7 +544,7 @@ impl<'a> ShouldRun<'a> {
}
}
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, ValueEnum)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum)]
pub enum Kind {
#[clap(alias = "b")]
Build,
@@ -641,12 +608,19 @@ impl Kind {
}
}
- pub fn test_description(&self) -> &'static str {
+ pub fn description(&self) -> String {
match self {
Kind::Test => "Testing",
Kind::Bench => "Benchmarking",
- _ => panic!("not a test command: {}!", self.as_str()),
+ Kind::Doc => "Documenting",
+ Kind::Run => "Running",
+ Kind::Suggest => "Suggesting",
+ _ => {
+ let title_letter = self.as_str()[0..1].to_ascii_uppercase();
+ return format!("{title_letter}{}ing", &self.as_str()[1..]);
+ }
}
+ .to_owned()
}
}
@@ -702,8 +676,8 @@ impl<'a> Builder<'a> {
check::CargoMiri,
check::MiroptTestTools,
check::Rls,
- check::RustAnalyzer,
check::Rustfmt,
+ check::RustAnalyzer,
check::Bootstrap
),
Kind::Test => describe!(
@@ -712,6 +686,7 @@ impl<'a> Builder<'a> {
test::Tidy,
test::Ui,
test::RunPassValgrind,
+ test::RunCoverage,
test::MirOpt,
test::Codegen,
test::CodegenUnits,
@@ -720,6 +695,7 @@ impl<'a> Builder<'a> {
test::Debuginfo,
test::UiFullDeps,
test::Rustdoc,
+ test::RunCoverageRustdoc,
test::Pretty,
test::Crate,
test::CrateLibrustc,
@@ -994,7 +970,7 @@ impl<'a> Builder<'a> {
}
pub fn sysroot(&self, compiler: Compiler) -> Interned<PathBuf> {
- self.ensure(compile::Sysroot { compiler })
+ self.ensure(compile::Sysroot::new(compiler))
}
/// Returns the libdir where the standard library and other artifacts are
@@ -1231,7 +1207,7 @@ impl<'a> Builder<'a> {
assert_eq!(target, compiler.host);
}
- if self.config.rust_optimize {
+ if self.config.rust_optimize.is_release() {
// FIXME: cargo bench/install do not accept `--release`
if cmd != "bench" && cmd != "install" {
cargo.arg("--release");
@@ -1287,7 +1263,7 @@ impl<'a> Builder<'a> {
}
let profile_var = |name: &str| {
- let profile = if self.config.rust_optimize { "RELEASE" } else { "DEV" };
+ let profile = if self.config.rust_optimize.is_release() { "RELEASE" } else { "DEV" };
format!("CARGO_PROFILE_{}_{}", profile, name)
};
@@ -1357,7 +1333,7 @@ impl<'a> Builder<'a> {
"error: `x.py clippy` requires a host `rustc` toolchain with the `clippy` component"
);
eprintln!("help: try `rustup component add clippy`");
- crate::detail_exit(1);
+ crate::detail_exit_macro!(1);
});
if !t!(std::str::from_utf8(&output.stdout)).contains("nightly") {
rustflags.arg("--cfg=bootstrap");
@@ -1634,7 +1610,7 @@ impl<'a> Builder<'a> {
// flesh out rpath support more fully in the future.
rustflags.arg("-Zosx-rpath-install-name");
Some("-Wl,-rpath,@loader_path/../lib")
- } else if !target.contains("windows") {
+ } else if !target.contains("windows") && !target.contains("aix") {
rustflags.arg("-Clink-args=-Wl,-z,origin");
Some("-Wl,-rpath,$ORIGIN/../lib")
} else {
@@ -1676,6 +1652,13 @@ impl<'a> Builder<'a> {
}
};
cargo.env(profile_var("DEBUG"), debuginfo_level.to_string());
+ if let Some(opt_level) = &self.config.rust_optimize.get_opt_level() {
+ cargo.env(profile_var("OPT_LEVEL"), opt_level);
+ }
+ if !self.config.dry_run() && self.cc.borrow()[&target].args().iter().any(|arg| arg == "-gz")
+ {
+ rustflags.arg("-Clink-arg=-gz");
+ }
cargo.env(
profile_var("DEBUG_ASSERTIONS"),
if mode == Mode::Std {
@@ -1785,7 +1768,10 @@ impl<'a> Builder<'a> {
cargo.env("RUSTC_TLS_MODEL_INITIAL_EXEC", "1");
}
- if self.config.incremental {
+ // Ignore incremental modes except for stage0, since we're
+ // not guaranteeing correctness across builds if the compiler
+ // is changing under your feet.
+ if self.config.incremental && compiler.stage == 0 {
cargo.env("CARGO_INCREMENTAL", "1");
} else {
// Don't rely on any default setting for incr. comp. in Cargo
@@ -2126,7 +2112,7 @@ impl<'a> Builder<'a> {
let should_run = (desc.should_run)(ShouldRun::new(self, desc.kind));
for path in &self.paths {
- if should_run.paths.iter().any(|s| s.has(path, Some(desc.kind)))
+ if should_run.paths.iter().any(|s| s.has(path, desc.kind))
&& !desc.is_excluded(
self,
&PathSet::Suite(TaskPath { path: path.clone(), kind: Some(desc.kind) }),