diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index 087a395a067f0..b3ae5bfbd74f2 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -166,10 +166,16 @@ pub fn prebuilt_llvm_config( static STAMP_HASH_MEMO: OnceLock = OnceLock::new(); let smart_stamp_hash = STAMP_HASH_MEMO.get_or_init(|| { + // Key LLVM on the commit hash and the configuration from bootstrap.toml. + let hash_input = format!( + "sha={sha}\nkey={key}", + sha = builder.in_tree_llvm_info.sha().unwrap_or_default(), + key = builder.config.llvm_cache_key, + ); generate_smart_stamp_hash( builder, &builder.config.src.join("src/llvm-project"), - builder.in_tree_llvm_info.sha().unwrap_or_default(), + &hash_input, ) }); diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 5a9c7264c006f..0297907057ef9 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -156,6 +156,9 @@ pub struct Config { pub backtrace_on_ice: bool, // llvm codegen options + /// Key used to decide when to rebuild LLVM. + pub llvm_cache_key: String, + pub llvm_assertions: bool, pub llvm_tests: bool, pub llvm_enzyme: bool, @@ -595,6 +598,8 @@ impl Config { rustflags: rust_rustflags, } = toml.rust.unwrap_or_default(); + let llvm = toml.llvm.unwrap_or_default(); + let llvm_cache_key = llvm.cache_key(); let Llvm { optimize: llvm_optimize, thin_lto: llvm_thin_lto, @@ -625,7 +630,7 @@ impl Config { enable_warnings: llvm_enable_warnings, download_ci_llvm: llvm_download_ci_llvm, build_config: llvm_build_config, - } = toml.llvm.unwrap_or_default(); + } = llvm; let Dist { sign_folder: dist_sign_folder, @@ -1401,6 +1406,7 @@ impl Config { llvm_assertions, llvm_bitcode_linker_enabled: rust_llvm_bitcode_linker.unwrap_or(false), llvm_build_config: llvm_build_config.clone().unwrap_or(Default::default()), + llvm_cache_key, llvm_cflags, llvm_clang: llvm_clang.unwrap_or(false), llvm_clang_cl, diff --git a/src/bootstrap/src/core/config/toml/llvm.rs b/src/bootstrap/src/core/config/toml/llvm.rs index 5f08884e4ef71..ad5db7ebe870d 100644 --- a/src/bootstrap/src/core/config/toml/llvm.rs +++ b/src/bootstrap/src/core/config/toml/llvm.rs @@ -43,6 +43,95 @@ define_config! { } } +impl Llvm { + /// A key that is used to determine whether LLVM should be rebuilt. + pub(crate) fn cache_key(&self) -> String { + let helper = || { + let mut key = String::with_capacity(512); + + let Self { + optimize, + thin_lto, + release_debuginfo, + assertions, + tests, + enzyme, + plugins, + static_libstdcpp, + libzstd, + ninja, + targets, + experimental_targets, + link_jobs, + link_shared, + version_suffix, + clang_cl, + cflags, + cxxflags, + ldflags, + use_libcxx, + use_linker, + allow_old_toolchain, + offload, + polly, + offload_clang_dir, + clang, + enable_warnings, + build_config, + download_ci_llvm: _, + } = self; + + use std::fmt::Write; + write!(key, "{:?}", optimize)?; + write!(key, "{:?}", thin_lto)?; + write!(key, "{:?}", release_debuginfo)?; + write!(key, "{:?}", assertions)?; + write!(key, "{:?}", tests)?; + write!(key, "{:?}", enzyme)?; + write!(key, "{:?}", plugins)?; + write!(key, "{:?}", static_libstdcpp)?; + write!(key, "{:?}", libzstd)?; + write!(key, "{:?}", ninja)?; + write!(key, "{:?}", targets)?; + write!(key, "{:?}", experimental_targets)?; + write!(key, "{:?}", link_jobs)?; + write!(key, "{:?}", link_shared)?; + write!(key, "{:?}", version_suffix)?; + write!(key, "{:?}", clang_cl)?; + write!(key, "{:?}", cflags)?; + write!(key, "{:?}", cxxflags)?; + write!(key, "{:?}", ldflags)?; + write!(key, "{:?}", use_libcxx)?; + write!(key, "{:?}", use_linker)?; + write!(key, "{:?}", allow_old_toolchain)?; + write!(key, "{:?}", offload)?; + write!(key, "{:?}", polly)?; + write!(key, "{:?}", offload_clang_dir)?; + write!(key, "{:?}", clang)?; + write!(key, "{:?}", enable_warnings)?; + + match build_config { + None => { + write!(key, "None")?; + } + Some(c) => { + let mut build_config = c.iter().collect::>(); + build_config.sort(); + + for (k, v) in build_config { + write!(key, "{}: {}", k, v)?; + } + } + } + + Ok::<_, std::fmt::Error>(key) + }; + + // write! to a String always succeeds unless OOM. + helper().unwrap() + } +} + /// Compares the current `Llvm` options against those in the CI LLVM builder and detects any incompatible options. /// It does this by destructuring the `Llvm` instance to make sure every `Llvm` field is covered and not missing. #[cfg(not(test))]