From 4547b622d8d29df964fa2914213088b148c498fc Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:18:32 +0200 Subject: Merging upstream version 1.67.1+dfsg1. Signed-off-by: Daniel Baumann --- src/bootstrap/lib.rs | 215 ++++++++++++++++++++++++--------------------------- 1 file changed, 102 insertions(+), 113 deletions(-) (limited to 'src/bootstrap/lib.rs') diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 7e70e99bb..3ed534523 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -112,15 +112,14 @@ use std::path::{Path, PathBuf}; use std::process::Command; use std::str; -use config::Target; +use channel::GitInfo; +use config::{DryRun, Target}; use filetime::FileTime; use once_cell::sync::OnceCell; use crate::builder::Kind; use crate::config::{LlvmLibunwind, TargetSelection}; -use crate::util::{ - check_run, exe, libdir, mtime, output, run, run_suppressed, try_run, try_run_suppressed, CiEnv, -}; +use crate::util::{exe, libdir, mtime, output, run, run_suppressed, try_run_suppressed, CiEnv}; mod bolt; mod builder; @@ -133,6 +132,7 @@ mod compile; mod config; mod dist; mod doc; +mod download; mod flags; mod format; mod install; @@ -281,7 +281,6 @@ pub struct Build { src: PathBuf, out: PathBuf, bootstrap_out: PathBuf, - rust_info: channel::GitInfo, cargo_info: channel::GitInfo, rust_analyzer_info: channel::GitInfo, clippy_info: channel::GitInfo, @@ -396,6 +395,28 @@ pub enum CLang { Cxx, } +macro_rules! forward { + ( $( $fn:ident( $($param:ident: $ty:ty),* ) $( -> $ret:ty)? ),+ $(,)? ) => { + impl Build { + $( fn $fn(&self, $($param: $ty),* ) $( -> $ret)? { + self.config.$fn( $($param),* ) + } )+ + } + } +} + +forward! { + verbose(msg: &str), + is_verbose() -> bool, + create(path: &Path, s: &str), + remove(f: &Path), + tempdir() -> PathBuf, + try_run(cmd: &mut Command) -> bool, + llvm_link_shared() -> bool, + download_rustc() -> bool, + initial_rustfmt() -> Option, +} + impl Build { /// Creates a new set of build configuration from the `flags` on the command /// line and the filesystem `config`. @@ -430,7 +451,7 @@ impl Build { // we always try to use git for LLVM builds let in_tree_llvm_info = channel::GitInfo::new(false, &src.join("src/llvm-project")); - let initial_target_libdir_str = if config.dry_run { + let initial_target_libdir_str = if config.dry_run() { "/dummy/lib/path/to/lib/".to_string() } else { output( @@ -444,7 +465,7 @@ impl Build { let initial_target_dir = Path::new(&initial_target_libdir_str).parent().unwrap(); let initial_lld = initial_target_dir.join("bin").join("rust-lld"); - let initial_sysroot = if config.dry_run { + let initial_sysroot = if config.dry_run() { "/dummy".to_string() } else { output(Command::new(&config.initial_rustc).arg("--print").arg("sysroot")) @@ -499,7 +520,6 @@ impl Build { out, bootstrap_out, - rust_info, cargo_info, rust_analyzer_info, clippy_info, @@ -522,16 +542,6 @@ impl Build { metrics: metrics::BuildMetrics::init(), }; - build.verbose("finding compilers"); - cc_detect::find(&mut build); - // When running `setup`, the profile is about to change, so any requirements we have now may - // be different on the next invocation. Don't check for them until the next time x.py is - // run. This is ok because `setup` never runs any build commands, so it won't fail if commands are missing. - if !matches!(build.config.cmd, Subcommand::Setup { .. }) { - build.verbose("running sanity check"); - sanity::check(&mut build); - } - // If local-rust is the same major.minor as the current version, then force a // local-rebuild let local_version_verbose = @@ -547,16 +557,34 @@ impl Build { build.local_rebuild = true; } - // Make sure we update these before gathering metadata so we don't get an error about missing - // Cargo.toml files. - let rust_submodules = - ["src/tools/rust-installer", "src/tools/cargo", "library/backtrace", "library/stdarch"]; - for s in rust_submodules { - build.update_submodule(Path::new(s)); - } + build.verbose("finding compilers"); + cc_detect::find(&mut build); + // When running `setup`, the profile is about to change, so any requirements we have now may + // be different on the next invocation. Don't check for them until the next time x.py is + // run. This is ok because `setup` never runs any build commands, so it won't fail if commands are missing. + // + // Similarly, for `setup` we don't actually need submodules or cargo metadata. + if !matches!(build.config.cmd, Subcommand::Setup { .. }) { + build.verbose("running sanity check"); + sanity::check(&mut build); + + // Make sure we update these before gathering metadata so we don't get an error about missing + // Cargo.toml files. + let rust_submodules = [ + "src/tools/rust-installer", + "src/tools/cargo", + "library/backtrace", + "library/stdarch", + ]; + for s in rust_submodules { + build.update_submodule(Path::new(s)); + } + // Now, update all existing submodules. + build.update_existing_submodules(); - build.verbose("learning about cargo"); - metadata::build(&mut build); + build.verbose("learning about cargo"); + metadata::build(&mut build); + } build } @@ -570,7 +598,7 @@ impl Build { t!(std::fs::read_dir(dir)).next().is_none() } - if !self.config.submodules(&self.rust_info) { + if !self.config.submodules(&self.rust_info()) { return; } @@ -628,15 +656,29 @@ impl Build { self.run(&mut update(false)); } + // Save any local changes, but avoid running `git stash pop` if there are none (since it will exit with an error). + let has_local_modifications = !self.try_run( + Command::new("git") + .args(&["diff-index", "--quiet", "HEAD"]) + .current_dir(&absolute_path), + ); + if has_local_modifications { + self.run(Command::new("git").args(&["stash", "push"]).current_dir(&absolute_path)); + } + self.run(Command::new("git").args(&["reset", "-q", "--hard"]).current_dir(&absolute_path)); - self.run(Command::new("git").args(&["clean", "-qdfx"]).current_dir(absolute_path)); + self.run(Command::new("git").args(&["clean", "-qdfx"]).current_dir(&absolute_path)); + + if has_local_modifications { + self.run(Command::new("git").args(&["stash", "pop"]).current_dir(absolute_path)); + } } /// If any submodule has been initialized already, sync it unconditionally. /// This avoids contributors checking in a submodule change by accident. - pub fn maybe_update_submodules(&self) { + pub fn update_existing_submodules(&self) { // Avoid running git when there isn't a git checkout. - if !self.config.submodules(&self.rust_info) { + if !self.config.submodules(&self.rust_info()) { return; } let output = output( @@ -663,8 +705,6 @@ impl Build { job::setup(self); } - self.maybe_update_submodules(); - if let Subcommand::Format { check, paths } = &self.config.cmd { return format::format(&builder::Builder::new(&self), *check, &paths); } @@ -689,13 +729,13 @@ impl Build { } } - if !self.config.dry_run { + if !self.config.dry_run() { { - self.config.dry_run = true; + self.config.dry_run = DryRun::SelfCheck; let builder = builder::Builder::new(&self); builder.execute_cli(); } - self.config.dry_run = false; + self.config.dry_run = DryRun::Disabled; let builder = builder::Builder::new(&self); builder.execute_cli(); } else { @@ -735,6 +775,10 @@ impl Build { cleared } + fn rust_info(&self) -> &GitInfo { + &self.config.rust_info + } + /// Gets the space-separated set of activated features for the standard /// library. fn std_features(&self, target: TargetSelection) -> String { @@ -947,7 +991,7 @@ impl Build { /// Runs a command, printing out nice contextual information if it fails. fn run(&self, cmd: &mut Command) { - if self.config.dry_run { + if self.config.dry_run() { return; } self.verbose(&format!("running: {:?}", cmd)); @@ -956,57 +1000,24 @@ impl Build { /// Runs a command, printing out nice contextual information if it fails. fn run_quiet(&self, cmd: &mut Command) { - if self.config.dry_run { + if self.config.dry_run() { return; } self.verbose(&format!("running: {:?}", cmd)); run_suppressed(cmd) } - /// Runs a command, printing out nice contextual information if it fails. - /// Exits if the command failed to execute at all, otherwise returns its - /// `status.success()`. - fn try_run(&self, cmd: &mut Command) -> bool { - if self.config.dry_run { - return true; - } - self.verbose(&format!("running: {:?}", cmd)); - try_run(cmd, self.is_verbose()) - } - /// Runs a command, printing out nice contextual information if it fails. /// Exits if the command failed to execute at all, otherwise returns its /// `status.success()`. fn try_run_quiet(&self, cmd: &mut Command) -> bool { - if self.config.dry_run { + if self.config.dry_run() { return true; } self.verbose(&format!("running: {:?}", cmd)); try_run_suppressed(cmd) } - /// Runs a command, printing out nice contextual information if it fails. - /// Returns false if do not execute at all, otherwise returns its - /// `status.success()`. - fn check_run(&self, cmd: &mut Command) -> bool { - if self.config.dry_run { - return true; - } - self.verbose(&format!("running: {:?}", cmd)); - check_run(cmd, self.is_verbose()) - } - - pub fn is_verbose(&self) -> bool { - self.verbosity > 0 - } - - /// Prints a message if this build is configured in verbose mode. - fn verbose(&self, msg: &str) { - if self.is_verbose() { - println!("{}", msg); - } - } - pub fn is_verbose_than(&self, level: usize) -> bool { self.verbosity > level } @@ -1019,10 +1030,12 @@ impl Build { } fn info(&self, msg: &str) { - if self.config.dry_run { - return; + match self.config.dry_run { + DryRun::SelfCheck => return, + DryRun::Disabled | DryRun::UserSelected => { + println!("{}", msg); + } } - println!("{}", msg); } /// Returns the number of parallel jobs that have been configured for this @@ -1152,8 +1165,8 @@ impl Build { options[0] = Some("-Clink-arg=-fuse-ld=lld".to_string()); } - let threads = if target.contains("windows") { "/threads:1" } else { "--threads=1" }; - options[1] = Some(format!("-Clink-arg=-Wl,{}", threads)); + let no_threads = util::lld_flag_no_threads(target.contains("windows")); + options[1] = Some(format!("-Clink-arg=-Wl,{}", no_threads)); } IntoIterator::into_iter(options).flatten() @@ -1267,7 +1280,7 @@ impl Build { match &self.config.channel[..] { "stable" => num.to_string(), "beta" => { - if self.rust_info.is_managed_git_subrepository() && !self.config.ignore_git { + if self.rust_info().is_managed_git_subrepository() && !self.config.ignore_git { format!("{}-beta.{}", num, self.beta_prerelease_version()) } else { format!("{}-beta", num) @@ -1327,7 +1340,7 @@ impl Build { /// Note that this is a descriptive string which includes the commit date, /// sha, version, etc. fn rust_version(&self) -> String { - let mut version = self.rust_info.version(self, &self.version); + let mut version = self.rust_info().version(self, &self.version); if let Some(ref s) = self.config.description { version.push_str(" ("); version.push_str(s); @@ -1338,7 +1351,7 @@ impl Build { /// Returns the full commit hash. fn rust_sha(&self) -> Option<&str> { - self.rust_info.sha() + self.rust_info().sha() } /// Returns the `a.b.c` version that the given package is at. @@ -1400,7 +1413,7 @@ impl Build { } fn read_stamp_file(&self, stamp: &Path) -> Vec<(PathBuf, DependencyType)> { - if self.config.dry_run { + if self.config.dry_run() { return Vec::new(); } @@ -1424,23 +1437,13 @@ impl Build { paths } - /// Create a temporary directory in `out` and return its path. - /// - /// NOTE: this temporary directory is shared between all steps; - /// if you need an empty directory, create a new subdirectory inside it. - fn tempdir(&self) -> PathBuf { - let tmp = self.out.join("tmp"); - t!(fs::create_dir_all(&tmp)); - tmp - } - /// Copies a file from `src` to `dst` pub fn copy(&self, src: &Path, dst: &Path) { self.copy_internal(src, dst, false); } fn copy_internal(&self, src: &Path, dst: &Path, dereference_symlinks: bool) { - if self.config.dry_run { + if self.config.dry_run() { return; } self.verbose_than(1, &format!("Copy {:?} to {:?}", src, dst)); @@ -1477,7 +1480,7 @@ impl Build { /// Copies the `src` directory recursively to `dst`. Both are assumed to exist /// when this function is called. pub fn cp_r(&self, src: &Path, dst: &Path) { - if self.config.dry_run { + if self.config.dry_run() { return; } for f in self.read_dir(src) { @@ -1530,7 +1533,7 @@ impl Build { } fn install(&self, src: &Path, dstdir: &Path, perms: u32) { - if self.config.dry_run { + if self.config.dry_run() { return; } let dst = dstdir.join(src.file_name().unwrap()); @@ -1543,29 +1546,22 @@ impl Build { chmod(&dst, perms); } - fn create(&self, path: &Path, s: &str) { - if self.config.dry_run { - return; - } - t!(fs::write(path, s)); - } - fn read(&self, path: &Path) -> String { - if self.config.dry_run { + if self.config.dry_run() { return String::new(); } t!(fs::read_to_string(path)) } fn create_dir(&self, dir: &Path) { - if self.config.dry_run { + if self.config.dry_run() { return; } t!(fs::create_dir_all(dir)) } fn remove_dir(&self, dir: &Path) { - if self.config.dry_run { + if self.config.dry_run() { return; } t!(fs::remove_dir_all(dir)) @@ -1574,7 +1570,7 @@ impl Build { fn read_dir(&self, dir: &Path) -> impl Iterator { let iter = match fs::read_dir(dir) { Ok(v) => v, - Err(_) if self.config.dry_run => return vec![].into_iter(), + Err(_) if self.config.dry_run() => return vec![].into_iter(), Err(err) => panic!("could not read dir {:?}: {:?}", dir, err), }; iter.map(|e| t!(e)).collect::>().into_iter() @@ -1585,14 +1581,7 @@ impl Build { use std::os::unix::fs::symlink as symlink_file; #[cfg(windows)] use std::os::windows::fs::symlink_file; - if !self.config.dry_run { symlink_file(src.as_ref(), link.as_ref()) } else { Ok(()) } - } - - fn remove(&self, f: &Path) { - if self.config.dry_run { - return; - } - fs::remove_file(f).unwrap_or_else(|_| panic!("failed to remove {:?}", f)); + if !self.config.dry_run() { symlink_file(src.as_ref(), link.as_ref()) } else { Ok(()) } } /// Returns if config.ninja is enabled, and checks for ninja existence, -- cgit v1.2.3