Skip to content

Commit 72dea04

Browse files
committed
refactor: streamline guest bundling
- auto-generate the content of `lib.rs` within the build script - allow a single feature flag with multiple binaries (e.g. for examples) - derive just command and output file from `lib` or `example`
1 parent cb4233f commit 72dea04

File tree

4 files changed

+105
-52
lines changed

4 files changed

+105
-52
lines changed

guests/bundle/build.rs

Lines changed: 99 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,15 @@
33

44
use std::{
55
collections::HashMap,
6+
fs::File,
7+
io::Write,
68
path::{Path, PathBuf},
79
process::{Command, Stdio},
810
str::FromStr,
911
};
1012

1113
fn main() {
14+
let out_dir = PathBuf::from(std::env::var_os("OUT_DIR").unwrap());
1215
let profile: Profile = std::env::var("PROFILE").unwrap().parse().unwrap();
1316
let package_locations = package_locations();
1417

@@ -28,10 +31,16 @@ fn main() {
2831
|| std::env::var("DOCS_RS").is_ok()
2932
|| std::env::var("JUSTCHECK").is_ok();
3033

34+
let mut gen_file = File::create(out_dir.join("gen.rs")).unwrap();
35+
3136
for feature in FEATURES {
3237
println!("processing {}", feature.name);
33-
feature.build_or_stub(stub, profile, &package_locations);
38+
feature.build_or_stub(stub, profile, &package_locations, &out_dir, &mut gen_file);
3439
}
40+
41+
gen_file.flush().unwrap();
42+
43+
println!("cargo::rerun-if-changed=build.rs");
3544
}
3645

3746
/// Get locations for all packages in the dependency tree.
@@ -151,6 +160,27 @@ impl std::fmt::Display for Profile {
151160
}
152161
}
153162

163+
/// Artifact type.
164+
enum ArtifactType {
165+
/// Library.
166+
Lib,
167+
168+
/// Example.
169+
Example(&'static str),
170+
}
171+
172+
/// Just(file) command.
173+
struct JustCmd {
174+
/// Artifact type.
175+
artifact_type: ArtifactType,
176+
177+
/// Name of the resulting constant.
178+
const_name: &'static str,
179+
180+
/// Documentation for the created constant.
181+
doc: &'static str,
182+
}
183+
154184
/// Feature description.
155185
struct Feature {
156186
/// Lowercase feature name.
@@ -159,15 +189,8 @@ struct Feature {
159189
/// Package that contains the feature code.
160190
package: &'static str,
161191

162-
/// `just` command prefix that compiles the feature.
163-
///
164-
/// This will call `just prefix{profile}` within the package directory.
165-
just_cmd_prefix: &'static str,
166-
167-
/// Path components to file in target directory.
168-
///
169-
/// So `["foo", "bar.bin"]` will resolve to `CARGO_TARGET_DIR/wasm32-wasip2/foo/bar.bin`.
170-
just_out_file: &'static [&'static str],
192+
/// Just commands.
193+
just_cmds: &'static [JustCmd],
171194
}
172195

173196
impl Feature {
@@ -177,12 +200,13 @@ impl Feature {
177200
stub: bool,
178201
profile: Profile,
179202
package_locations: &HashMap<String, PathBuf>,
203+
out_dir: &Path,
204+
gen_file: &mut File,
180205
) {
181206
let Self {
182207
name,
183208
package,
184-
just_cmd_prefix,
185-
just_out_file,
209+
just_cmds,
186210
} = self;
187211

188212
let name_upper = name.to_uppercase();
@@ -191,32 +215,61 @@ impl Feature {
191215
return;
192216
}
193217

194-
let out_dir = PathBuf::from(std::env::var_os("OUT_DIR").unwrap());
195-
196-
let out_file = if stub {
197-
let out_file = out_dir.join(format!("{name}.wasm"));
198-
// write empty stub file
199-
std::fs::write(&out_file, b"").unwrap();
200-
out_file
201-
} else {
202-
let target_dir = out_dir.join(name);
218+
let cwd = package_locations.get(*package).unwrap();
219+
let target_dir = out_dir.join(name);
220+
221+
for just_cmd in *just_cmds {
222+
let JustCmd {
223+
artifact_type,
224+
const_name,
225+
doc,
226+
} = just_cmd;
227+
let out_file = if stub {
228+
let out_file = out_dir.join(format!("{name}.wasm"));
229+
// write empty stub file
230+
std::fs::write(&out_file, b"").unwrap();
231+
out_file
232+
} else {
233+
let mut just_cmd = "build-".to_owned();
234+
match artifact_type {
235+
ArtifactType::Lib => {}
236+
ArtifactType::Example(example) => {
237+
just_cmd.push_str(example);
238+
just_cmd.push('-');
239+
}
240+
}
241+
just_cmd.push_str(profile.as_str());
242+
243+
just_build(cwd, &just_cmd, &target_dir);
244+
245+
let out = target_dir.join("wasm32-wasip2").join(profile.as_str());
246+
match artifact_type {
247+
ArtifactType::Lib => out.join(format!("{}.wasm", package.replace("-", "_"))),
248+
ArtifactType::Example(example) => out
249+
.join("examples")
250+
.join(format!("{}.wasm", example.replace("-", "_"))),
251+
}
252+
};
203253

204-
just_build(
205-
package_locations.get(*package).unwrap(),
206-
&format!("{just_cmd_prefix}{profile}"),
207-
&target_dir,
254+
println!(
255+
"cargo::rustc-env=BIN_PATH_{const_name}={}",
256+
out_file.display(),
208257
);
209258

210-
just_out_file.iter().fold(
211-
target_dir.join("wasm32-wasip2").join(profile.as_str()),
212-
|path, part| path.join(part),
213-
)
214-
};
215-
216-
println!(
217-
"cargo::rustc-env=BIN_PATH_{name_upper}={}",
218-
out_file.display(),
219-
);
259+
writeln!(gen_file, "/// {doc}").unwrap();
260+
writeln!(gen_file, r#"#[cfg(feature = "{name}")]"#).unwrap();
261+
writeln!(gen_file, r#"pub static BIN_{const_name}: &[u8] = include_bytes!(env!("BIN_PATH_{const_name}"));"#).unwrap();
262+
263+
// we cannot really depend directly on examples, so we need to tell Cargo about it
264+
if let ArtifactType::Example(example) = artifact_type {
265+
println!(
266+
"cargo::rerun-if-changed={}",
267+
cwd.join("examples")
268+
.join(format!("{}.rs", example.replace("-", "_")))
269+
.display(),
270+
);
271+
}
272+
}
220273
}
221274
}
222275

@@ -232,18 +285,24 @@ fn just_build(cwd: &Path, just_cmd: &str, cargo_target_dir: &Path) {
232285

233286
/// All supported features.
234287
///
235-
/// This must be in-sync with the feature list in `Cargo.toml` and the imports in `src/lib.rs`.
288+
/// This must be in-sync with the feature list in `Cargo.toml`.
236289
const FEATURES: &[Feature] = &[
237290
Feature {
238291
name: "example",
239292
package: "datafusion-udf-wasm-guest",
240-
just_cmd_prefix: "build-add-one-",
241-
just_out_file: &["examples", "add_one.wasm"],
293+
just_cmds: &[JustCmd {
294+
artifact_type: ArtifactType::Example("add-one"),
295+
const_name: "EXAMPLE",
296+
doc: r#""add-one" example."#,
297+
}],
242298
},
243299
Feature {
244300
name: "python",
245301
package: "datafusion-udf-wasm-python",
246-
just_cmd_prefix: "",
247-
just_out_file: &["datafusion_udf_wasm_python.wasm"],
302+
just_cmds: &[JustCmd {
303+
artifact_type: ArtifactType::Lib,
304+
const_name: "PYTHON",
305+
doc: "Python UDF.",
306+
}],
248307
},
249308
];

guests/bundle/src/lib.rs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,3 @@
11
//! Bundles guests as pre-compiled WASM bytecode.
22
3-
/// "add-one" example.
4-
#[cfg(feature = "example")]
5-
pub static BIN_EXAMPLE: &[u8] = include_bytes!(env!("BIN_PATH_EXAMPLE"));
6-
7-
/// Python UDF.
8-
#[cfg(feature = "python")]
9-
pub static BIN_PYTHON: &[u8] = include_bytes!(env!("BIN_PATH_PYTHON"));
3+
include!(concat!(env!("OUT_DIR"), "/gen.rs"));

guests/python/Justfile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -163,13 +163,13 @@ build-lib profile: download-python-sdk download-wasi-sdk python-site-packages
163163
do profile: (build-lib profile)
164164

165165
# create dev/debug build
166-
debug: (do "debug")
166+
build-debug: (do "debug")
167167

168168
# create release build
169-
release: (do "release")
169+
build-release: (do "release")
170170

171171
# checks build
172-
check-build: debug
172+
check-build: build-debug
173173

174174
# clean build artifacts
175175
clean:

guests/python/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@
44
Use:
55

66
```console
7-
just debug
7+
just build-debug
88
```
99

1010
or
1111

1212
```console
13-
just release
13+
just build-release
1414
```
1515

1616
## Python Version

0 commit comments

Comments
 (0)