diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 652e797538223..23cdf5ad9bf7e 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -1425,13 +1425,13 @@ fn rustc_llvm_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelect if builder.config.llvm_enzyme { cargo.env("LLVM_ENZYME", "1"); } - let llvm::LlvmResult { host_llvm_config, .. } = builder.ensure(llvm::Llvm { target }); + let llvm_output = builder.ensure(llvm::Llvm { target }); if builder.config.llvm_offload { builder.ensure(llvm::OmpOffload { target }); cargo.env("LLVM_OFFLOAD", "1"); } - cargo.env("LLVM_CONFIG", &host_llvm_config); + cargo.env("LLVM_CONFIG", &llvm_output.host_llvm_config); // Some LLVM linker flags (-L and -l) may be needed to link `rustc_llvm`. Its build script // expects these to be passed via the `LLVM_LINKER_FLAGS` env variable, separated by @@ -2122,11 +2122,11 @@ impl CommandLineStep for Assemble { trace!("target_compiler.host" = ?target_compiler.host, "LLVM enabled"); let target = target_compiler.host; - let llvm::LlvmResult { host_llvm_config, .. } = builder.ensure(llvm::Llvm { target }); + let llvm_output = builder.ensure(llvm::Llvm { target }); if !builder.config.dry_run() && builder.config.llvm_tools_enabled { trace!("LLVM tools enabled"); - let host_llvm_bin_dir = command(&host_llvm_config) + let host_llvm_bin_dir = command(&llvm_output.host_llvm_config) .arg("--bindir") .cached() .run_capture_stdout(builder) @@ -2153,7 +2153,7 @@ impl CommandLineStep for Assemble { // relative to its output build directory, and then apply it to the target // LLVM output build directory. let host_llvm_out = builder.llvm_out(builder.host_target); - let target_llvm_out = builder.llvm_out(target); + let target_llvm_out = llvm_output.root_dir(); if let Ok(relative_path) = Path::new(&host_llvm_bin_dir).strip_prefix(host_llvm_out) { diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index 9028a7a340ca7..abe6100c4e3fc 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -2527,7 +2527,7 @@ fn maybe_install_llvm( } } !builder.config.dry_run() - } else if let llvm::LlvmBuildStatus::AlreadyBuilt(llvm::LlvmResult { + } else if let llvm::LlvmBuildStatus::AlreadyBuilt(llvm::LlvmOutput { host_llvm_config, .. }) = llvm::prebuilt_llvm_config(builder, target, true) { @@ -2678,7 +2678,7 @@ impl CommandLineStep for LlvmTools { builder.require_submodule("src/llvm-project", None); } - builder.ensure(crate::core::build_steps::llvm::Llvm { target }); + 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); @@ -2686,7 +2686,7 @@ impl CommandLineStep for LlvmTools { if builder.config.llvm_tools_enabled { // Prepare the image directory - let src_bindir = builder.llvm_out(target).join("bin"); + let src_bindir = llvm_output.root_dir().join("bin"); let dst_bindir = format!("lib/rustlib/{}/bin", target.triple); for tool in tools_to_install(&builder.paths) { let exe = src_bindir.join(exe(tool, target)); @@ -2859,9 +2859,9 @@ impl CommandLineStep for RustDev { // LLVM requires a shared object symlink to exist on some platforms. tarball.permit_symlinks(true); - builder.ensure(crate::core::build_steps::llvm::Llvm { target }); + let llvm_output = builder.ensure(crate::core::build_steps::llvm::Llvm { target }); - let src_bindir = builder.llvm_out(target).join("bin"); + let src_bindir = llvm_output.root_dir().join("bin"); // If updating this, you likely want to change // src/bootstrap/download-ci-llvm-stamp as well, otherwise local users // will not pick up the extra file until LLVM gets bumped. @@ -2888,12 +2888,13 @@ impl CommandLineStep for RustDev { } } - tarball.add_file(builder.llvm_filecheck(target), "bin", FileType::Executable); + let filecheck = builder.ensure(llvm::FileCheck { target }); + tarball.add_file(filecheck, "bin", FileType::Executable); // Copy the include directory as well; needed mostly to build // librustc_llvm properly (e.g., llvm-config.h is in here). But also // just broadly useful to be able to link against the bundled LLVM. - tarball.add_dir(builder.llvm_out(target).join("include"), "include"); + tarball.add_dir(llvm_output.root_dir().join("include"), "include"); // Copy libLLVM.so to the target lib dir as well, so the RPATH like // `$ORIGIN/../lib` can find it. It may also be used as a dependency diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index d3276cfb5371b..2c669f312ddf4 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -17,7 +17,7 @@ use std::{env, fs}; use build_helper::git::PathFreshness; use crate::core::build_steps::llvm; -use crate::core::builder::{Builder, CommandLineStep, RunConfig, ShouldRun, StepMetadata}; +use crate::core::builder::{Builder, CommandLineStep, RunConfig, ShouldRun, Step, StepMetadata}; use crate::core::config::{Config, LlvmPgoGenerationMode, TargetSelection}; use crate::utils::build_stamp::{BuildStamp, generate_smart_stamp_hash}; use crate::utils::exec::command; @@ -26,25 +26,36 @@ use crate::utils::helpers::{ }; use crate::{CLang, GitRepo, Kind, exit, trace}; +/// Result of building or downloading LLVM artifacts. #[derive(Clone)] -pub struct LlvmResult { +pub struct LlvmOutput { /// Path to llvm-config binary. /// NB: This is always the host llvm-config! pub host_llvm_config: PathBuf, - /// Path to LLVM cmake directory for the target. - pub llvm_cmake_dir: PathBuf, + llvm_root_dir: PathBuf, } -pub struct Meta { +impl LlvmOutput { + /// Directory containing the built LLVM artifacts. + /// Contains `bin`/`lib` directories. + pub fn root_dir(&self) -> &Path { + &self.llvm_root_dir + } + + /// Path to LLVM cmake directory. + pub fn cmake_dir(&self) -> PathBuf { + self.llvm_root_dir.join("lib").join("cmake").join("llvm") + } +} + +pub struct LlvmBuildInfo { stamp: BuildStamp, - res: LlvmResult, - out_dir: PathBuf, - root: String, + output: LlvmOutput, } pub enum LlvmBuildStatus { - AlreadyBuilt(LlvmResult), - ShouldBuild(Meta), + AlreadyBuilt(LlvmOutput), + ShouldBuild(LlvmBuildInfo), } impl LlvmBuildStatus { @@ -56,10 +67,10 @@ impl LlvmBuildStatus { } #[cfg(test)] - pub fn llvm_result(&self) -> &LlvmResult { + pub fn llvm_result(&self) -> &LlvmOutput { match self { LlvmBuildStatus::AlreadyBuilt(res) => res, - LlvmBuildStatus::ShouldBuild(meta) => &meta.res, + LlvmBuildStatus::ShouldBuild(meta) => &meta.output, } } } @@ -130,13 +141,10 @@ pub fn prebuilt_llvm_config( { check_llvm_version(builder, s); let host_llvm_config = s.to_path_buf(); - let mut llvm_cmake_dir = host_llvm_config.clone(); - llvm_cmake_dir.pop(); - llvm_cmake_dir.pop(); - llvm_cmake_dir.push("lib"); - llvm_cmake_dir.push("cmake"); - llvm_cmake_dir.push("llvm"); - return LlvmBuildStatus::AlreadyBuilt(LlvmResult { host_llvm_config, llvm_cmake_dir }); + let mut llvm_root_dir = host_llvm_config.clone(); + llvm_root_dir.pop(); + llvm_root_dir.pop(); + return LlvmBuildStatus::AlreadyBuilt(LlvmOutput { host_llvm_config, llvm_root_dir }); } if handle_submodule_when_needed { @@ -144,7 +152,6 @@ pub fn prebuilt_llvm_config( builder.config.update_submodule("src/llvm-project"); } - let root = "src/llvm-project/llvm"; let out_dir = builder.llvm_out(target); let build_llvm_config = if let Some(build_llvm_config) = builder @@ -160,8 +167,7 @@ pub fn prebuilt_llvm_config( llvm_config_ret_dir.join(exe("llvm-config", builder.config.host_target)) }; - let llvm_cmake_dir = out_dir.join("lib/cmake/llvm"); - let res = LlvmResult { host_llvm_config: build_llvm_config, llvm_cmake_dir }; + let res = LlvmOutput { host_llvm_config: build_llvm_config, llvm_root_dir: out_dir.clone() }; static STAMP_HASH_MEMO: OnceLock = OnceLock::new(); let smart_stamp_hash = STAMP_HASH_MEMO.get_or_init(|| { @@ -188,7 +194,7 @@ pub fn prebuilt_llvm_config( return LlvmBuildStatus::AlreadyBuilt(res); } - LlvmBuildStatus::ShouldBuild(Meta { stamp, res, out_dir, root: root.into() }) + LlvmBuildStatus::ShouldBuild(LlvmBuildInfo { stamp, output: res }) } /// Paths whose changes invalidate LLVM downloads. @@ -273,7 +279,7 @@ pub struct Llvm { } impl CommandLineStep for Llvm { - type Output = LlvmResult; + type Output = LlvmOutput; const IS_HOST: bool = true; @@ -286,7 +292,7 @@ impl CommandLineStep for Llvm { } /// Compile LLVM for `target`. - fn run(self, builder: &Builder<'_>) -> LlvmResult { + fn run(self, builder: &Builder<'_>) -> LlvmOutput { let target = self.target; let target_native = if self.target.starts_with("riscv") { // RISC-V target triples in Rust is not named the same as C compiler target triples. @@ -303,7 +309,7 @@ impl CommandLineStep for Llvm { }; // If LLVM has already been built or been downloaded through download-ci-llvm, we avoid building it again. - let Meta { stamp, res, out_dir, root } = match prebuilt_llvm_config(builder, target, true) { + let LlvmBuildInfo { stamp, output } = match prebuilt_llvm_config(builder, target, true) { LlvmBuildStatus::AlreadyBuilt(p) => return p, LlvmBuildStatus::ShouldBuild(m) => m, }; @@ -315,17 +321,13 @@ impl CommandLineStep for Llvm { let _guard = builder.msg_unstaged(Kind::Build, "LLVM", target); t!(stamp.remove()); let _time = helpers::timeit(builder); - t!(fs::create_dir_all(&out_dir)); + t!(fs::create_dir_all(output.root_dir())); // https://llvm.org/docs/CMake.html - let mut cfg = cmake::Config::new(builder.src.join(root)); + let mut cfg = cmake::Config::new(builder.src.join("src/llvm-project/llvm")); let mut ldflags = LdFlags::default(); - let profile = match (builder.config.llvm_optimize, builder.config.llvm_release_debuginfo) { - (false, _) => "Debug", - (true, false) => "Release", - (true, true) => "RelWithDebInfo", - }; + let profile = get_llvm_profile(&builder.config); // NOTE: remember to also update `bootstrap.example.toml` when changing the // defaults! @@ -347,7 +349,7 @@ impl CommandLineStep for Llvm { let enable_tests = if builder.config.llvm_tests { "ON" } else { "OFF" }; let enable_warnings = if builder.config.llvm_enable_warnings { "ON" } else { "OFF" }; - cfg.out_dir(&out_dir) + cfg.out_dir(output.root_dir()) .profile(profile) .define("LLVM_ENABLE_ASSERTIONS", assertions) .define("LLVM_UNREACHABLE_OPTIMIZE", "OFF") @@ -509,7 +511,7 @@ impl CommandLineStep for Llvm { // https://llvm.org/docs/HowToCrossCompileLLVM.html if !builder.config.is_host_target(target) { - let LlvmResult { host_llvm_config, .. } = + let LlvmOutput { host_llvm_config, .. } = builder.ensure(Llvm { target: builder.config.host_target }); if !builder.config.dry_run() { let llvm_bindir = command(&host_llvm_config) @@ -560,14 +562,14 @@ impl CommandLineStep for Llvm { } if builder.config.dry_run() { - return res; + return output; } cfg.build(); // Helper to find the name of LLVM's shared library on darwin and linux. let find_llvm_lib_name = |extension| { - let major = get_llvm_version_major(builder, &res.host_llvm_config); + let major = get_llvm_version_major(builder, &output.host_llvm_config); match &llvm_version_suffix { Some(version_suffix) => format!("libLLVM-{major}{version_suffix}.{extension}"), None => format!("libLLVM-{major}.{extension}"), @@ -580,7 +582,7 @@ impl CommandLineStep for Llvm { // link to make llvm-config happy. if builder.llvm_link_shared() && target.contains("apple-darwin") { let lib_name = find_llvm_lib_name("dylib"); - let lib_llvm = out_dir.join("build").join("lib").join(lib_name); + let lib_llvm = output.root_dir().join("build").join("lib").join(lib_name); if !lib_llvm.exists() { t!(builder.symlink_file("libLLVM.dylib", &lib_llvm)); } @@ -601,18 +603,18 @@ impl CommandLineStep for Llvm { crate::core::build_steps::compile::strip_debug( builder, target, - &out_dir.join("lib").join(&lib_name), + &output.root_dir().join("lib").join(&lib_name), ); crate::core::build_steps::compile::strip_debug( builder, target, - &out_dir.join("build").join("lib").join(&lib_name), + &output.root_dir().join("build").join("lib").join(&lib_name), ); } t!(stamp.write()); - res + output } fn metadata(&self) -> Option { @@ -636,6 +638,14 @@ pub fn get_llvm_version_major(builder: &Builder<'_>, llvm_config: &Path) -> u8 { major_str.parse().unwrap() } +fn get_llvm_profile(config: &Config) -> &'static str { + match (config.llvm_optimize, config.llvm_release_debuginfo) { + (false, _) => "Debug", + (true, false) => "Release", + (true, true) => "RelWithDebInfo", + } +} + fn check_llvm_version(builder: &Builder<'_>, llvm_config: &Path) { if builder.config.dry_run() { return; @@ -992,13 +1002,12 @@ impl CommandLineStep for OmpOffload { } let target = self.target; - let LlvmResult { host_llvm_config, llvm_cmake_dir } = - builder.ensure(Llvm { target: self.target }); + let llvm_output = builder.ensure(Llvm { target: self.target }); // Running cmake twice in the same folder is known to cause issues, like deleting existing // binaries. We therefore write our offload artifacts into it's own folder, instead of // using the llvm build dir. - let out_dir = builder.offload_out(target); + let out_dir = builder.out.join(self.target.triple).join("offload"); let mut files = vec![]; let lib_ext = std::env::consts::DLL_EXTENSION; @@ -1075,24 +1084,19 @@ impl CommandLineStep for OmpOffload { // Re-use the same flags as llvm to control the level of debug information // generated for offload. - let profile = - match (builder.config.llvm_optimize, builder.config.llvm_release_debuginfo) { - (false, _) => "Debug", - (true, false) => "Release", - (true, true) => "RelWithDebInfo", - }; + let profile = get_llvm_profile(&builder.config); trace!(?profile); // FIXME(offload): Once we move from OMP to Offload (Ol) APIs, we should drop the openmp // runtime to simplify our build. So far, these are still under development. cfg.out_dir(&out_dir) .profile(profile) - .env("LLVM_CONFIG_REAL", &host_llvm_config) + .env("LLVM_CONFIG_REAL", &llvm_output.host_llvm_config) .define("LLVM_ENABLE_ASSERTIONS", "ON") .define("LLVM_INCLUDE_TESTS", "OFF") .define("OFFLOAD_INCLUDE_TESTS", "OFF") .define("LLVM_ROOT", builder.llvm_out(target).join("build")) - .define("LLVM_DIR", llvm_cmake_dir.clone()) + .define("LLVM_DIR", llvm_output.cmake_dir()) .define("LLVM_DEFAULT_TARGET_TRIPLE", omp_target); if let Some(p) = clang_dir.clone() { cfg.define("Clang_DIR", p); @@ -1174,7 +1178,7 @@ impl CommandLineStep for Enzyme { return BuiltEnzyme { enzyme: builder.config.tempdir().join("enzyme-dryrun") }; } - let LlvmResult { host_llvm_config, llvm_cmake_dir } = builder.ensure(Llvm { target }); + let llvm_output = builder.ensure(Llvm { target }); // Enzyme links against LLVM. If we update the LLVM submodule libLLVM might get a new // version number, in which case Enzyme will now fail to find LLVM. By including the LLVM @@ -1191,10 +1195,11 @@ impl CommandLineStep for Enzyme { ) }); - let out_dir = builder.enzyme_out(target); + let out_dir = builder.out.join(self.target.triple).join("enzyme"); let stamp = BuildStamp::new(&out_dir).with_prefix("enzyme").add_stamp(smart_stamp_hash); - let llvm_version_major = llvm::get_llvm_version_major(builder, &host_llvm_config); + let llvm_version_major = + llvm::get_llvm_version_major(builder, &llvm_output.host_llvm_config); let lib_ext = std::env::consts::DLL_EXTENSION; let libenzyme = format!("libEnzyme-{llvm_version_major}"); let build_dir = out_dir.join(libdir(target)); @@ -1216,10 +1221,11 @@ impl CommandLineStep for Enzyme { return BuiltEnzyme { enzyme: dylib }; } + let llvm_cmake_dir = llvm_output.cmake_dir(); if !builder.config.dry_run() && !llvm_cmake_dir.is_dir() { builder.info(&format!( - "WARNING: {} does not exist, Enzyme build will likely fail", - llvm_cmake_dir.display() + "WARNING: {:?} does not exist, Enzyme build will likely fail", + llvm_cmake_dir )); } @@ -1249,16 +1255,12 @@ impl CommandLineStep for Enzyme { // Re-use the same flags as llvm to control the level of debug information // generated by Enzyme. // FIXME(ZuseZ4): Find a nicer way to use Enzyme Debug builds. - let profile = match (builder.config.llvm_optimize, builder.config.llvm_release_debuginfo) { - (false, _) => "Debug", - (true, false) => "Release", - (true, true) => "RelWithDebInfo", - }; + let profile = get_llvm_profile(&builder.config); trace!(?profile); cfg.out_dir(&out_dir) .profile(profile) - .env("LLVM_CONFIG_REAL", &host_llvm_config) + .env("LLVM_CONFIG_REAL", &llvm_output.host_llvm_config) .define("LLVM_ENABLE_ASSERTIONS", "ON") .define("ENZYME_EXTERNAL_SHARED_LIB", "ON") .define("ENZYME_BC_LOADER", "OFF") @@ -1305,13 +1307,13 @@ impl CommandLineStep for Lld { } let target = self.target; - let LlvmResult { host_llvm_config, llvm_cmake_dir } = builder.ensure(Llvm { target }); + let llvm_output = builder.ensure(Llvm { target }); // The `dist` step packages LLD next to LLVM's binaries for download-ci-llvm. The root path // we usually expect here is `./build/$triple/ci-llvm/`, with the binaries in its `bin` // subfolder. We check if that's the case, and if LLD's binary already exists there next to // `llvm-config`: if so, we can use it instead of building LLVM/LLD from source. - let ci_llvm_bin = host_llvm_config.parent().unwrap(); + let ci_llvm_bin = llvm_output.host_llvm_config.parent().unwrap(); if ci_llvm_bin.is_dir() && ci_llvm_bin.file_name().unwrap() == "bin" { let lld_path = ci_llvm_bin.join(exe("lld", target)); if lld_path.exists() { @@ -1321,7 +1323,7 @@ impl CommandLineStep for Lld { } } - let out_dir = builder.lld_out(target); + let out_dir = builder.out.join(target).join("lld"); let lld_stamp = BuildStamp::new(&out_dir).with_prefix("lld"); if lld_stamp.path().exists() { @@ -1379,22 +1381,21 @@ impl CommandLineStep for Lld { // Re-use the same flags as llvm to control the level of debug information // generated for lld. - let profile = match (builder.config.llvm_optimize, builder.config.llvm_release_debuginfo) { - (false, _) => "Debug", - (true, false) => "Release", - (true, true) => "RelWithDebInfo", - }; + let profile = get_llvm_profile(&builder.config); cfg.out_dir(&out_dir) .profile(profile) - .define("LLVM_CMAKE_DIR", llvm_cmake_dir) + .define("LLVM_CMAKE_DIR", llvm_output.cmake_dir()) .define("LLVM_INCLUDE_TESTS", "OFF"); if !builder.config.is_host_target(target) { // Use the host llvm-tblgen binary. cfg.define( "LLVM_TABLEGEN_EXE", - host_llvm_config.with_file_name("llvm-tblgen").with_extension(EXE_EXTENSION), + llvm_output + .host_llvm_config + .with_file_name("llvm-tblgen") + .with_extension(EXE_EXTENSION), ); } @@ -1435,7 +1436,7 @@ impl CommandLineStep for Sanitizers { return runtimes; } - let LlvmResult { host_llvm_config, .. } = + let LlvmOutput { host_llvm_config, .. } = builder.ensure(Llvm { target: builder.config.host_target }); static STAMP_HASH_MEMO: OnceLock = OnceLock::new(); @@ -1849,3 +1850,52 @@ impl CommandLineStep for Libunwind { out_dir } } + +/// Returns the path to `FileCheck` LLVM binary for the specified target. +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct FileCheck { + pub target: TargetSelection, +} + +impl Step for FileCheck { + type Output = PathBuf; + + fn run(self, builder: &Builder<'_>) -> Self::Output { + let target_config = builder.config.target_config.get(&self.target); + + // The target configured filecheck, prefer it + if let Some(s) = target_config.and_then(|c| c.llvm_filecheck.as_ref()) { + return s.clone(); + }; + + // There is a LLVM config set, take filecheck from it + // Note: because `download-ci-llvm` currently overrides `llvm-config`, when the LLVM is + // downloaded, we go through this branch. Ideally, this should be changed so that + // `download-ci-llvm` doesn't override the config. + if let Some(s) = target_config.and_then(|c| c.llvm_config.as_ref()) { + let llvm_bindir = command(s).arg("--bindir").run_capture_stdout(builder).stdout(); + let filecheck = Path::new(llvm_bindir.trim()).join(exe("FileCheck", self.target)); + let filecheck = if filecheck.exists() { + filecheck + } else { + // On Fedora the system LLVM installs FileCheck in the + // llvm subdirectory of the libdir. + let llvm_libdir = command(s).arg("--libdir").run_capture_stdout(builder).stdout(); + let lib_filecheck = + Path::new(llvm_libdir.trim()).join("llvm").join(exe("FileCheck", self.target)); + if lib_filecheck.exists() { + lib_filecheck + } else { + // Return the most normal file name, even though + // it doesn't exist, so that any error message + // refers to that. + filecheck + } + }; + return filecheck; + } + // Here we take the filecheck from LLVM directly + let llvm_output = builder.ensure(Llvm { target: self.target }); + llvm_output.root_dir().join("bin").join(exe("FileCheck", self.target)) + } +} diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 9257a238a3498..b71bbe5a0a9d9 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -2352,7 +2352,9 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the cmd.arg("--mode").arg(mode.as_str()); cmd.arg("--target").arg(target.rustc_target_arg()); cmd.arg("--host").arg(&*test_compiler.host.triple); - cmd.arg("--llvm-filecheck").arg(builder.llvm_filecheck(builder.config.host_target)); + + let filecheck = builder.ensure(llvm::FileCheck { target: builder.config.host_target }); + cmd.arg("--llvm-filecheck").arg(filecheck); if let Some(codegen_backend) = builder.config.cmd.test_codegen_backend() { if !builder @@ -2630,7 +2632,7 @@ Please disable assertions with `rust.debug-assertions = false`. let mut llvm_components_passed = false; let mut copts_passed = false; if builder.config.llvm_enabled(test_compiler.host) { - let llvm::LlvmResult { host_llvm_config, .. } = + let llvm::LlvmOutput { host_llvm_config, .. } = builder.ensure(llvm::Llvm { target: builder.config.host_target }); if !builder.config.dry_run() { let llvm_version = get_llvm_version(builder, &host_llvm_config); diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs index 603ef65854cf6..6321ba3630166 100644 --- a/src/bootstrap/src/core/builder/mod.rs +++ b/src/bootstrap/src/core/builder/mod.rs @@ -1551,7 +1551,7 @@ Alternatively, you can set `build.local-rebuild=true` and use a stage0 compiler /// *target*. pub fn llvm_config(&self, target: TargetSelection) -> Option { if self.config.llvm_enabled(target) && self.kind != Kind::Check && !self.config.dry_run() { - let llvm::LlvmResult { host_llvm_config, .. } = self.ensure(llvm::Llvm { target }); + let llvm::LlvmOutput { host_llvm_config, .. } = self.ensure(llvm::Llvm { target }); if host_llvm_config.is_file() { return Some(host_llvm_config); } diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 81a425fba1cab..7a3b0adf8e93f 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -1076,7 +1076,7 @@ impl Config { llvm_assertions, ); let is_host_system_llvm = - is_system_llvm(&target_config, llvm_from_ci, host_target, host_target); + target_config.get(&host_target).and_then(|c| c.llvm_config.as_ref()).is_some(); if llvm_from_ci { let warn = |option: &str| { @@ -1111,17 +1111,15 @@ impl Config { "HELP: To use `llvm.libzstd` for LLVM/LLD builds, set `download-ci-llvm` option to false." ); } - } - if llvm_from_ci { let triple = &host_target.triple; 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)); check_ci_llvm!(build_target.llvm_config); check_ci_llvm!(build_target.llvm_filecheck); + // FIXME: Do not overwrite the LLVM config here 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))); } for (target, linker_override) in default_linux_linker_overrides() { diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs index 400d0715a4738..84165b08715af 100644 --- a/src/bootstrap/src/core/sanity.rs +++ b/src/bootstrap/src/core/sanity.rs @@ -309,17 +309,6 @@ than building it. if !skip_tools_checks { for host in &build.hosts { cmd_finder.must_have(build.cxx(*host).unwrap()); - - if build.config.llvm_enabled(*host) { - // Externally configured LLVM requires FileCheck to exist - let filecheck = build.llvm_filecheck(build.host_target); - if !filecheck.starts_with(&build.out) - && !filecheck.exists() - && build.config.codegen_tests - { - panic!("FileCheck executable {filecheck:?} does not exist"); - } - } } } diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 7d119247b3bac..54e04ca43c189 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -979,18 +979,6 @@ impl Build { } } - fn enzyme_out(&self, target: TargetSelection) -> PathBuf { - self.out.join(&*target.triple).join("enzyme") - } - - fn offload_out(&self, target: TargetSelection) -> PathBuf { - self.out.join(&*target.triple).join("offload") - } - - fn lld_out(&self, target: TargetSelection) -> PathBuf { - self.out.join(target).join("lld") - } - /// Output directory for all documentation for a target fn doc_out(&self, target: TargetSelection) -> PathBuf { self.out.join(target).join("doc") @@ -1020,50 +1008,6 @@ impl Build { if self.config.vendor { Some(self.src.join(VENDOR_DIR)) } else { None } } - /// Returns the path to `FileCheck` binary for the specified target - fn llvm_filecheck(&self, target: TargetSelection) -> PathBuf { - let target_config = self.config.target_config.get(&target); - if let Some(s) = target_config.and_then(|c| c.llvm_filecheck.as_ref()) { - s.to_path_buf() - } else if let Some(s) = target_config.and_then(|c| c.llvm_config.as_ref()) { - let llvm_bindir = command(s).arg("--bindir").run_capture_stdout(self).stdout(); - let filecheck = Path::new(llvm_bindir.trim()).join(exe("FileCheck", target)); - if filecheck.exists() { - filecheck - } else { - // On Fedora the system LLVM installs FileCheck in the - // llvm subdirectory of the libdir. - let llvm_libdir = command(s).arg("--libdir").run_capture_stdout(self).stdout(); - let lib_filecheck = - Path::new(llvm_libdir.trim()).join("llvm").join(exe("FileCheck", target)); - if lib_filecheck.exists() { - lib_filecheck - } else { - // Return the most normal file name, even though - // it doesn't exist, so that any error message - // refers to that. - filecheck - } - } - } else { - let base = self.llvm_out(target).join("build"); - let base = if !self.ninja() && target.is_msvc() { - if self.config.llvm_optimize { - if self.config.llvm_release_debuginfo { - base.join("RelWithDebInfo") - } else { - base.join("Release") - } - } else { - base.join("Debug") - } - } else { - base - }; - base.join("bin").join(exe("FileCheck", target)) - } - } - /// Directory for libraries built from C/C++ code and shared between stages. fn native_dir(&self, target: TargetSelection) -> PathBuf { self.out.join(target).join("native")