diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 9d8f97196b61..5913c871d83d 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -679,15 +679,11 @@ impl Config { .unwrap_or_else(|| vec![host_target]); let llvm_assertions = llvm_assertions_.unwrap_or(false); - let mut target_config = HashMap::new(); - let mut download_rustc_commit = None; - let mut llvm_from_ci = false; let mut channel = "dev".to_string(); let mut out = flags_build_dir .or(build_build_dir.map(PathBuf::from)) .unwrap_or_else(|| PathBuf::from("build")); - let mut rust_info = GitInfo::Absent; if cfg!(test) { // Use the build directory of the original x.py invocation, so that we can set `initial_rustc` properly. @@ -730,16 +726,11 @@ impl Config { ); } - let mut dwn_ctx = DownloadContext { + let dwn_ctx = DownloadContext { path_modification_cache: path_modification_cache.clone(), src: &src, - rust_info: rust_info.clone(), submodules: &build_submodules, - download_rustc_commit: download_rustc_commit.clone(), host_target, - llvm_from_ci, - target_config: target_config.clone(), - out: out.clone(), patch_binaries_for_nix: build_patch_binaries_for_nix, exec_ctx: &exec_ctx, stage0_metadata: &stage0_metadata, @@ -749,7 +740,7 @@ impl Config { }; let initial_rustc = build_rustc.unwrap_or_else(|| { - download_beta_toolchain(&dwn_ctx); + download_beta_toolchain(&dwn_ctx, &out); out.join(host_target).join("stage0").join("bin").join(exe("rustc", host_target)) }); @@ -763,7 +754,7 @@ impl Config { )); let initial_cargo = build_cargo.unwrap_or_else(|| { - download_beta_toolchain(&dwn_ctx); + download_beta_toolchain(&dwn_ctx, &out); initial_sysroot.join("bin").join(exe("cargo", host_target)) }); @@ -771,7 +762,6 @@ impl Config { if exec_ctx.dry_run() { out = out.join("tmp-dry-run"); fs::create_dir_all(&out).expect("Failed to create dry-run directory"); - dwn_ctx.out = out.clone(); } let file_content = t!(fs::read_to_string(src.join("src/ci/channel"))); @@ -791,8 +781,7 @@ impl Config { let omit_git_hash = rust_omit_git_hash.unwrap_or(channel == "dev"); - rust_info = git_info(&exec_ctx, omit_git_hash, &src); - dwn_ctx.rust_info = rust_info.clone(); + let rust_info = git_info(&exec_ctx, omit_git_hash, &src); if !is_user_configured_rust_channel && rust_info.is_from_tarball() { channel = ci_channel.into(); @@ -823,9 +812,8 @@ impl Config { ); } - download_rustc_commit = - download_ci_rustc_commit(&dwn_ctx, rust_download_rustc, llvm_assertions); - dwn_ctx.download_rustc_commit = download_rustc_commit.clone(); + let mut download_rustc_commit = + download_ci_rustc_commit(&dwn_ctx, &rust_info, rust_download_rustc, llvm_assertions); if debug_assertions_requested && download_rustc_commit.is_some() { eprintln!( @@ -834,7 +822,6 @@ impl Config { ); // We need to put this later down_ci_rustc_commit. download_rustc_commit = None; - dwn_ctx.download_rustc_commit = None; } // We need to override `rust.channel` if it's manually specified when using the CI rustc. @@ -847,9 +834,10 @@ impl Config { "WARNING: `rust.download-rustc` is enabled. The `rust.channel` option will be overridden by the CI rustc's channel." ); - channel = read_file_by_commit(&dwn_ctx, Path::new("src/ci/channel"), commit) - .trim() - .to_owned(); + channel = + read_file_by_commit(&dwn_ctx, &rust_info, Path::new("src/ci/channel"), commit) + .trim() + .to_owned(); } if let Some(t) = toml.target { @@ -911,11 +899,15 @@ impl Config { target_config.insert(TargetSelection::from_user(&triple), target); } - dwn_ctx.target_config = target_config.clone(); } - llvm_from_ci = parse_download_ci_llvm(&dwn_ctx, llvm_download_ci_llvm, llvm_assertions); - dwn_ctx.llvm_from_ci = llvm_from_ci; + let llvm_from_ci = parse_download_ci_llvm( + &dwn_ctx, + &rust_info, + &download_rustc_commit, + llvm_download_ci_llvm, + llvm_assertions, + ); // We make `x86_64-unknown-linux-gnu` use the self-contained linker by default, so we will // build our internal lld and use it as the default linker, by setting the `rust.lld` config @@ -976,18 +968,16 @@ impl Config { if llvm_from_ci { let triple = &host_target.triple; - let ci_llvm_bin = ci_llvm_root(&dwn_ctx).join("bin"); + let ci_llvm_bin = ci_llvm_root(&dwn_ctx, llvm_from_ci, &out).join("bin"); let build_target = target_config.entry(host_target).or_insert_with(|| Target::from_triple(triple)); - dwn_ctx.target_config.entry(host_target).or_insert_with(|| Target::from_triple(triple)); - check_ci_llvm!(build_target.llvm_config); check_ci_llvm!(build_target.llvm_filecheck); build_target.llvm_config = Some(ci_llvm_bin.join(exe("llvm-config", host_target))); build_target.llvm_filecheck = Some(ci_llvm_bin.join(exe("FileCheck", host_target))); } - let initial_rustfmt = build_rustfmt.or_else(|| maybe_download_rustfmt(&dwn_ctx)); + let initial_rustfmt = build_rustfmt.or_else(|| maybe_download_rustfmt(&dwn_ctx, &out)); if matches!(rust_lld_mode.unwrap_or_default(), LldMode::SelfContained) && !lld_enabled @@ -998,7 +988,7 @@ impl Config { ); } - if lld_enabled && is_system_llvm(&dwn_ctx, host_target) { + if lld_enabled && is_system_llvm(&dwn_ctx, &target_config, llvm_from_ci, host_target) { panic!("Cannot enable LLD with `rust.lld = true` when using external llvm-config."); } @@ -1392,7 +1382,7 @@ impl Config { /// Returns the content of the given file at a specific commit. pub(crate) fn read_file_by_commit(&self, file: &Path, commit: &str) -> String { let dwn_ctx = DownloadContext::from(self); - read_file_by_commit(dwn_ctx, file, commit) + read_file_by_commit(dwn_ctx, &self.rust_info, file, commit) } /// Bootstrap embeds a version number into the name of shared libraries it uploads in CI. @@ -1464,7 +1454,7 @@ impl Config { /// The absolute path to the downloaded LLVM artifacts. pub(crate) fn ci_llvm_root(&self) -> PathBuf { let dwn_ctx = DownloadContext::from(self); - ci_llvm_root(dwn_ctx) + ci_llvm_root(dwn_ctx, self.llvm_from_ci, &self.out) } /// Directory where the extracted `rustc-dev` component is stored. @@ -1628,7 +1618,7 @@ impl Config { )] pub(crate) fn update_submodule(&self, relative_path: &str) { let dwn_ctx = DownloadContext::from(self); - update_submodule(dwn_ctx, relative_path); + update_submodule(dwn_ctx, &self.rust_info, relative_path); } /// Returns true if any of the `paths` have been modified locally. @@ -1744,7 +1734,7 @@ impl Config { /// NOTE: this is not the same as `!is_rust_llvm` when `llvm_has_patches` is set. pub fn is_system_llvm(&self, target: TargetSelection) -> bool { let dwn_ctx = DownloadContext::from(self); - is_system_llvm(dwn_ctx, target) + is_system_llvm(dwn_ctx, &self.target_config, self.llvm_from_ci, target) } /// Returns `true` if this is our custom, patched, version of LLVM. @@ -2038,6 +2028,7 @@ pub fn check_stage0_version( pub fn download_ci_rustc_commit<'a>( dwn_ctx: impl AsRef>, + rust_info: &channel::GitInfo, download_rustc: Option, llvm_assertions: bool, ) -> Option { @@ -2057,7 +2048,7 @@ pub fn download_ci_rustc_commit<'a>( None | Some(StringOrBool::Bool(false)) => return None, Some(StringOrBool::Bool(true)) => false, Some(StringOrBool::String(s)) if s == "if-unchanged" => { - if !dwn_ctx.rust_info.is_managed_git_subrepository() { + if !rust_info.is_managed_git_subrepository() { println!( "ERROR: `download-rustc=if-unchanged` is only compatible with Git managed sources." ); @@ -2071,7 +2062,7 @@ pub fn download_ci_rustc_commit<'a>( } }; - let commit = if dwn_ctx.rust_info.is_managed_git_subrepository() { + let commit = if rust_info.is_managed_git_subrepository() { // Look for a version to compare to based on the current commit. // Only commits merged by bors will have CI artifacts. let freshness = check_path_modifications_(dwn_ctx, RUSTC_IF_UNCHANGED_ALLOWED_PATHS); @@ -2145,6 +2136,8 @@ pub fn git_config(stage0_metadata: &build_helper::stage0_parser::Stage0) -> GitC pub fn parse_download_ci_llvm<'a>( dwn_ctx: impl AsRef>, + rust_info: &channel::GitInfo, + download_rustc_commit: &Option, download_ci_llvm: Option, asserts: bool, ) -> bool { @@ -2160,7 +2153,7 @@ pub fn parse_download_ci_llvm<'a>( let download_ci_llvm = download_ci_llvm.unwrap_or(default); let if_unchanged = || { - if dwn_ctx.rust_info.is_from_tarball() { + if rust_info.is_from_tarball() { // Git is needed for running "if-unchanged" logic. println!("ERROR: 'if-unchanged' is only compatible with Git managed sources."); crate::exit!(1); @@ -2168,7 +2161,7 @@ pub fn parse_download_ci_llvm<'a>( // Fetching the LLVM submodule is unnecessary for self-tests. #[cfg(not(test))] - update_submodule(dwn_ctx, "src/llvm-project"); + update_submodule(dwn_ctx, rust_info, "src/llvm-project"); // Check for untracked changes in `src/llvm-project` and other important places. let has_changes = has_changes_from_upstream(dwn_ctx, LLVM_INVALIDATION_PATHS); @@ -2183,7 +2176,7 @@ pub fn parse_download_ci_llvm<'a>( match download_ci_llvm { StringOrBool::Bool(b) => { - if !b && dwn_ctx.download_rustc_commit.is_some() { + if !b && download_rustc_commit.is_some() { panic!( "`llvm.download-ci-llvm` cannot be set to `false` if `rust.download-rustc` is set to `true` or `if-unchanged`." ); @@ -2226,9 +2219,13 @@ pub fn has_changes_from_upstream<'a>( fields(relative_path = ?relative_path), ), )] -pub(crate) fn update_submodule<'a>(dwn_ctx: impl AsRef>, relative_path: &str) { +pub(crate) fn update_submodule<'a>( + dwn_ctx: impl AsRef>, + rust_info: &channel::GitInfo, + relative_path: &str, +) { let dwn_ctx = dwn_ctx.as_ref(); - if dwn_ctx.rust_info.is_from_tarball() || !submodules_(dwn_ctx.submodules, &dwn_ctx.rust_info) { + if rust_info.is_from_tarball() || !submodules_(dwn_ctx.submodules, rust_info) { return; } @@ -2357,12 +2354,14 @@ pub fn submodules_(submodules: &Option, rust_info: &channel::GitInfo) -> b /// NOTE: this is not the same as `!is_rust_llvm` when `llvm_has_patches` is set. pub fn is_system_llvm<'a>( dwn_ctx: impl AsRef>, + target_config: &HashMap, + llvm_from_ci: bool, target: TargetSelection, ) -> bool { let dwn_ctx = dwn_ctx.as_ref(); - match dwn_ctx.target_config.get(&target) { + match target_config.get(&target) { Some(Target { llvm_config: Some(_), .. }) => { - let ci_llvm = dwn_ctx.llvm_from_ci && is_host_target(&dwn_ctx.host_target, &target); + let ci_llvm = llvm_from_ci && is_host_target(&dwn_ctx.host_target, &target); !ci_llvm } // We're building from the in-tree src/llvm-project sources. @@ -2375,21 +2374,26 @@ pub fn is_host_target(host_target: &TargetSelection, target: &TargetSelection) - host_target == target } -pub(crate) fn ci_llvm_root<'a>(dwn_ctx: impl AsRef>) -> PathBuf { +pub(crate) fn ci_llvm_root<'a>( + dwn_ctx: impl AsRef>, + llvm_from_ci: bool, + out: &Path, +) -> PathBuf { let dwn_ctx = dwn_ctx.as_ref(); - assert!(dwn_ctx.llvm_from_ci); - dwn_ctx.out.join(dwn_ctx.host_target).join("ci-llvm") + assert!(llvm_from_ci); + out.join(dwn_ctx.host_target).join("ci-llvm") } /// Returns the content of the given file at a specific commit. pub(crate) fn read_file_by_commit<'a>( dwn_ctx: impl AsRef>, + rust_info: &channel::GitInfo, file: &Path, commit: &str, ) -> String { let dwn_ctx = dwn_ctx.as_ref(); assert!( - dwn_ctx.rust_info.is_managed_git_subrepository(), + rust_info.is_managed_git_subrepository(), "`Config::read_file_by_commit` is not supported in non-git sources." ); diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs index 402d6019dabb..2f3c80559c0e 100644 --- a/src/bootstrap/src/core/download.rs +++ b/src/bootstrap/src/core/download.rs @@ -9,9 +9,8 @@ use std::sync::{Arc, Mutex, OnceLock}; use build_helper::git::PathFreshness; use xz2::bufread::XzDecoder; -use crate::core::config::{BUILDER_CONFIG_FILENAME, Target, TargetSelection}; +use crate::core::config::{BUILDER_CONFIG_FILENAME, TargetSelection}; use crate::utils::build_stamp::BuildStamp; -use crate::utils::channel; use crate::utils::exec::{ExecutionContext, command}; use crate::utils::helpers::{exe, hex_encode, move_file}; use crate::{Config, t}; @@ -73,7 +72,7 @@ impl Config { fn download_file(&self, url: &str, dest_path: &Path, help_on_error: &str) { let dwn_ctx: DownloadContext<'_> = self.into(); - download_file(dwn_ctx, url, dest_path, help_on_error); + download_file(dwn_ctx, &self.out, url, dest_path, help_on_error); } fn unpack(&self, tarball: &Path, dst: &Path, pattern: &str) { @@ -238,7 +237,7 @@ impl Config { destination: &str, ) { let dwn_ctx: DownloadContext<'_> = self.into(); - download_component(dwn_ctx, mode, filename, prefix, key, destination); + download_component(dwn_ctx, &self.out, mode, filename, prefix, key, destination); } #[cfg(test)] @@ -403,13 +402,8 @@ impl Config { pub(crate) struct DownloadContext<'a> { pub path_modification_cache: Arc, PathFreshness>>>, pub src: &'a Path, - pub rust_info: channel::GitInfo, pub submodules: &'a Option, - pub download_rustc_commit: Option, pub host_target: TargetSelection, - pub llvm_from_ci: bool, - pub target_config: HashMap, - pub out: PathBuf, pub patch_binaries_for_nix: Option, pub exec_ctx: &'a ExecutionContext, pub stage0_metadata: &'a build_helper::stage0_parser::Stage0, @@ -430,12 +424,7 @@ impl<'a> From<&'a Config> for DownloadContext<'a> { path_modification_cache: value.path_modification_cache.clone(), src: &value.src, host_target: value.host_target, - rust_info: value.rust_info.clone(), - download_rustc_commit: value.download_rustc_commit.clone(), submodules: &value.submodules, - llvm_from_ci: value.llvm_from_ci, - target_config: value.target_config.clone(), - out: value.out.clone(), patch_binaries_for_nix: value.patch_binaries_for_nix, exec_ctx: &value.exec_ctx, stage0_metadata: &value.stage0_metadata, @@ -495,6 +484,7 @@ pub(crate) fn is_download_ci_available(target_triple: &str, llvm_assertions: boo #[cfg(test)] pub(crate) fn maybe_download_rustfmt<'a>( dwn_ctx: impl AsRef>, + out: &Path, ) -> Option { Some(PathBuf::new()) } @@ -504,6 +494,7 @@ pub(crate) fn maybe_download_rustfmt<'a>( #[cfg(not(test))] pub(crate) fn maybe_download_rustfmt<'a>( dwn_ctx: impl AsRef>, + out: &Path, ) -> Option { use build_helper::stage0_parser::VersionMetadata; @@ -517,7 +508,7 @@ pub(crate) fn maybe_download_rustfmt<'a>( let channel = format!("{version}-{date}"); let host = dwn_ctx.host_target; - let bin_root = dwn_ctx.out.join(host).join("rustfmt"); + let bin_root = out.join(host).join("rustfmt"); let rustfmt_path = bin_root.join("bin").join(exe("rustfmt", host)); let rustfmt_stamp = BuildStamp::new(&bin_root).with_prefix("rustfmt").add_stamp(channel); if rustfmt_path.exists() && rustfmt_stamp.is_up_to_date() { @@ -526,6 +517,7 @@ pub(crate) fn maybe_download_rustfmt<'a>( download_component( dwn_ctx, + out, DownloadSource::Dist, format!("rustfmt-{version}-{build}.tar.xz", build = host.triple), "rustfmt-preview", @@ -535,6 +527,7 @@ pub(crate) fn maybe_download_rustfmt<'a>( download_component( dwn_ctx, + out, DownloadSource::Dist, format!("rustc-{version}-{build}.tar.xz", build = host.triple), "rustc", @@ -543,13 +536,13 @@ pub(crate) fn maybe_download_rustfmt<'a>( ); if should_fix_bins_and_dylibs(dwn_ctx.patch_binaries_for_nix, dwn_ctx.exec_ctx) { - fix_bin_or_dylib(&dwn_ctx.out, &bin_root.join("bin").join("rustfmt"), dwn_ctx.exec_ctx); - fix_bin_or_dylib(&dwn_ctx.out, &bin_root.join("bin").join("cargo-fmt"), dwn_ctx.exec_ctx); + fix_bin_or_dylib(out, &bin_root.join("bin").join("rustfmt"), dwn_ctx.exec_ctx); + fix_bin_or_dylib(out, &bin_root.join("bin").join("cargo-fmt"), dwn_ctx.exec_ctx); let lib_dir = bin_root.join("lib"); for lib in t!(fs::read_dir(&lib_dir), lib_dir.display().to_string()) { let lib = t!(lib); if path_is_dylib(&lib.path()) { - fix_bin_or_dylib(&dwn_ctx.out, &lib.path(), dwn_ctx.exec_ctx); + fix_bin_or_dylib(out, &lib.path(), dwn_ctx.exec_ctx); } } } @@ -559,10 +552,10 @@ pub(crate) fn maybe_download_rustfmt<'a>( } #[cfg(test)] -pub(crate) fn download_beta_toolchain<'a>(dwn_ctx: impl AsRef>) {} +pub(crate) fn download_beta_toolchain<'a>(dwn_ctx: impl AsRef>, out: &Path) {} #[cfg(not(test))] -pub(crate) fn download_beta_toolchain<'a>(dwn_ctx: impl AsRef>) { +pub(crate) fn download_beta_toolchain<'a>(dwn_ctx: impl AsRef>, out: &Path) { let dwn_ctx = dwn_ctx.as_ref(); dwn_ctx.exec_ctx.verbose(|| { println!("downloading stage0 beta artifacts"); @@ -574,6 +567,7 @@ pub(crate) fn download_beta_toolchain<'a>(dwn_ctx: impl AsRef(dwn_ctx: impl AsRef( dwn_ctx: impl AsRef>, + out: &Path, version: &str, sysroot: &str, stamp_key: &str, @@ -594,7 +590,7 @@ fn download_toolchain<'a>( ) { let dwn_ctx = dwn_ctx.as_ref(); let host = dwn_ctx.host_target.triple; - let bin_root = dwn_ctx.out.join(host).join(sysroot); + let bin_root = out.join(host).join(sysroot); let rustc_stamp = BuildStamp::new(&bin_root).with_prefix("rustc").add_stamp(stamp_key); if !bin_root.join("bin").join(exe("rustc", dwn_ctx.host_target)).exists() @@ -605,20 +601,28 @@ fn download_toolchain<'a>( } let filename = format!("rust-std-{version}-{host}.tar.xz"); let pattern = format!("rust-std-{host}"); - download_component(dwn_ctx, mode.clone(), filename, &pattern, stamp_key, destination); + download_component(dwn_ctx, out, mode.clone(), filename, &pattern, stamp_key, destination); let filename = format!("rustc-{version}-{host}.tar.xz"); - download_component(dwn_ctx, mode.clone(), filename, "rustc", stamp_key, destination); + download_component(dwn_ctx, out, mode.clone(), filename, "rustc", stamp_key, destination); for component in extra_components { let filename = format!("{component}-{version}-{host}.tar.xz"); - download_component(dwn_ctx, mode.clone(), filename, component, stamp_key, destination); + download_component( + dwn_ctx, + out, + mode.clone(), + filename, + component, + stamp_key, + destination, + ); } if should_fix_bins_and_dylibs(dwn_ctx.patch_binaries_for_nix, dwn_ctx.exec_ctx) { - fix_bin_or_dylib(&dwn_ctx.out, &bin_root.join("bin").join("rustc"), dwn_ctx.exec_ctx); - fix_bin_or_dylib(&dwn_ctx.out, &bin_root.join("bin").join("rustdoc"), dwn_ctx.exec_ctx); + fix_bin_or_dylib(out, &bin_root.join("bin").join("rustc"), dwn_ctx.exec_ctx); + fix_bin_or_dylib(out, &bin_root.join("bin").join("rustdoc"), dwn_ctx.exec_ctx); fix_bin_or_dylib( - &dwn_ctx.out, + out, &bin_root.join("libexec").join("rust-analyzer-proc-macro-srv"), dwn_ctx.exec_ctx, ); @@ -626,7 +630,7 @@ fn download_toolchain<'a>( for lib in t!(fs::read_dir(&lib_dir), lib_dir.display().to_string()) { let lib = t!(lib); if path_is_dylib(&lib.path()) { - fix_bin_or_dylib(&dwn_ctx.out, &lib.path(), dwn_ctx.exec_ctx); + fix_bin_or_dylib(out, &lib.path(), dwn_ctx.exec_ctx); } } } @@ -750,6 +754,7 @@ fn should_fix_bins_and_dylibs( fn download_component<'a>( dwn_ctx: impl AsRef>, + out: &Path, mode: DownloadSource, filename: String, prefix: &str, @@ -763,14 +768,14 @@ fn download_component<'a>( } let cache_dst = - dwn_ctx.bootstrap_cache_path.as_ref().cloned().unwrap_or_else(|| dwn_ctx.out.join("cache")); + dwn_ctx.bootstrap_cache_path.as_ref().cloned().unwrap_or_else(|| out.join("cache")); let cache_dir = cache_dst.join(key); if !cache_dir.exists() { t!(fs::create_dir_all(&cache_dir)); } - let bin_root = dwn_ctx.out.join(dwn_ctx.host_target).join(destination); + let bin_root = out.join(dwn_ctx.host_target).join(destination); let tarball = cache_dir.join(&filename); let (base_url, url, should_verify) = match mode { DownloadSource::CI => { @@ -835,7 +840,7 @@ HELP: if trying to compile an old commit of rustc, disable `download-rustc` in b download-rustc = false "; } - download_file(dwn_ctx, &format!("{base_url}/{url}"), &tarball, help_on_error); + download_file(dwn_ctx, out, &format!("{base_url}/{url}"), &tarball, help_on_error); if let Some(sha256) = checksum && !verify(dwn_ctx.exec_ctx, &tarball, sha256) { @@ -953,6 +958,7 @@ fn unpack(exec_ctx: &ExecutionContext, tarball: &Path, dst: &Path, pattern: &str fn download_file<'a>( dwn_ctx: impl AsRef>, + out: &Path, url: &str, dest_path: &Path, help_on_error: &str, @@ -963,7 +969,7 @@ fn download_file<'a>( println!("download {url}"); }); // Use a temporary file in case we crash while downloading, to avoid a corrupt download in cache/. - let tempfile = tempdir(&dwn_ctx.out).join(dest_path.file_name().unwrap()); + let tempfile = tempdir(out).join(dest_path.file_name().unwrap()); // While bootstrap itself only supports http and https downloads, downstream forks might // need to download components from other protocols. The match allows them adding more // protocols without worrying about merge conflicts if we change the HTTP implementation.