Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion compiler/rustc_llvm/llvm-wrapper/offload/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
cmake_minimum_required(VERSION 3.20)
project(RustOffload LANGUAGES CXX)

find_package(LLVM CONFIG REQUIRED)
# If we don't prohibit the default path, CMake will find an incompatible system LLVM installation instead of the one we built.
find_package(LLVM CONFIG REQUIRED NO_DEFAULT_PATH PATHS "${LLVM_DIR}")

add_library(RustOffload-${LLVM_VERSION_MAJOR} SHARED
OffloadWrapper.cpp
Expand Down
69 changes: 62 additions & 7 deletions src/bootstrap/src/core/build_steps/llvm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1298,17 +1298,64 @@ impl CommandLineStep for OmpOffload {

builder.config.update_submodule("src/llvm-project");

// OpenMP/Offload builds currently (LLVM-22) still depend on Clang, although there are
// intentions to loosen this requirement over time. FIXME(offload): re-evaluate on LLVM 23
let clang_dir = if !builder.config.llvm_clang {
let offload_clang_dir = if !builder.config.llvm_clang {
// We must have an external clang to use.
assert!(&builder.build.config.llvm_clang_dir.is_some());
builder.build.config.llvm_clang_dir.clone()
builder.build.config.offload_clang_dir.clone()
} else {
// No need to specify it, since we use the in-tree clang
None
};

// We currently build libompdevice by accident. It includes bitcode for our amd/nvptx
// targets, and only the latest clang compiler can build those. We could stop building those
// to fix this requirement, but we plan on instead building libc-for-gpu very soon, which
// will have the same clang requirement, so we wouldn't save much. There are two ways in
// which we can find a suitable clang. Either a user enabled the llvm.clang, in which case
// we built our own clang based on the llvm submodule first, this always works. The
// alternative is that the user sets the offload_clang_dir path, in which case they hopefully point
// to a suitable clang, otherwise the build will fail.
let clang_bin_dir = if builder.config.llvm_clang {
llvm_output.host_llvm_config.parent().map(Path::to_path_buf)
} else {
// We expect the following (default) structure of the offload_clang_dir:
// <prefix>/lib/cmake/clang, with a ClangConfig.cmake inside.
// The clang binary is located in <prefix>/bin, so we go up three levels to find it.
// This hardcodes the ClangConfig.cmake logic, which isn't great, so we filter for the
// binary and error if we can't find it (presumably because LLVM build layout changed?).
offload_clang_dir
.as_deref()
.and_then(|dir| dir.ancestors().nth(3))
.map(|prefix| prefix.join("bin"))
}
.filter(|dir| dir.join(exe("clang", target)).exists());

let Some(clang_bin_dir) = clang_bin_dir else {
eprintln!(
"Building Offload requires a clang binary. Please either set `llvm.offload-clang-dir` or enable `llvm.clang` to build it."
);
helpers::exit_process(1);
};
let clang = clang_bin_dir.join(exe("clang", target));
let clangxx = clang_bin_dir.join(exe("clang++", target));

// This was encountered when using gcc 13 to build the llvm submodule on a server, where no
// clang was available. We first built clang along with llvm, and then switched over to use
// the newly built clang to build the offload runtimes. Since we switched compiler, we have
// to make sure that we're still using the same libstdc++ we used before. Without this
// change, clang picked up a system libstdc++ from a different gcc and failed.
let cxx_lib_dir = builder.cxx(target).ok().and_then(|cxx| {
let stdout = command(&cxx)
.arg("-print-file-name=libstdc++.so")
.cached()
.run_capture_stdout(builder)
.stdout();
let libstdcxx = PathBuf::from(stdout.trim());
if !libstdcxx.is_absolute() {
return None;
}
libstdcxx.parent().map(Path::to_path_buf)
});

// In the context of OpenMP offload, some libraries must be compiled for the gpu target,
// some for the host, and others for both. We do not perform a full cross-compilation, since
// we don't want to run rustc on a GPU.
Expand All @@ -1320,7 +1367,6 @@ impl CommandLineStep for OmpOffload {
// come with it's own set of default include directories, which are based on a potentially older
// LLVM. This can cause issues, so we overwrite it to include headers based on our
// `src/llvm-project` submodule instead.
// FIXME(offload): With LLVM-22 we hopefully won't need an external clang anymore.
let mut cflags = CcFlags::default();
if !builder.config.llvm_clang {
let base = builder.llvm_out(target).join("include");
Expand All @@ -1335,9 +1381,18 @@ impl CommandLineStep for OmpOffload {
if builder.config.llvm_thin_lto && !target.contains("apple") {
ldflags.push_all("-fuse-ld=lld");
}
if *omp_target == *target.triple
&& let Some(dir) = &cxx_lib_dir
{
ldflags.push_all(format!("-L{}", dir.display()));
}

configure_cmake(builder, target, &mut cfg, true, ldflags, cflags, &[]);

cfg.define("CMAKE_C_COMPILER", &clang)
.define("CMAKE_CXX_COMPILER", &clangxx)
.define("CMAKE_ASM_COMPILER", &clang);

// Re-use the same flags as llvm to control the level of debug information
// generated for offload.
let profile = get_llvm_profile(&builder.config);
Expand All @@ -1354,7 +1409,7 @@ impl CommandLineStep for OmpOffload {
.define("LLVM_ROOT", builder.llvm_out(target).join("build"))
.define("LLVM_DIR", llvm_output.cmake_dir())
.define("LLVM_DEFAULT_TARGET_TRIPLE", omp_target);
if let Some(p) = clang_dir.clone() {
if let Some(p) = offload_clang_dir.clone() {
cfg.define("Clang_DIR", p);
}

Expand Down
6 changes: 3 additions & 3 deletions src/bootstrap/src/core/config/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ pub(crate) struct Config {
pub llvm_link_jobs: Option<u32>,
pub llvm_version_suffix: Option<String>,
pub llvm_use_linker: Option<String>,
pub llvm_clang_dir: Option<PathBuf>,
pub offload_clang_dir: Option<PathBuf>,
pub llvm_allow_old_toolchain: bool,
pub llvm_polly: bool,
pub llvm_clang: bool,
Expand Down Expand Up @@ -643,7 +643,7 @@ impl Config {
use_linker: llvm_use_linker,
allow_old_toolchain: llvm_allow_old_toolchain,
offload: llvm_offload,
offload_clang_dir: llvm_clang_dir,
offload_clang_dir,
polly: llvm_polly,
clang: llvm_clang,
enable_warnings: llvm_enable_warnings,
Expand Down Expand Up @@ -1489,7 +1489,6 @@ NOTE: Please add `--stage 2` to your command line, or if you're sure you want to
llvm_ci_mode,
llvm_clang: llvm_clang.unwrap_or(false),
llvm_clang_cl,
llvm_clang_dir: llvm_clang_dir.map(PathBuf::from),
llvm_cxxflags,
llvm_enable_warnings: llvm_enable_warnings.unwrap_or(false),
llvm_enzyme: llvm_enzyme.unwrap_or(false),
Expand Down Expand Up @@ -1522,6 +1521,7 @@ NOTE: Please add `--stage 2` to your command line, or if you're sure you want to
musl_root: rust_musl_root.map(PathBuf::from),
ninja_in_file: llvm_ninja.unwrap_or(true),
nodejs: build_nodejs.map(PathBuf::from),
offload_clang_dir: offload_clang_dir.map(PathBuf::from),
omit_git_hash,
on_fail: flags_on_fail,
optimized_compiler_builtins,
Expand Down
Loading