Skip to content

Commit 791fabf

Browse files
Auto merge of #148671 - ZuseZ4:offload-bootstrap, r=<try>
Offload bootstrap
2 parents f520900 + 2271b97 commit 791fabf

File tree

8 files changed

+160
-11
lines changed

8 files changed

+160
-11
lines changed

bootstrap.example.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,9 @@
106106
# Whether to build LLVM with support for it's gpu offload runtime.
107107
#llvm.offload = false
108108

109+
# absolute path to ClangConfig.cmake
110+
#llvm.offload-clang-dir = ""
111+
109112
# When true, link libstdc++ statically into the rustc_llvm.
110113
# This is useful if you don't want to use the dynamic version of that
111114
# library provided by LLVM.

src/bootstrap/configure.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ def v(*args):
120120
o("llvm-assertions", "llvm.assertions", "build LLVM with assertions")
121121
o("llvm-enzyme", "llvm.enzyme", "build LLVM with enzyme")
122122
o("llvm-offload", "llvm.offload", "build LLVM with gpu offload support")
123+
o("llvm-offload-clang-dir", "llvm.offload-clang-dir", "pass the absolute directory of ClangConfig.cmake")
123124
o("llvm-plugins", "llvm.plugins", "build LLVM with plugin interface")
124125
o("debug-assertions", "rust.debug-assertions", "build with debugging assertions")
125126
o(

src/bootstrap/src/core/build_steps/compile.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1440,10 +1440,12 @@ fn rustc_llvm_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelect
14401440
if builder.config.llvm_enzyme {
14411441
cargo.env("LLVM_ENZYME", "1");
14421442
}
1443+
let llvm::LlvmResult { host_llvm_config, .. } = builder.ensure(llvm::Llvm { target });
14431444
if builder.config.llvm_offload {
1445+
builder.ensure(llvm::OmpOffload { target });
14441446
cargo.env("LLVM_OFFLOAD", "1");
14451447
}
1446-
let llvm::LlvmResult { host_llvm_config, .. } = builder.ensure(llvm::Llvm { target });
1448+
14471449
cargo.env("LLVM_CONFIG", &host_llvm_config);
14481450

14491451
// Some LLVM linker flags (-L and -l) may be needed to link `rustc_llvm`. Its build script

src/bootstrap/src/core/build_steps/llvm.rs

Lines changed: 122 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -454,16 +454,6 @@ impl Step for Llvm {
454454
enabled_llvm_runtimes.push("compiler-rt");
455455
}
456456

457-
// This is an experimental flag, which likely builds more than necessary.
458-
// We will optimize it when we get closer to releasing it on nightly.
459-
if builder.config.llvm_offload {
460-
enabled_llvm_runtimes.push("offload");
461-
//FIXME(ZuseZ4): LLVM intends to drop the offload dependency on openmp.
462-
//Remove this line once they achieved it.
463-
enabled_llvm_runtimes.push("openmp");
464-
enabled_llvm_projects.push("compiler-rt");
465-
}
466-
467457
if !enabled_llvm_projects.is_empty() {
468458
enabled_llvm_projects.sort();
469459
enabled_llvm_projects.dedup();
@@ -896,6 +886,128 @@ fn get_var(var_base: &str, host: &str, target: &str) -> Option<OsString> {
896886
.or_else(|| env::var_os(var_base))
897887
}
898888

889+
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
890+
pub struct OmpOffload {
891+
pub target: TargetSelection,
892+
}
893+
894+
impl Step for OmpOffload {
895+
type Output = PathBuf;
896+
const IS_HOST: bool = true;
897+
898+
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
899+
run.path("src/llvm-project/offload")
900+
}
901+
902+
fn make_run(run: RunConfig<'_>) {
903+
run.builder.ensure(OmpOffload { target: run.target });
904+
}
905+
906+
/// Compile OpenMP offload runtimes for `target`.
907+
#[allow(unused)]
908+
fn run(self, builder: &Builder<'_>) -> PathBuf {
909+
if builder.config.dry_run() {
910+
return PathBuf::from("/");
911+
}
912+
let target = self.target;
913+
914+
let LlvmResult { host_llvm_config, .. } = builder.ensure(Llvm { target: self.target });
915+
916+
let out_dir = builder.llvm_out(target);
917+
static STAMP_HASH_MEMO: OnceLock<String> = OnceLock::new();
918+
let smart_stamp_hash = STAMP_HASH_MEMO.get_or_init(|| {
919+
generate_smart_stamp_hash(
920+
builder,
921+
&builder.config.src.join("src/llvm-project/offload"),
922+
builder.offload_info.sha().unwrap_or_default(),
923+
)
924+
});
925+
let stamp = BuildStamp::new(&out_dir).with_prefix("offload").add_stamp(smart_stamp_hash);
926+
927+
trace!("checking build stamp to see if we need to rebuild offload/openmp artifacts");
928+
if stamp.is_up_to_date() {
929+
trace!(?out_dir, "offload/openmp build artifacts are up to date");
930+
if stamp.stamp().is_empty() {
931+
builder.info(
932+
"Could not determine the Offload submodule commit hash. \
933+
Assuming that an Offload rebuild is not necessary.",
934+
);
935+
builder.info(&format!(
936+
"To force Offload/OpenMP to rebuild, remove the file `{}`",
937+
stamp.path().display()
938+
));
939+
}
940+
return out_dir;
941+
}
942+
943+
trace!(?target, "(re)building offload/openmp artifacts");
944+
builder.info(&format!("Building OpenMP/Offload for {target}"));
945+
t!(stamp.remove());
946+
let _time = helpers::timeit(builder);
947+
t!(fs::create_dir_all(&out_dir));
948+
949+
builder.config.update_submodule(Path::new("src").join("llvm-project").to_str().unwrap());
950+
let mut cfg = cmake::Config::new(builder.src.join("src/llvm-project/runtimes/"));
951+
configure_cmake(builder, target, &mut cfg, true, LdFlags::default(), &[]);
952+
953+
// Re-use the same flags as llvm to control the level of debug information
954+
// generated by Enzyme.
955+
// FIXME(ZuseZ4): Find a nicer way to use Enzyme Debug builds.
956+
let profile = match (builder.config.llvm_optimize, builder.config.llvm_release_debuginfo) {
957+
(false, _) => "Debug",
958+
(true, false) => "Release",
959+
(true, true) => "RelWithDebInfo",
960+
};
961+
trace!(?profile);
962+
963+
//let cc = if let Some(p) = &builder.build.config.llvm_offload_cc {
964+
// //p.clone()
965+
// builder.cc(target)
966+
//} else {
967+
// builder.cc(target)
968+
//};
969+
//let cxx = if let Some(p) = &builder.build.config.llvm_offload_cxx {
970+
// //p.clone()
971+
// builder.cxx(target).unwrap()
972+
//} else {
973+
// builder.cxx(target).unwrap()
974+
//};
975+
let root = if let Some(p) = &builder.build.config.llvm_root_offload {
976+
p.clone()
977+
} else {
978+
builder.llvm_out(target).join("build")
979+
};
980+
let clang_dir = if !builder.config.llvm_clang {
981+
// We must have an external clang to use.
982+
assert!(&builder.build.config.llvm_clang_dir.is_some());
983+
builder.build.config.llvm_clang_dir.clone()
984+
} else {
985+
// No need to specify it, since we use the in-tree clang
986+
None
987+
};
988+
989+
cfg.out_dir(&out_dir)
990+
.profile(profile)
991+
.env("LLVM_CONFIG_REAL", &host_llvm_config)
992+
.define("LLVM_ENABLE_ASSERTIONS", "ON")
993+
.define("LLVM_ENABLE_RUNTIMES", "openmp;offload")
994+
.define("LLVM_INCLUDE_TESTS", "OFF")
995+
.define("OFFLOAD_INCLUDE_TESTS", "OFF")
996+
//.define("CMAKE_C_COMPILER", cc)
997+
//.define("CMAKE_CXX_COMPILER", cxx)
998+
.define("OPENMP_STANDALONE_BUILD", "ON")
999+
.define("LLVM_ROOT", root)
1000+
.define("LLVM_DIR", builder.llvm_out(target).join("lib").join("cmake").join("llvm"));
1001+
if let Some(p) = clang_dir {
1002+
cfg.define("Clang_DIR", p);
1003+
}
1004+
cfg.build();
1005+
1006+
t!(stamp.write());
1007+
out_dir
1008+
}
1009+
}
1010+
8991011
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
9001012
pub struct Enzyme {
9011013
pub target: TargetSelection,

src/bootstrap/src/core/config/config.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,10 @@ pub struct Config {
169169
pub llvm_link_jobs: Option<u32>,
170170
pub llvm_version_suffix: Option<String>,
171171
pub llvm_use_linker: Option<String>,
172+
pub llvm_offload_cc: Option<PathBuf>,
173+
pub llvm_offload_cxx: Option<PathBuf>,
174+
pub llvm_root_offload: Option<PathBuf>,
175+
pub llvm_clang_dir: Option<PathBuf>,
172176
pub llvm_allow_old_toolchain: bool,
173177
pub llvm_polly: bool,
174178
pub llvm_clang: bool,
@@ -290,6 +294,7 @@ pub struct Config {
290294
pub miri_info: channel::GitInfo,
291295
pub rustfmt_info: channel::GitInfo,
292296
pub enzyme_info: channel::GitInfo,
297+
pub offload_info: channel::GitInfo,
293298
pub in_tree_llvm_info: channel::GitInfo,
294299
pub in_tree_gcc_info: channel::GitInfo,
295300

@@ -601,6 +606,10 @@ impl Config {
601606
ldflags: llvm_ldflags,
602607
use_libcxx: llvm_use_libcxx,
603608
use_linker: llvm_use_linker,
609+
offload_cc: llvm_offload_cc,
610+
offload_cxx: llvm_offload_cxx,
611+
root_offload: llvm_root_offload,
612+
clang_dir: llvm_clang_dir,
604613
allow_old_toolchain: llvm_allow_old_toolchain,
605614
offload: llvm_offload,
606615
polly: llvm_polly,
@@ -1257,6 +1266,8 @@ impl Config {
12571266
let in_tree_gcc_info = git_info(&exec_ctx, false, &src.join("src/gcc"));
12581267
let in_tree_llvm_info = git_info(&exec_ctx, false, &src.join("src/llvm-project"));
12591268
let enzyme_info = git_info(&exec_ctx, omit_git_hash, &src.join("src/tools/enzyme"));
1269+
let offload_info =
1270+
git_info(&exec_ctx, omit_git_hash, &src.join("src/llvm-project/offload"));
12601271
let miri_info = git_info(&exec_ctx, omit_git_hash, &src.join("src/tools/miri"));
12611272
let rust_analyzer_info =
12621273
git_info(&exec_ctx, omit_git_hash, &src.join("src/tools/rust-analyzer"));
@@ -1356,10 +1367,12 @@ impl Config {
13561367
llvm_cflags,
13571368
llvm_clang: llvm_clang.unwrap_or(false),
13581369
llvm_clang_cl,
1370+
llvm_clang_dir: llvm_clang_dir.map(PathBuf::from),
13591371
llvm_cxxflags,
13601372
llvm_enable_warnings: llvm_enable_warnings.unwrap_or(false),
13611373
llvm_enzyme: llvm_enzyme.unwrap_or(false),
13621374
llvm_experimental_targets,
1375+
llvm_root_offload: llvm_root_offload.map(PathBuf::from),
13631376
llvm_from_ci,
13641377
llvm_ldflags,
13651378
llvm_libunwind_default: rust_llvm_libunwind
@@ -1374,6 +1387,8 @@ impl Config {
13741387
.or((!llvm_from_ci && llvm_thin_lto.unwrap_or(false)).then_some(true)),
13751388
),
13761389
llvm_offload: llvm_offload.unwrap_or(false),
1390+
llvm_offload_cc: llvm_offload_cc.map(PathBuf::from),
1391+
llvm_offload_cxx: llvm_offload_cxx.map(PathBuf::from),
13771392
llvm_optimize: llvm_optimize.unwrap_or(true),
13781393
llvm_plugins: llvm_plugin.unwrap_or(false),
13791394
llvm_polly: llvm_polly.unwrap_or(false),
@@ -1396,6 +1411,7 @@ impl Config {
13961411
musl_root: rust_musl_root.map(PathBuf::from),
13971412
ninja_in_file: llvm_ninja.unwrap_or(true),
13981413
nodejs: build_nodejs.map(PathBuf::from),
1414+
offload_info,
13991415
omit_git_hash,
14001416
on_fail: flags_on_fail,
14011417
optimized_compiler_builtins,

src/bootstrap/src/core/config/toml/llvm.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ define_config! {
3232
ldflags: Option<String> = "ldflags",
3333
use_libcxx: Option<bool> = "use-libcxx",
3434
use_linker: Option<String> = "use-linker",
35+
offload_cc: Option<String> = "offload-cc",
36+
offload_cxx: Option<String> = "offload-cxx",
37+
root_offload: Option<String> = "root-offload",
38+
clang_dir: Option<String> = "offload-clang-dir",
3539
allow_old_toolchain: Option<bool> = "allow-old-toolchain",
3640
offload: Option<bool> = "offload",
3741
polly: Option<bool> = "polly",
@@ -110,6 +114,10 @@ pub fn check_incompatible_options_for_ci_llvm(
110114
ldflags,
111115
use_libcxx,
112116
use_linker,
117+
offload_cc: _,
118+
offload_cxx: _,
119+
root_offload: _,
120+
clang_dir: _,
113121
allow_old_toolchain,
114122
offload,
115123
polly,

src/bootstrap/src/lib.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,12 +212,15 @@ pub struct Build {
212212
src: PathBuf,
213213
out: PathBuf,
214214
bootstrap_out: PathBuf,
215+
//offload_cc: PathBuf,
216+
//offload_cxx: PathBuf,
215217
cargo_info: GitInfo,
216218
rust_analyzer_info: GitInfo,
217219
clippy_info: GitInfo,
218220
miri_info: GitInfo,
219221
rustfmt_info: GitInfo,
220222
enzyme_info: GitInfo,
223+
offload_info: GitInfo,
221224
in_tree_llvm_info: GitInfo,
222225
in_tree_gcc_info: GitInfo,
223226
local_rebuild: bool,
@@ -476,6 +479,7 @@ impl Build {
476479
let miri_info = config.miri_info.clone();
477480
let rustfmt_info = config.rustfmt_info.clone();
478481
let enzyme_info = config.enzyme_info.clone();
482+
let offload_info = config.offload_info.clone();
479483
let in_tree_llvm_info = config.in_tree_llvm_info.clone();
480484
let in_tree_gcc_info = config.in_tree_gcc_info.clone();
481485

@@ -568,6 +572,7 @@ impl Build {
568572
miri_info,
569573
rustfmt_info,
570574
enzyme_info,
575+
offload_info,
571576
in_tree_llvm_info,
572577
in_tree_gcc_info,
573578
cc: HashMap::new(),

src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ ENV RUST_CONFIGURE_ARGS \
9090
--set target.x86_64-unknown-linux-gnu.ranlib=/rustroot/bin/llvm-ranlib \
9191
--set llvm.thin-lto=true \
9292
--set llvm.ninja=false \
93+
--set llvm.offload=true \
94+
--set llvm.offload-clang-dir="/rustroot/lib/cmake/clang" \
9395
--set llvm.libzstd=true \
9496
--set rust.jemalloc \
9597
--set rust.bootstrap-override-lld=true \

0 commit comments

Comments
 (0)