Skip to content

Commit 188e965

Browse files
committed
[component_macro] Add host_bindgen!() and guest_bindgen!()
This adds a proc-macro crate that exposes the bindings code generation from hyperlight_component_util as macros suitable for using WIT to define a hyperlight host<->guest interface. Signed-off-by: Lucy Menon <[email protected]>
1 parent 6978faf commit 188e965

File tree

4 files changed

+86
-0
lines changed

4 files changed

+86
-0
lines changed

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ members = [
1414
"fuzz",
1515
"src/hyperlight_guest_bin",
1616
"src/hyperlight_component_util",
17+
"src/hyperlight_component_macro",
1718
]
1819
# Guests have custom linker flags, so we need to exclude them from the workspace
1920
exclude = [
@@ -38,6 +39,7 @@ hyperlight-guest = { path = "src/hyperlight_guest", version = "0.5.1", default-f
3839
hyperlight-guest-bin = { path = "src/hyperlight_guest_bin", version = "0.5.1", default-features = false }
3940
hyperlight-testing = { path = "src/hyperlight_testing", default-features = false }
4041
hyperlight-component-util = { path = "src/hyperlight_component_util" }
42+
hyperlight-component-macro = { path = "src/hyperlight_component_macro" }
4143

4244
[workspace.lints.rust]
4345
unsafe_op_in_unsafe_fn = "deny"
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
[package]
2+
name = "hyperlight-component-macro"
3+
version.workspace = true
4+
edition.workspace = true
5+
rust-version.workspace = true
6+
license.workspace = true
7+
homepage.workspace = true
8+
repository.workspace = true
9+
readme.workspace = true
10+
description = """
11+
Procedural macros to generate Hyperlight host and guest bindings from component types
12+
"""
13+
14+
[lib]
15+
name = "hyperlight_component_macro"
16+
proc-macro = true
17+
18+
[dependencies]
19+
wasmparser = { version = "0.224.0" }
20+
quote = { version = "1.0.38" }
21+
proc-macro2 = { version = "1.0.93" }
22+
syn = { version = "2.0.96" }
23+
itertools = { version = "0.14.0" }
24+
prettyplease = { version = "0.2.31" }
25+
hyperlight-component-util = { workspace = true }
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
extern crate proc_macro;
2+
3+
use hyperlight_component_util::*;
4+
5+
/// Create host bindings for the wasm component type in the file
6+
/// passed in (or `$WIT_WORLD`, if nothign is passed in). This will
7+
/// produce all relevant types and trait implementations for the
8+
/// component type, as well as functions allowing the component to be
9+
/// instantiated inside a sandbox.
10+
///
11+
/// This includes both a primitive `register_host_functions`, which can
12+
/// be used to directly register the host functions on any sandbox
13+
/// (and which can easily be used with Hyperlight-Wasm), as well as an
14+
/// `instantiate()` method on the component trait that makes
15+
/// instantiating the sandbox particularly ergonomic in core
16+
/// Hyperlight.
17+
#[proc_macro]
18+
pub fn host_bindgen(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
19+
let path: Option<syn::LitStr> = syn::parse_macro_input!(input as Option<syn::LitStr>);
20+
let path = path
21+
.map(|x| x.value().into())
22+
.unwrap_or_else(|| std::env::var_os("WIT_WORLD").unwrap());
23+
util::read_wit_type_from_file(path, |kebab_name, ct| {
24+
let decls = emit::run_state(false, false, |s| {
25+
rtypes::emit_toplevel(s, &kebab_name, ct);
26+
host::emit_toplevel(s, &kebab_name, ct);
27+
});
28+
util::emit_decls(decls).into()
29+
})
30+
}
31+
32+
/// Create the hyperlight_guest_init() function (which should be
33+
/// called in hyperlight_main()) for the wasm component type in the
34+
/// file passed in (or `$WIT_WORLD`, if nothing is passed in). This
35+
/// function registers Hyperlight functions for component exports
36+
/// (which are implemented by calling into the trait provided) and
37+
/// implements the relevant traits for a trivial Host type (by calling
38+
/// into the Hyperlight host).
39+
#[proc_macro]
40+
pub fn guest_bindgen(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
41+
let path: Option<syn::LitStr> = syn::parse_macro_input!(input as Option<syn::LitStr>);
42+
let path = path
43+
.map(|x| x.value().into())
44+
.unwrap_or_else(|| std::env::var_os("WIT_WORLD").unwrap());
45+
util::read_wit_type_from_file(path, |kebab_name, ct| {
46+
let decls = emit::run_state(true, false, |s| {
47+
// Emit type/trait definitions for all instances in the world
48+
rtypes::emit_toplevel(s, &kebab_name, ct);
49+
// Emit the host/guest function registrations
50+
guest::emit_toplevel(s, &kebab_name, ct);
51+
});
52+
// Use util::emit_decls() to choose between emitting the token
53+
// stream directly and emitting an include!() pointing at a
54+
// temporary file, depending on whether the user has requested
55+
// a debug temporary file be created.
56+
util::emit_decls(decls).into()
57+
})
58+
}

src/hyperlight_host/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ metrics-util = "0.19.1"
102102
metrics-exporter-prometheus = "0.17.0"
103103
tracing-tracy = "0.11.4"
104104
serde_json = "1.0"
105+
hyperlight-component-macro = { workspace = true }
105106

106107
[target.'cfg(windows)'.dev-dependencies]
107108
windows = { version = "0.61", features = [

0 commit comments

Comments
 (0)