@bloomengine/engine 0.3.3 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/native/shared/build.rs +137 -6
- package/package.json +1 -1
package/native/shared/build.rs
CHANGED
|
@@ -39,6 +39,28 @@ fn build_jolt() {
|
|
|
39
39
|
.join("third_party")
|
|
40
40
|
.join("bloom_jolt");
|
|
41
41
|
|
|
42
|
+
let target_os = std::env::var("CARGO_CFG_TARGET_OS").unwrap_or_default();
|
|
43
|
+
let target_arch = std::env::var("CARGO_CFG_TARGET_ARCH").unwrap_or_default();
|
|
44
|
+
|
|
45
|
+
println!("cargo:rerun-if-env-changed=BLOOM_JOLT_PREBUILT_DIR");
|
|
46
|
+
println!("cargo:rerun-if-env-changed=BLOOM_JOLT_FROM_SOURCE");
|
|
47
|
+
|
|
48
|
+
// Prebuilt fast path — if `@bloomengine/jolt-prebuilt` is available
|
|
49
|
+
// (via env var or a node_modules sibling), link its archives and
|
|
50
|
+
// skip the multi-minute cmake build of JoltPhysics entirely. The
|
|
51
|
+
// env var BLOOM_JOLT_FROM_SOURCE=1 forces the cmake fallback even
|
|
52
|
+
// when prebuilts are present, useful for hacking on the C++ shim.
|
|
53
|
+
let from_source = std::env::var_os("BLOOM_JOLT_FROM_SOURCE").is_some();
|
|
54
|
+
if !from_source {
|
|
55
|
+
if let Some(prebuilt_dir) =
|
|
56
|
+
find_prebuilt_dir(&manifest_dir, &target_os, &target_arch)
|
|
57
|
+
{
|
|
58
|
+
link_prebuilt(&prebuilt_dir, &target_os);
|
|
59
|
+
emit_cxx_runtime_link(&target_os);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
42
64
|
if !shim_dir.join("CMakeLists.txt").exists() {
|
|
43
65
|
panic!(
|
|
44
66
|
"bloom_jolt shim not found at {}; did the third_party submodules init?",
|
|
@@ -60,8 +82,6 @@ fn build_jolt() {
|
|
|
60
82
|
// 2. The Jolt build is expensive and identical across every cargo target
|
|
61
83
|
// hash — caching it once per profile lets `cargo clean` not nuke a
|
|
62
84
|
// multi-minute compile.
|
|
63
|
-
let target_os = std::env::var("CARGO_CFG_TARGET_OS").unwrap_or_default();
|
|
64
|
-
let target_arch = std::env::var("CARGO_CFG_TARGET_ARCH").unwrap_or_default();
|
|
65
85
|
let dst = shim_dir
|
|
66
86
|
.join("build")
|
|
67
87
|
.join(format!("{}-{}", target_os, target_arch));
|
|
@@ -87,10 +107,121 @@ fn build_jolt() {
|
|
|
87
107
|
println!("cargo:rustc-link-lib=static=bloom_jolt");
|
|
88
108
|
println!("cargo:rustc-link-lib=static=Jolt");
|
|
89
109
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
110
|
+
emit_cxx_runtime_link(&target_os);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/// Locate the `@bloomengine/jolt-prebuilt` package's lib dir for the
|
|
114
|
+
/// active build target. Returns `Some(dir)` only when both expected
|
|
115
|
+
/// archives are present — a half-shipped package falls through to the
|
|
116
|
+
/// cmake build instead of producing a confusing linker error.
|
|
117
|
+
///
|
|
118
|
+
/// Resolution order:
|
|
119
|
+
/// 1. `BLOOM_JOLT_PREBUILT_DIR` env var — points at a directory
|
|
120
|
+
/// containing per-target subdirs (`<dir>/<os>-<arch>/lib*.a`).
|
|
121
|
+
/// Used for local spike testing and for CI matrix jobs that
|
|
122
|
+
/// stage archives outside `node_modules`.
|
|
123
|
+
/// 2. Walk up from `CARGO_MANIFEST_DIR` looking for any
|
|
124
|
+
/// `node_modules/@bloomengine/jolt-prebuilt/lib/<os>-<arch>/`.
|
|
125
|
+
/// Matches what npm's resolver does when `@bloomengine/engine`
|
|
126
|
+
/// depends on `@bloomengine/jolt-prebuilt` — the consumer's
|
|
127
|
+
/// install creates this directory next to the engine package.
|
|
128
|
+
#[cfg(feature = "jolt")]
|
|
129
|
+
fn find_prebuilt_dir(
|
|
130
|
+
manifest_dir: &std::path::Path,
|
|
131
|
+
target_os: &str,
|
|
132
|
+
target_arch: &str,
|
|
133
|
+
) -> Option<std::path::PathBuf> {
|
|
134
|
+
// Map Rust's target_arch to the npm/Node convention used in this
|
|
135
|
+
// package's directory layout. Keep this in sync with the matrix in
|
|
136
|
+
// npm/jolt-prebuilt/README.md.
|
|
137
|
+
let arch_token = match target_arch {
|
|
138
|
+
"aarch64" => "arm64",
|
|
139
|
+
"x86_64" => "x64",
|
|
140
|
+
"arm" => "armv7",
|
|
141
|
+
other => other,
|
|
142
|
+
};
|
|
143
|
+
let target_token = format!("{}-{}", target_os, arch_token);
|
|
144
|
+
|
|
145
|
+
let candidates = std::iter::empty::<std::path::PathBuf>()
|
|
146
|
+
.chain(
|
|
147
|
+
std::env::var_os("BLOOM_JOLT_PREBUILT_DIR")
|
|
148
|
+
.map(|v| std::path::PathBuf::from(v).join(&target_token)),
|
|
149
|
+
)
|
|
150
|
+
.chain(walk_up_for_node_modules(manifest_dir).map(|nm| {
|
|
151
|
+
nm.join("@bloomengine")
|
|
152
|
+
.join("jolt-prebuilt")
|
|
153
|
+
.join("lib")
|
|
154
|
+
.join(&target_token)
|
|
155
|
+
}));
|
|
156
|
+
|
|
157
|
+
let (lib_prefix, lib_ext) = if target_os == "windows" {
|
|
158
|
+
("", "lib")
|
|
159
|
+
} else {
|
|
160
|
+
("lib", "a")
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
for dir in candidates {
|
|
164
|
+
let bloom_jolt = dir.join(format!("{}bloom_jolt.{}", lib_prefix, lib_ext));
|
|
165
|
+
let jolt = dir.join(format!("{}Jolt.{}", lib_prefix, lib_ext));
|
|
166
|
+
if bloom_jolt.exists() && jolt.exists() {
|
|
167
|
+
return Some(dir);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
None
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/// Iterator over every ancestor `node_modules/` reachable from
|
|
174
|
+
/// `start`. Yields each directory once, parent-first, so a closer
|
|
175
|
+
/// prebuilt installation wins over a higher one (matching node's
|
|
176
|
+
/// resolution algorithm).
|
|
177
|
+
#[cfg(feature = "jolt")]
|
|
178
|
+
fn walk_up_for_node_modules(
|
|
179
|
+
start: &std::path::Path,
|
|
180
|
+
) -> impl Iterator<Item = std::path::PathBuf> + '_ {
|
|
181
|
+
let mut next: Option<&std::path::Path> = Some(start);
|
|
182
|
+
std::iter::from_fn(move || {
|
|
183
|
+
while let Some(cur) = next {
|
|
184
|
+
next = cur.parent();
|
|
185
|
+
let candidate = cur.join("node_modules");
|
|
186
|
+
if candidate.is_dir() {
|
|
187
|
+
return Some(candidate);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
None
|
|
191
|
+
})
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
#[cfg(feature = "jolt")]
|
|
195
|
+
fn link_prebuilt(dir: &std::path::Path, target_os: &str) {
|
|
196
|
+
// Rerun if any archive in the prebuilt dir changes — covers the
|
|
197
|
+
// case where a new release of jolt-prebuilt drops in new bytes.
|
|
198
|
+
let (lib_prefix, lib_ext) = if target_os == "windows" {
|
|
199
|
+
("", "lib")
|
|
200
|
+
} else {
|
|
201
|
+
("lib", "a")
|
|
202
|
+
};
|
|
203
|
+
println!(
|
|
204
|
+
"cargo:rerun-if-changed={}",
|
|
205
|
+
dir.join(format!("{}bloom_jolt.{}", lib_prefix, lib_ext))
|
|
206
|
+
.display()
|
|
207
|
+
);
|
|
208
|
+
println!(
|
|
209
|
+
"cargo:rerun-if-changed={}",
|
|
210
|
+
dir.join(format!("{}Jolt.{}", lib_prefix, lib_ext)).display()
|
|
211
|
+
);
|
|
212
|
+
|
|
213
|
+
println!("cargo:rustc-link-search=native={}", dir.display());
|
|
214
|
+
println!("cargo:rustc-link-lib=static=bloom_jolt");
|
|
215
|
+
println!("cargo:rustc-link-lib=static=Jolt");
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/// Emit the C++ standard library link directive that matches the
|
|
219
|
+
/// archives we just linked. Required because the static archives pull
|
|
220
|
+
/// in libc++ / libstdc++ symbols that the Rust toolchain doesn't
|
|
221
|
+
/// resolve on its own.
|
|
222
|
+
#[cfg(feature = "jolt")]
|
|
223
|
+
fn emit_cxx_runtime_link(target_os: &str) {
|
|
224
|
+
match target_os {
|
|
94
225
|
"macos" | "ios" | "tvos" | "watchos" => {
|
|
95
226
|
println!("cargo:rustc-link-lib=dylib=c++");
|
|
96
227
|
}
|