diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index a1fdffc35f226..fec13e94648f8 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -21,7 +21,7 @@ use tracing::span; use crate::core::backend::CodegenBackendKind; use crate::core::build_steps::gcc::{Gcc, GccOutput, GccTargetPair}; -use crate::core::build_steps::llvm::{LlvmFromCi, prebuilt_llvm_output}; +use crate::core::build_steps::llvm::{LlvmFromCi, LlvmKind, prebuilt_llvm_output}; use crate::core::build_steps::tool::{RustcPrivateCompilers, SourceType, copy_lld_artifacts}; use crate::core::build_steps::{dist, llvm}; use crate::core::builder::{ @@ -2191,7 +2191,7 @@ impl CommandLineStep for Assemble { let src_path = llvm_bin_dir.join(&tool_exe); // When using `download-ci-llvm`, some of the tools may not exist, so skip trying to copy them. - if !src_path.exists() && builder.config.llvm_ci_mode.download_from_ci() { + if !src_path.exists() && llvm_output.kind() == LlvmKind::DownloadedFromCi { eprintln!("{} does not exist; skipping copy", src_path.display()); continue; } diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index a266fba781e1a..3bbb13f08bd12 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -26,7 +26,7 @@ use crate::core::build_steps::compile::{ use crate::core::build_steps::doc::DocumentationFormat; use crate::core::build_steps::gcc::GccTargetPair; use crate::core::build_steps::llvm::{ - LLVM_CI_LINK_TYPE_PATH, LlvmBuildStatus, get_llvm_build_status, + LLVM_CI_LINK_TYPE_PATH, LlvmBuildStatus, LlvmKind, get_llvm_build_status, }; use crate::core::build_steps::tool::{ self, RustcPrivateCompilers, ToolTargetBuildMode, get_tool_target_compiler, @@ -2525,12 +2525,7 @@ fn maybe_install_llvm( // If the LLVM is coming from ourselves (just from CI) though, we // still want to install it, as it otherwise won't be available. - // FIXME: this should be simplified once we stop pre-setting LLVM CI llvm-config during - // config parsing. - let is_system_llvm = - builder.config.target_config.get(&target).and_then(|t| t.llvm_config.as_ref()).is_some() - && !(builder.config.llvm_ci_mode.download_from_ci() - && builder.config.is_host_target(target)); + let is_system_llvm = llvm.llvm_output().kind() == LlvmKind::External; if is_system_llvm { trace!("system LLVM requested, no install"); return false; @@ -2712,11 +2707,10 @@ impl CommandLineStep for LlvmTools { let target = self.target; + let llvm_output = builder.ensure(crate::core::build_steps::llvm::Llvm { target }); + // Run only if a custom llvm-config is not used - if let Some(config) = builder.config.target_config.get(&target) - && !builder.config.llvm_ci_mode.download_from_ci() - && config.llvm_config.is_some() - { + if llvm_output.kind() == LlvmKind::External { builder.info(&format!("Skipping LlvmTools ({target}): external LLVM")); return None; } @@ -2725,8 +2719,6 @@ impl CommandLineStep for LlvmTools { builder.require_submodule("src/llvm-project", None); } - let llvm_output = builder.ensure(crate::core::build_steps::llvm::Llvm { target }); - let mut tarball = Tarball::new(builder, "llvm-tools", &target.triple); tarball.set_overlay(OverlayKind::Llvm); tarball.is_preview(true); @@ -2738,7 +2730,7 @@ impl CommandLineStep for LlvmTools { for tool in tools_to_install(&builder.paths) { let exe = src_bindir.join(exe(tool, target)); // When using `download-ci-llvm`, some of the tools may not exist, so skip trying to copy them. - if !exe.exists() && builder.config.llvm_ci_mode.download_from_ci() { + if !exe.exists() && llvm_output.kind() == LlvmKind::DownloadedFromCi { eprintln!("{} does not exist; skipping copy", exe.display()); continue; } diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index 81e0726f414cc..9d6e27ffc698e 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -32,7 +32,7 @@ use crate::utils::helpers::{ /// Path where a file containing the link type (dynamic or static) is stored in the LLVM CI tarball. pub const LLVM_CI_LINK_TYPE_PATH: &str = "link-type.txt"; -#[derive(Copy, Clone)] +#[derive(Copy, Clone, PartialEq, Eq)] pub enum LlvmKind { /// The LLVM was built from in-tree sources BuiltLocally, @@ -256,26 +256,45 @@ fn llvm_output_dir(builder: &Builder<'_>, target: TargetSelection) -> PathBuf { } fn try_download_ci_llvm(builder: &Builder<'_>, target: TargetSelection) -> Option { - match builder.config.llvm_ci_mode { - LlvmCiMode::BuildLocally => return None, - LlvmCiMode::DownloadFromCi => {} + if builder.config.llvm_ci_mode.requests_download_from_ci() + && let Some(config) = builder.config.target_config.get(&target) + { + if config.llvm_config.is_some() { + panic!( + "Cannot configure `llvm-config` for {target} when using `llvm.download-ci-llvm`", + ); + } + if config.llvm_filecheck.is_some() { + panic!( + "Cannot configure `llvm-filecheck` for {target} when using `llvm.download-ci-llvm`" + ); + } } - // FIXME: this should eventually be relaxed - if target != builder.host_target { - crate::debug!("LLVM not available on CI for non-host target {target}"); - return None; + match builder.config.llvm_ci_mode { + LlvmCiMode::BuildLocally => return None, + LlvmCiMode::Download => {} + LlvmCiMode::DownloadIfUnchanged => { + builder.config.update_submodule("src/llvm-project"); + + // Check for untracked changes in `src/llvm-project` and other important places. + let has_changes = builder.config.has_changes_from_upstream(LLVM_INVALIDATION_PATHS); + if has_changes { + builder.info("Warning: LLVM will not be downloaded because of local changes"); + return None; + } + } } if !is_ci_llvm_available_for_target(&target, builder.config.llvm_assertions) { - crate::debug!( - "LLVM not available on CI for target={target} and assertions={}", + builder.info(&format!( + "Warning: LLVM not available on CI for target={target} and assertions={}", builder.config.llvm_assertions - ); + )); return None; } - let ci_llvm = builder.config.maybe_download_host_ci_llvm()?; + let ci_llvm = builder.config.maybe_download_ci_llvm(target)?; let link_shared = if !builder.config.dry_run() { let link_type = t!( std::fs::read_to_string(ci_llvm.join(LLVM_CI_LINK_TYPE_PATH)), @@ -288,7 +307,7 @@ fn try_download_ci_llvm(builder: &Builder<'_>, target: TargetSelection) -> Optio Some(DownloadedLlvm { output: LlvmOutput { - llvm_config: ci_llvm.join("bin").join(exe("llvm-config", builder.host_target)), + llvm_config: ci_llvm.join("bin").join(exe("llvm-config", target)), link_shared, llvm_root_dir: ci_llvm, kind: LlvmKind::DownloadedFromCi, @@ -405,8 +424,12 @@ impl Step for LlvmFromCi { fn run(self, builder: &Builder<'_>) -> Self::Output { let llvm_ci = try_download_ci_llvm(builder, self.target)?; + // Sanity check - check_llvm_version(builder, llvm_ci.output.llvm_config()); + if builder.host_target == self.target { + check_llvm_version(builder, llvm_ci.output.llvm_config()); + } + Some(llvm_ci) } } diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs index 0e51a7c105478..2956f950c3e27 100644 --- a/src/bootstrap/src/core/builder/cargo.rs +++ b/src/bootstrap/src/core/builder/cargo.rs @@ -743,9 +743,9 @@ impl Builder<'_> { cargo.env("REAL_LIBRARY_PATH", e); } - // Set a flag for `check`/`clippy`/`fix`, so that certain build - // scripts can do less work (i.e. not building/requiring LLVM). - if matches!(cmd_kind, Kind::Check | Kind::Clippy | Kind::Fix) { + // Set a flag for `check`/`clippy`/`fix`, so that te rustc_llvm build + // script can do less work (i.e. not building C/C++ code and requiring LLVM). + if matches!(cmd_kind, Kind::Check | Kind::Clippy | Kind::Fix) && mode == Mode::Rustc { // If we've not yet built LLVM, or it's stale, then bust // the rustc_llvm cache. That will always work, even though it // may mean that on the next non-check build we'll need to rebuild diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs index 0d7f4613723dc..69a3715d588c4 100644 --- a/src/bootstrap/src/core/builder/mod.rs +++ b/src/bootstrap/src/core/builder/mod.rs @@ -15,6 +15,7 @@ use tracing::instrument; pub(crate) use self::cargo::{Cargo, apply_pgo, cargo_profile_var}; use crate::core::build_steps::compile::{Std, StdLink, looks_like_codegen_backend}; +use crate::core::build_steps::llvm::{LlvmKind, get_llvm_build_status}; use crate::core::build_steps::tool::RustcPrivateCompilers; use crate::core::build_steps::{ check, clean, clippy, compile, dist, doc, gcc, install, llvm, run, setup, test, tool, vendor, @@ -1377,7 +1378,10 @@ Alternatively, you can set `build.local-rebuild=true` and use a stage0 compiler let mut dylib_dirs = vec![self.rustc_libdir(compiler)]; // Ensure that the downloaded LLVM libraries can be found. - if self.config.llvm_ci_mode.download_from_ci() { + // FIXME: the libraries should be added elsewhere, not in this function... + if get_llvm_build_status(self, compiler.host).llvm_output().kind() + == LlvmKind::DownloadedFromCi + { let ci_llvm_lib = self.out.join(compiler.host).join("ci-llvm").join("lib"); dylib_dirs.push(ci_llvm_lib); } diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index 9d0a7aa466c9e..46782830a49b7 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -5,6 +5,7 @@ use build_helper::stage0_parser::parse_stage0_file; use llvm::get_llvm_build_status; use super::*; +use crate::core::build_steps::llvm::LlvmKind; use crate::core::config::Config; use crate::utils::cache::ExecutedStep; use crate::utils::helpers::get_host_target; @@ -293,15 +294,14 @@ fn test_prebuilt_llvm_config_path_resolution() { "#, ); - // CI-LLVM isn't always available; check if it's enabled before testing. - if config.llvm_ci_mode.download_from_ci() { - let sess = Session::new(config.clone()); - let builder = Builder::new(&sess); + let sess = Session::new(config.clone()); + let builder = Builder::new(&sess); - let actual = get_llvm_build_status(&builder, builder.config.host_target) - .llvm_output() - .llvm_config() - .to_path_buf(); + let llvm = get_llvm_build_status(&builder, builder.config.host_target); + let llvm = llvm.llvm_output(); + // CI-LLVM isn't always available; check if it's enabled before testing. + if llvm.kind() == LlvmKind::DownloadedFromCi { + let actual = llvm.llvm_config().to_path_buf(); let expected = builder .out .join(builder.config.host_target) diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 6df39a0927738..71fe7ce2e75c1 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -27,11 +27,9 @@ use serde::Deserialize; use tracing::{instrument, span}; use crate::core::backend::CodegenBackendKind; -use crate::core::build_steps::llvm; use crate::core::build_steps::llvm::{LLVM_INVALIDATION_PATHS, LlvmKind, LlvmOutput}; use crate::core::build_steps::test::failed_tests::collect_previously_failed_tests; use crate::core::config::flags::{Color, Flags, Subcommand, Warnings}; -use crate::core::config::macros::check_ci_llvm; use crate::core::config::target_selection::TargetSelectionList; use crate::core::config::toml::TomlConfig; use crate::core::config::toml::build::{Build, Tool}; @@ -1082,23 +1080,37 @@ impl Config { } } - let llvm_from_ci = parse_download_ci_llvm( - &dwn_ctx, - &rust_info, - &download_rustc_commit, - llvm_download_ci_llvm, - llvm_assertions, - ); - - // FIXME: llvm_ci_mode should eventually represent what was used in the config, not the - // dynamic value used for determining whether it is actually available. - let llvm_ci_mode = - if llvm_from_ci { LlvmCiMode::DownloadFromCi } else { LlvmCiMode::BuildLocally }; + let llvm_ci_mode = parse_download_ci_llvm(llvm_download_ci_llvm); - let is_host_system_llvm = - target_config.get(&host_target).and_then(|c| c.llvm_config.as_ref()).is_some(); + // Sanity checks + match llvm_ci_mode { + LlvmCiMode::DownloadIfUnchanged => { + if rust_info.is_from_tarball() { + // Git is needed for running "if-unchanged" logic. + panic!("ERROR: 'if-unchanged' is only compatible with Git managed sources."); + } + } + LlvmCiMode::Download => { + if cfg!(not(test)) + && ci_env.is_running_in_ci() + && CiEnv::is_rust_lang_managed_ci_job() + { + // On rust-lang CI, we must always rebuild LLVM if there were any modifications to it + panic!( + "`llvm.download-ci-llvm` cannot be set to `true` on CI. Use `if-unchanged` instead." + ); + } + } + LlvmCiMode::BuildLocally => { + if 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`." + ); + } + } + } - if llvm_from_ci { + if llvm_ci_mode.requests_download_from_ci() { let warn = |option: &str| { println!( "WARNING: `{option}` will only be used on `compiler/rustc_llvm` build, not for the LLVM build." @@ -1131,13 +1143,11 @@ impl Config { "HELP: To use `llvm.libzstd` for LLVM/LLD builds, set `download-ci-llvm` option to false." ); } - - if let Some(target) = target_config.get(&host_target) { - check_ci_llvm!(target.llvm_config); - check_ci_llvm!(target.llvm_filecheck); - } } + let is_host_system_llvm = + target_config.get(&host_target).and_then(|c| c.llvm_config.as_ref()).is_some(); + for (target, linker_override) in default_linux_linker_overrides() { // If the user overrode the default Linux linker, do not apply bootstrap defaults if targets_with_user_linker_override.contains(&target) { @@ -1409,8 +1419,7 @@ NOTE: Please add `--stage 2` to your command line, or if you're sure you want to // If we're building with ThinLTO on, by default we want to link // to LLVM shared, to avoid re-doing ThinLTO (which happens in // the link step) with each stage. - let llvm_link_shared = - llvm_link_shared.or((!llvm_from_ci && llvm_thin_lto.unwrap_or(false)).then_some(true)); + let llvm_link_shared = llvm_link_shared.or(llvm_thin_lto.unwrap_or(false).then_some(true)); Config { // tidy-alphabetical-start @@ -1760,18 +1769,15 @@ NOTE: Please add `--stage 2` to your command line, or if you're sure you want to Some(commit) => { self.download_ci_rustc(commit); - // CI-rustc can't be used without CI-LLVM. If `self.llvm_from_ci` is false, it means the "if-unchanged" - // logic has detected some changes in the LLVM submodule (download-ci-llvm=false can't happen here as - // we don't allow it while parsing the configuration). - if !self.llvm_ci_mode.download_from_ci() { - // This happens when LLVM submodule is updated in CI, we should disable ci-rustc without an error - // to not break CI. For non-CI environments, we should return an error. - if self.is_running_on_ci() { - println!("WARNING: LLVM submodule has changes, `download-rustc` will be disabled."); - return None; - } else { - panic!("ERROR: LLVM submodule has changes, `download-rustc` can't be used."); - } + let llvm_ci_requested = self.llvm_ci_mode.requests_download_from_ci(); + // CI-rustc can't be used without CI-LLVM. If LLVM Ci is requested, but the + // LLVM submodule has changes, it is an error. + // FIXME: this whole logic should be refactored to not use + // `has_changes_from_upstream` explicitly + if llvm_ci_requested && self.has_changes_from_upstream(LLVM_INVALIDATION_PATHS) { + // download-ci-rustc should not be used on CI at the moment + assert!(self.is_running_on_ci()); + panic!("ERROR: LLVM submodule has changes, `download-rustc` can't be used."); } if let Some(config_path) = &self.config { @@ -2457,62 +2463,17 @@ 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 { - let dwn_ctx = dwn_ctx.as_ref(); +pub fn parse_download_ci_llvm(download_ci_llvm: Option) -> LlvmCiMode { let download_ci_llvm = download_ci_llvm.unwrap_or(StringOrBool::Bool(true)); - - let if_unchanged = || { - 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."); - helpers::exit_process(1); - } - - // Fetching the LLVM submodule is unnecessary for self-tests. - if cfg!(not(test)) { - 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); - - // Return false if there are untracked changes, otherwise check if CI LLVM is available. - if has_changes { - false - } else { - llvm::is_ci_llvm_available_for_target(&dwn_ctx.host_target, asserts) - } - }; - match download_ci_llvm { StringOrBool::Bool(b) => { - 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`." - ); - } - - if cfg!(not(test)) - && b - && dwn_ctx.is_running_on_ci() - && CiEnv::is_rust_lang_managed_ci_job() - { - // On rust-lang CI, we must always rebuild LLVM if there were any modifications to it - panic!( - "`llvm.download-ci-llvm` cannot be set to `true` on CI. Use `if-unchanged` instead." - ); + if b { + LlvmCiMode::Download + } else { + LlvmCiMode::BuildLocally } - - // If download-ci-llvm=true we also want to check that CI llvm is available - b && llvm::is_ci_llvm_available_for_target(&dwn_ctx.host_target, asserts) } - StringOrBool::String(s) if s == "if-unchanged" => if_unchanged(), + StringOrBool::String(s) if s == "if-unchanged" => LlvmCiMode::DownloadIfUnchanged, StringOrBool::String(other) => { panic!("unrecognized option for download-ci-llvm: {other:?}") } diff --git a/src/bootstrap/src/core/config/macros.rs b/src/bootstrap/src/core/config/macros.rs index 3c3805968d0c1..37c04d251cb4e 100644 --- a/src/bootstrap/src/core/config/macros.rs +++ b/src/bootstrap/src/core/config/macros.rs @@ -136,15 +136,4 @@ macro_rules! define_config { } } -macro_rules! check_ci_llvm { - ($name:expr) => { - assert!( - $name.is_none(), - "setting {} is incompatible with download-ci-llvm.", - stringify!($name).replace("_", "-") - ); - }; -} - -pub(crate) use check_ci_llvm; pub(crate) use define_config; diff --git a/src/bootstrap/src/core/config/mod.rs b/src/bootstrap/src/core/config/mod.rs index d8ce0161da23e..1093f0c1d035a 100644 --- a/src/bootstrap/src/core/config/mod.rs +++ b/src/bootstrap/src/core/config/mod.rs @@ -373,17 +373,22 @@ pub enum GccCiMode { pub enum LlvmCiMode { /// Build LLVM from the local `src/llvm-project` submodule. BuildLocally, + /// Try to download LLVM from CI if the `src/llvm-project` submodule + /// (and some other files that affect LLVM's build) are not modified in git. + DownloadIfUnchanged, /// Try to download LLVM from CI. /// If it is not available on CI, it will be built locally instead. #[default] - DownloadFromCi, + Download, } impl LlvmCiMode { - pub fn download_from_ci(&self) -> bool { + /// Return true if the user has requested LLVM to be downloaded from CI. + /// **Note:** this does not mean that it will be actually downloaded. + pub fn requests_download_from_ci(&self) -> bool { match self { LlvmCiMode::BuildLocally => false, - LlvmCiMode::DownloadFromCi => true, + LlvmCiMode::Download | LlvmCiMode::DownloadIfUnchanged => true, } } } diff --git a/src/bootstrap/src/core/config/tests.rs b/src/bootstrap/src/core/config/tests.rs index 7afaa6997514b..6318042602dbe 100644 --- a/src/bootstrap/src/core/config/tests.rs +++ b/src/bootstrap/src/core/config/tests.rs @@ -11,13 +11,15 @@ use clap::CommandFactory; use super::flags::Flags; use super::toml::change_id::ChangeIdWrapper; use super::toml::rust::parse_codegen_backends; -use super::{Config, DebuggerPath, RUSTC_IF_UNCHANGED_ALLOWED_PATHS}; +use super::{Config, DebuggerPath, LlvmCiMode, RUSTC_IF_UNCHANGED_ALLOWED_PATHS}; use crate::core::build_steps::clippy::{LintConfig, get_clippy_rules_in_order}; -use crate::core::build_steps::llvm::LLVM_INVALIDATION_PATHS; +use crate::core::build_steps::llvm::{LLVM_INVALIDATION_PATHS, LlvmKind, get_llvm_build_status}; +use crate::core::builder::Builder; use crate::core::config::flags::Subcommand; use crate::core::config::{ BootstrapOverrideLld, ChangeId, CompilerBuiltins, Target, TargetSelection, }; +use crate::core::session::Session; use crate::utils::tests::TestCtx; use crate::utils::tests::git::git_test; @@ -35,21 +37,28 @@ fn modified(upstream: impl Into, changes: &[&str]) -> PathFreshness { #[test] fn download_ci_llvm() { let config = TestCtx::new().config("check").create_config(); - assert!(!config.llvm_ci_mode.download_from_ci()); + assert_eq!(config.llvm_ci_mode, LlvmCiMode::BuildLocally); // this doesn't make sense, as we are overriding it later. let if_unchanged_config = TestCtx::new() .config("check") .with_default_toml_config("llvm.download-ci-llvm = \"if-unchanged\"") .create_config(); - if if_unchanged_config.llvm_ci_mode.download_from_ci() && if_unchanged_config.is_running_on_ci() - { - let has_changes = if_unchanged_config.has_changes_from_upstream(LLVM_INVALIDATION_PATHS); - - assert!( - !has_changes, - "CI LLVM can't be enabled with 'if-unchanged' while there are changes in LLVM submodule." - ); + if if_unchanged_config.is_running_on_ci() { + let build = Session::new(config.clone()); + let builder = Builder::new(&build); + + let llvm = get_llvm_build_status(&builder, builder.config.host_target); + let llvm = llvm.llvm_output(); + if llvm.kind() == LlvmKind::DownloadedFromCi { + let has_changes = + if_unchanged_config.has_changes_from_upstream(LLVM_INVALIDATION_PATHS); + + assert!( + !has_changes, + "CI LLVM can't be enabled with 'if-unchanged' while there are changes in LLVM submodule." + ); + } } } @@ -163,7 +172,7 @@ fn override_toml() { .collect(), "setting dictionary value" ); - assert!(!config.llvm_ci_mode.download_from_ci()); + assert!(matches!(config.llvm_ci_mode, LlvmCiMode::BuildLocally)); assert!(!config.download_rustc()); } diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs index 29f0810b972bb..94d5e6b02ba42 100644 --- a/src/bootstrap/src/core/download.rs +++ b/src/bootstrap/src/core/download.rs @@ -269,15 +269,15 @@ impl Config { download_component(dwn_ctx, &self.out, mode, filename, prefix, key, destination); } - /// Attempts to download LLVM from CI for the **host target**. + /// Attempts to download LLVM from CI for the given **target**. /// Returns a path to the downloaded and extracted directory. - pub(crate) fn maybe_download_host_ci_llvm(&self) -> Option { + pub(crate) fn maybe_download_ci_llvm(&self, target: TargetSelection) -> Option { // Never try to download CI LLVM during unit tests. if cfg!(test) { return None; } - let llvm_root = self.out.join(self.host_target).join("ci-llvm"); + let llvm_root = self.out.join(target).join("ci-llvm"); let llvm_freshness = detect_llvm_freshness(self, self.rust_info.is_managed_git_subrepository()); self.do_if_verbose(|| { @@ -297,7 +297,7 @@ impl Config { let stamp_key = format!("{}{}", llvm_sha, self.llvm_assertions); let llvm_stamp = BuildStamp::new(&llvm_root).with_prefix("llvm").add_stamp(stamp_key); if !llvm_stamp.is_up_to_date() && !self.dry_run() { - self.download_ci_llvm(&llvm_root, &llvm_sha); + self.download_ci_llvm(&llvm_root, target, &llvm_sha); if self.should_fix_bins_and_dylibs() { for entry in t!(fs::read_dir(llvm_root.join("bin"))) { @@ -316,7 +316,7 @@ impl Config { let now = std::time::SystemTime::now(); let file_times = fs::FileTimes::new().set_accessed(now).set_modified(now); - let llvm_config = llvm_root.join("bin").join(exe("llvm-config", self.host_target)); + let llvm_config = llvm_root.join("bin").join(exe("llvm-config", target)); t!(crate::utils::helpers::set_file_times(llvm_config, file_times)); if self.should_fix_bins_and_dylibs() { @@ -354,13 +354,13 @@ impl Config { Some(llvm_root) } - fn download_ci_llvm(&self, llvm_root: &Path, llvm_sha: &str) { + fn download_ci_llvm(&self, llvm_root: &Path, target: TargetSelection, llvm_sha: &str) { // For unit tests, downloading should have been blocked by `maybe_download_ci_llvm`. assert!(cfg!(not(test)), "unit tests shouldn't be downloading CI LLVM"); let llvm_assertions = self.llvm_assertions; - let cache_prefix = format!("llvm-{llvm_sha}-{llvm_assertions}"); + let cache_prefix = format!("llvm-{}-{llvm_sha}-{llvm_assertions}", target.triple); let cache_dst = self.bootstrap_cache_path.as_ref().cloned().unwrap_or_else(|| self.out.join("cache")); @@ -374,20 +374,23 @@ impl Config { &self.stage0_metadata.config.artifacts_server }; let version = self.artifact_version_part(llvm_sha); - let filename = format!("rust-dev-{}-{}.tar.xz", version, self.host_target.triple); + let filename = format!("rust-dev-{}-{}.tar.xz", version, target.triple); let tarball = rustc_cache.join(&filename); if !tarball.exists() { - let help_on_error = "ERROR: failed to download llvm from ci + let help_on_error = format!( + "ERROR: failed to download llvm from CI for `{target}` HELP: There could be two reasons behind this: - 1) The host triple is not supported for `download-ci-llvm`. + 1) `{target}` is not supported for `download-ci-llvm`. 2) Old builds get deleted after a certain time. HELP: In either case, disable `download-ci-llvm` in your bootstrap.toml: [llvm] download-ci-llvm = false - "; - self.download_file(&format!("{base}/{llvm_sha}/{filename}"), &tarball, help_on_error); + ", + target = target.triple + ); + self.download_file(&format!("{base}/{llvm_sha}/{filename}"), &tarball, &help_on_error); } self.unpack(&tarball, llvm_root, "rust-dev"); } diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs index 27638810fb7bb..90c33d8d0e87f 100644 --- a/src/bootstrap/src/core/sanity.rs +++ b/src/bootstrap/src/core/sanity.rs @@ -110,7 +110,7 @@ pub(crate) fn check(sess: &mut Session) { if cfg!(not(test)) && !sess.config.dry_run() && !sess.host_target.is_msvc() - && sess.config.llvm_ci_mode.download_from_ci() + && sess.config.llvm_ci_mode.requests_download_from_ci() { let builder = Builder::new(sess); let libcxx_version = builder.ensure(tool::LibcxxVersionTool { target: sess.host_target }); @@ -138,7 +138,7 @@ pub(crate) fn check(sess: &mut Session) { } // We need cmake, but only if we're actually building LLVM or sanitizers. - let building_llvm = !sess.config.llvm_ci_mode.download_from_ci() + let building_llvm = !sess.config.llvm_ci_mode.requests_download_from_ci() && !sess.config.local_rebuild && sess.hosts.iter().any(|host| { sess.config.llvm_enabled(*host)