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.rs218
1 files changed, 152 insertions, 66 deletions
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 8ee6d49da..b4fc1d4f2 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -13,17 +13,18 @@ use std::time::{Duration, Instant};
use crate::cache::{Cache, Interned, INTERNER};
use crate::config::{SplitDebuginfo, TargetSelection};
-use crate::dist;
use crate::doc;
use crate::flags::{Color, Subcommand};
use crate::install;
use crate::native;
use crate::run;
+use crate::setup;
use crate::test;
use crate::tool::{self, SourceType};
use crate::util::{self, add_dylib_path, add_link_lib_path, exe, libdir, output, t};
use crate::EXTRA_CHECK_CFGS;
use crate::{check, compile, Crate};
+use crate::{clean, dist};
use crate::{Build, CLang, DocTests, GitRepo, Mode};
pub use crate::Compiler;
@@ -95,6 +96,35 @@ impl RunConfig<'_> {
pub fn build_triple(&self) -> TargetSelection {
self.builder.build.build
}
+
+ /// Return a list of crate names selected by `run.paths`.
+ 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];
+ crates.push(crate_name.to_string());
+ }
+ INTERNER.intern_list(crates)
+ }
+}
+
+/// A description of the crates in this set, suitable for passing to `builder.info`.
+///
+/// `crates` should be generated by [`RunConfig::cargo_crates_in_set`].
+pub fn crate_description(crates: &[impl AsRef<str>]) -> String {
+ if crates.is_empty() {
+ return "".into();
+ }
+
+ let mut descr = String::from(" {");
+ descr.push_str(crates[0].as_ref());
+ for krate in &crates[1..] {
+ descr.push_str(", ");
+ descr.push_str(krate.as_ref());
+ }
+ descr.push('}');
+ descr
}
struct StepDescription {
@@ -161,9 +191,9 @@ pub enum PathSet {
/// A "suite" of paths.
///
/// These can match as a path suffix (like `Set`), or as a prefix. For
- /// example, a command-line value of `src/test/ui/abi/variadic-ffi.rs`
- /// will match `src/test/ui`. A command-line value of `ui` would also
- /// match `src/test/ui`.
+ /// example, a command-line value of `tests/ui/abi/variadic-ffi.rs`
+ /// will match `tests/ui`. A command-line value of `ui` would also
+ /// match `tests/ui`.
Suite(TaskPath),
}
@@ -433,8 +463,11 @@ impl<'a> ShouldRun<'a> {
// single alias, which does not correspond to any on-disk path
pub fn alias(mut self, alias: &str) -> Self {
+ // exceptional case for `Kind::Setup` because its `library`
+ // and `compiler` options would otherwise naively match with
+ // `compiler` and `library` folders respectively.
assert!(
- !self.builder.src.join(alias).exists(),
+ self.kind == Kind::Setup || !self.builder.src.join(alias).exists(),
"use `builder.path()` for real paths: {}",
alias
);
@@ -629,6 +662,7 @@ impl<'a> Builder<'a> {
crate::toolstate::ToolStateCheck,
test::ExpandYamlAnchors,
test::Tidy,
+ test::TidySelfTest,
test::Ui,
test::RunPassValgrind,
test::MirOpt,
@@ -698,6 +732,7 @@ impl<'a> Builder<'a> {
doc::RustdocBook,
doc::RustByExample,
doc::RustcBook,
+ doc::Cargo,
doc::CargoBook,
doc::Clippy,
doc::ClippyBook,
@@ -744,6 +779,7 @@ impl<'a> Builder<'a> {
install::RustDemangler,
install::Clippy,
install::Miri,
+ install::LlvmTools,
install::Analysis,
install::Src,
install::Rustc
@@ -757,8 +793,10 @@ impl<'a> Builder<'a> {
run::CollectLicenseMetadata,
run::GenerateCopyright,
),
- // These commands either don't use paths, or they're special-cased in Build::build()
- Kind::Clean | Kind::Format | Kind::Setup => vec![],
+ Kind::Setup => describe!(setup::Profile),
+ Kind::Clean => describe!(clean::CleanAll, clean::Rustc, clean::Std),
+ // special-cased in Build::build()
+ Kind::Format => vec![],
}
}
@@ -820,10 +858,12 @@ impl<'a> Builder<'a> {
Subcommand::Dist { ref paths } => (Kind::Dist, &paths[..]),
Subcommand::Install { ref paths } => (Kind::Install, &paths[..]),
Subcommand::Run { ref paths, .. } => (Kind::Run, &paths[..]),
+ Subcommand::Clean { ref paths, .. } => (Kind::Clean, &paths[..]),
Subcommand::Format { .. } => (Kind::Format, &[][..]),
- Subcommand::Clean { .. } | Subcommand::Setup { .. } => {
- panic!()
- }
+ Subcommand::Setup { profile: ref path } => (
+ Kind::Setup,
+ path.as_ref().map_or([].as_slice(), |path| std::slice::from_ref(path)),
+ ),
};
Self::new_internal(build, kind, paths.to_owned())
@@ -1058,7 +1098,7 @@ impl<'a> Builder<'a> {
/// check build or dry-run, where there's no need to build all of LLVM.
fn llvm_config(&self, target: TargetSelection) -> Option<PathBuf> {
if self.config.llvm_enabled() && self.kind != Kind::Check && !self.config.dry_run() {
- let llvm_config = self.ensure(native::Llvm { target });
+ let native::LlvmResult { llvm_config, .. } = self.ensure(native::Llvm { target });
if llvm_config.is_file() {
return Some(llvm_config);
}
@@ -1066,6 +1106,62 @@ impl<'a> Builder<'a> {
None
}
+ /// Like `cargo`, but only passes flags that are valid for all commands.
+ pub fn bare_cargo(
+ &self,
+ compiler: Compiler,
+ mode: Mode,
+ target: TargetSelection,
+ cmd: &str,
+ ) -> Command {
+ let mut cargo = Command::new(&self.initial_cargo);
+ // Run cargo from the source root so it can find .cargo/config.
+ // This matters when using vendoring and the working directory is outside the repository.
+ cargo.current_dir(&self.src);
+
+ let out_dir = self.stage_out(compiler, mode);
+ cargo.env("CARGO_TARGET_DIR", &out_dir).arg(cmd);
+
+ // Found with `rg "init_env_logger\("`. If anyone uses `init_env_logger`
+ // from out of tree it shouldn't matter, since x.py is only used for
+ // building in-tree.
+ let color_logs = ["RUSTDOC_LOG_COLOR", "RUSTC_LOG_COLOR", "RUST_LOG_COLOR"];
+ match self.build.config.color {
+ Color::Always => {
+ cargo.arg("--color=always");
+ for log in &color_logs {
+ cargo.env(log, "always");
+ }
+ }
+ Color::Never => {
+ cargo.arg("--color=never");
+ for log in &color_logs {
+ cargo.env(log, "never");
+ }
+ }
+ Color::Auto => {} // nothing to do
+ }
+
+ if cmd != "install" {
+ cargo.arg("--target").arg(target.rustc_target_arg());
+ } else {
+ assert_eq!(target, compiler.host);
+ }
+
+ if self.config.rust_optimize {
+ // FIXME: cargo bench/install do not accept `--release`
+ if cmd != "bench" && cmd != "install" {
+ cargo.arg("--release");
+ }
+ }
+
+ // Remove make-related flags to ensure Cargo can correctly set things up
+ cargo.env_remove("MAKEFLAGS");
+ cargo.env_remove("MFLAGS");
+
+ cargo
+ }
+
/// Prepares an invocation of `cargo` to be run.
///
/// This will create a `Command` that represents a pending execution of
@@ -1081,11 +1177,8 @@ impl<'a> Builder<'a> {
target: TargetSelection,
cmd: &str,
) -> Cargo {
- let mut cargo = Command::new(&self.initial_cargo);
+ let mut cargo = self.bare_cargo(compiler, mode, target, cmd);
let out_dir = self.stage_out(compiler, mode);
- // Run cargo from the source root so it can find .cargo/config.
- // This matters when using vendoring and the working directory is outside the repository.
- cargo.current_dir(&self.src);
// Codegen backends are not yet tracked by -Zbinary-dep-depinfo,
// so we need to explicitly clear out if they've been updated.
@@ -1110,8 +1203,6 @@ impl<'a> Builder<'a> {
self.clear_if_dirty(&my_out, &rustdoc);
}
- cargo.env("CARGO_TARGET_DIR", &out_dir).arg(cmd);
-
let profile_var = |name: &str| {
let profile = if self.config.rust_optimize { "RELEASE" } else { "DEV" };
format!("CARGO_PROFILE_{}_{}", profile, name)
@@ -1124,32 +1215,6 @@ impl<'a> Builder<'a> {
cargo.env("REAL_LIBRARY_PATH", e);
}
- // Found with `rg "init_env_logger\("`. If anyone uses `init_env_logger`
- // from out of tree it shouldn't matter, since x.py is only used for
- // building in-tree.
- let color_logs = ["RUSTDOC_LOG_COLOR", "RUSTC_LOG_COLOR", "RUST_LOG_COLOR"];
- match self.build.config.color {
- Color::Always => {
- cargo.arg("--color=always");
- for log in &color_logs {
- cargo.env(log, "always");
- }
- }
- Color::Never => {
- cargo.arg("--color=never");
- for log in &color_logs {
- cargo.env(log, "never");
- }
- }
- Color::Auto => {} // nothing to do
- }
-
- if cmd != "install" {
- cargo.arg("--target").arg(target.rustc_target_arg());
- } else {
- assert_eq!(target, compiler.host);
- }
-
// Set a flag for `check`/`clippy`/`fix`, so that certain build
// scripts can do less work (i.e. not building/requiring LLVM).
if cmd == "check" || cmd == "clippy" || cmd == "fix" {
@@ -1316,23 +1381,31 @@ impl<'a> Builder<'a> {
// this), as well as #63012 which is the tracking issue for this
// feature on the rustc side.
cargo.arg("-Zbinary-dep-depinfo");
- match mode {
- Mode::ToolBootstrap => {
- // Restrict the allowed features to those passed by rustbuild, so we don't depend on nightly accidentally.
- rustflags.arg("-Zallow-features=binary-dep-depinfo");
+ let allow_features = match mode {
+ Mode::ToolBootstrap | Mode::ToolStd => {
+ // Restrict the allowed features so we don't depend on nightly
+ // accidentally.
+ //
+ // binary-dep-depinfo is used by rustbuild itself for all
+ // compilations.
+ //
+ // Lots of tools depend on proc_macro2 and proc-macro-error.
+ // Those have build scripts which assume nightly features are
+ // available if the `rustc` version is "nighty" or "dev". See
+ // bin/rustc.rs for why that is a problem. Instead of labeling
+ // those features for each individual tool that needs them,
+ // just blanket allow them here.
+ //
+ // If this is ever removed, be sure to add something else in
+ // its place to keep the restrictions in place (or make a way
+ // to unset RUSTC_BOOTSTRAP).
+ "binary-dep-depinfo,proc_macro_span,proc_macro_span_shrink,proc_macro_diagnostic"
+ .to_string()
}
- Mode::ToolStd => {
- // Right now this is just compiletest and a few other tools that build on stable.
- // Allow them to use `feature(test)`, but nothing else.
- rustflags.arg("-Zallow-features=binary-dep-depinfo,test,proc_macro_internals,proc_macro_diagnostic,proc_macro_span");
- }
- Mode::Std | Mode::Rustc | Mode::Codegen | Mode::ToolRustc => {}
- }
+ Mode::Std | Mode::Rustc | Mode::Codegen | Mode::ToolRustc => String::new(),
+ };
cargo.arg("-j").arg(self.jobs().to_string());
- // Remove make-related flags to ensure Cargo can correctly set things up
- cargo.env_remove("MAKEFLAGS");
- cargo.env_remove("MFLAGS");
// FIXME: Temporary fix for https://github.com/rust-lang/cargo/issues/3005
// Force cargo to output binaries with disambiguating hashes in the name
@@ -1816,13 +1889,6 @@ impl<'a> Builder<'a> {
}
}
- if self.config.rust_optimize {
- // FIXME: cargo bench/install do not accept `--release`
- if cmd != "bench" && cmd != "install" {
- cargo.arg("--release");
- }
- }
-
if self.config.locked_deps {
cargo.arg("--locked");
}
@@ -1853,11 +1919,14 @@ impl<'a> Builder<'a> {
};
if let Some(limit) = limit {
- rustflags.arg(&format!("-Cllvm-args=-import-instr-limit={}", limit));
+ if stage == 0 || self.config.default_codegen_backend().unwrap_or_default() == "llvm"
+ {
+ rustflags.arg(&format!("-Cllvm-args=-import-instr-limit={}", limit));
+ }
}
}
- Cargo { command: cargo, rustflags, rustdocflags }
+ Cargo { command: cargo, rustflags, rustdocflags, allow_features }
}
/// Ensure that a given step is built, returning its output. This will
@@ -2036,6 +2105,7 @@ pub struct Cargo {
command: Command,
rustflags: Rustflags,
rustdocflags: Rustflags,
+ allow_features: String,
}
impl Cargo {
@@ -2080,6 +2150,18 @@ impl Cargo {
self.command.current_dir(dir);
self
}
+
+ /// Adds nightly-only features that this invocation is allowed to use.
+ ///
+ /// By default, all nightly features are allowed. Once this is called, it
+ /// will be restricted to the given set.
+ pub fn allow_features(&mut self, features: &str) -> &mut Cargo {
+ if !self.allow_features.is_empty() {
+ self.allow_features.push(',');
+ }
+ self.allow_features.push_str(features);
+ self
+ }
}
impl From<Cargo> for Command {
@@ -2094,6 +2176,10 @@ impl From<Cargo> for Command {
cargo.command.env("RUSTDOCFLAGS", rustdocflags);
}
+ if !cargo.allow_features.is_empty() {
+ cargo.command.env("RUSTC_ALLOW_FEATURES", cargo.allow_features);
+ }
+
cargo.command
}
}