Skip to content

Commit ec521a5

Browse files
committed
Add wasi example for verification
Signed-off-by: James Sturtevant <jstur@microsoft.com>
1 parent bd4423a commit ec521a5

13 files changed

Lines changed: 587 additions & 4 deletions

File tree

.github/workflows/dep_rust.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@ jobs:
7676
with:
7777
name: guest-modules
7878
path: ./x64/${{ matrix.config }}
79+
80+
- name: Build Rust Wasi examples
81+
run: just build-rust-wasi-examples ${{ matrix.config }}
7982

8083
- name: Fmt
8184
run: just fmt-check
@@ -124,6 +127,10 @@ jobs:
124127
# required for gh cli when downloading
125128
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
126129

130+
- name: Test Wasi Examples
131+
run: just examples-wasi ${{ matrix.config }} ${{ matrix.hypervisor == 'mshv3' && 'mshv3' || ''}}
132+
working-directory: ./src/hyperlight_wasm
133+
127134
### Benchmarks ###
128135

129136
- name: Download benchmarks from "latest"

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -478,3 +478,4 @@ target/
478478

479479
# MSVC Windows builds of rustc generate these, which store debugging information
480480
*.pdb
481+
src/wasi_samples/wit/component-world.wasm

Cargo.lock

Lines changed: 97 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[workspace]
2-
members = ["src/hyperlight_wasm", "src/examples_common", "src/hyperlight_wasm_aot" ]
3-
exclude = [ "src/wasm_runtime", "src/rust_wasm_samples", "src/hyperlight_wasm_macro" ]
2+
members = [ "src/hyperlight_wasm", "src/examples_common", "src/hyperlight_wasm_aot" ]
3+
exclude = [ "src/wasm_runtime", "src/rust_wasm_samples", "src/hyperlight_wasm_macro", "src/wasi_samples" ]
44
resolver = "2"
55

66
[workspace.dependencies]

Justfile

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@ default-tag:= "latest"
33
build-wasm-examples-command := if os() == "windows" { "./src/hyperlight_wasm/scripts/build-wasm-examples.bat" } else { "./src/hyperlight_wasm/scripts/build-wasm-examples.sh" }
44
mkdir-arg := if os() == "windows" { "-Force" } else { "-p" }
55
latest-release:= if os() == "windows" {"$(git tag -l --sort=v:refname | select -last 2 | select -first 1)"} else {`git tag -l --sort=v:refname | tail -n 2 | head -n 1`}
6+
wit-world := if os() == "windows" { "$env:WIT_WORLD=\"" + justfile_directory() + "\\src\\wasi_samples\\wit\\component-world.wasm" + "\";" } else { "WIT_WORLD=" + justfile_directory() + "/src/wasi_samples/wit/component-world.wasm" }
67

78
set windows-shell := ["pwsh.exe", "-NoLogo", "-Command"]
89

9-
build-all target=default-target: (build target) (build-wasm-examples target) (build-rust-wasm-examples target) (build-wasm-runtime target)
10+
build-all target=default-target: (build target) (build-wasm-examples target) (build-rust-wasm-examples target) (build-wasm-runtime target) (build-rust-wasi-examples target)
1011

1112
build target=default-target features="": (build-wasm-runtime target) (fmt-check)
1213
cargo build {{ if features =="" {''} else if features=="no-default-features" {"--no-default-features" } else {"--no-default-features -F " + features } }} --verbose --profile={{ if target == "debug" {"dev"} else { target } }}
@@ -31,23 +32,39 @@ build-rust-wasm-examples target=default-target: (mkdir-redist target)
3132
cargo run -p hyperlight-wasm-aot compile ./src/rust_wasm_samples/target/wasm32-unknown-unknown/{{ target }}/rust_wasm_samples.wasm ./x64/{{ target }}/rust_wasm_samples.aot
3233
cp ./x64/{{ target }}/rust_wasm_samples.aot ./x64/{{ target }}/rust_wasm_samples.wasm
3334

35+
build-rust-wasi-examples target=default-target:
36+
cargo install --locked wasm-tools
37+
cargo install cargo-component --locked
38+
wasm-tools component wit ./src/wasi_samples/wit/example.wit -w -o ./src/wasi_samples/wit/component-world.wasm
39+
# use cargo component so we don't get all the wasi imports https://github.com/bytecodealliance/cargo-component?tab=readme-ov-file#relationship-with-wasm32-wasip2
40+
# we also explicitly target wasm32-unknown-unknown since cargo component might try to pull in wasi imports https://github.com/bytecodealliance/cargo-component/issues/290
41+
rustup target add wasm32-unknown-unknown
42+
cd ./src/wasi_samples && cargo component build --target wasm32-unknown-unknown --profile={{ if target == "debug" {"dev"} else { target } }}
43+
cargo run -p hyperlight-wasm-aot compile --component ./src/wasi_samples/target/wasm32-unknown-unknown/{{ target }}/wasi_samples.wasm ./x64/{{ target }}/wasi_samples.aot
44+
cp ./x64/{{ target }}/wasi_samples.aot ./x64/{{ target }}/wasi_samples.wasm
45+
3446
check target=default-target:
3547
cargo check --profile={{ if target == "debug" {"dev"} else { target } }}
3648
cd src/rust_wasm_samples && cargo check --profile={{ if target == "debug" {"dev"} else { target } }}
49+
cd src/wasi_samples && cargo check --profile={{ if target == "debug" {"dev"} else { target } }}
3750
cd src/wasm_runtime && cargo check --profile={{ if target == "debug" {"dev"} else { target } }}
3851

3952
fmt-check:
4053
rustup toolchain install nightly -c rustfmt && cargo +nightly fmt -v --all -- --check
4154
cd src/rust_wasm_samples && rustup toolchain install nightly -c rustfmt && cargo +nightly fmt -v --all -- --check
55+
cd src/wasi_samples && rustup toolchain install nightly -c rustfmt && cargo +nightly fmt -v --all -- --check
4256
cd src/wasm_runtime && rustup toolchain install nightly -c rustfmt && cargo +nightly fmt -v --all -- --check
43-
fmt:
57+
fmt:
58+
rustup toolchain install nightly -c rustfmt
4459
cargo +nightly fmt --all
4560
cd src/rust_wasm_samples && cargo +nightly fmt
61+
cd src/wasi_samples && cargo +nightly fmt
4662
cd src/wasm_runtime && cargo +nightly fmt
4763

4864
clippy target=default-target: (check target)
4965
cargo clippy --profile={{ if target == "debug" {"dev"} else { target } }} --all-targets --all-features -- -D warnings
5066
cd src/rust_wasm_samples && cargo clippy --profile={{ if target == "debug" {"dev"} else { target } }} --all-targets --all-features -- -D warnings
67+
cd src/wasi_samples && cargo clippy --profile={{ if target == "debug" {"dev"} else { target } }} --all-targets --all-features -- -D warnings
5168
cd src/wasm_runtime && cargo clippy --profile={{ if target == "debug" {"dev"} else { target } }} --all-targets --all-features -- -D warnings
5269

5370
# TESTING
@@ -71,6 +88,9 @@ examples-ci target=default-target features="": (build-rust-wasm-examples target)
7188
cargo run {{ if features =="" {''} else {"--no-default-features -F function_call_metrics," + features } }} --profile={{ if target == "debug" {"dev"} else { target } }} --example metrics
7289
cargo run {{ if features =="" {"--no-default-features --features kvm,mshv2"} else {"--no-default-features -F function_call_metrics," + features } }} --profile={{ if target == "debug" {"dev"} else { target } }} --example metrics
7390

91+
examples-wasi target=default-target features="": (build-rust-wasi-examples target)
92+
{{ wit-world }} cargo run {{ if features =="" {''} else {"--no-default-features -F " + features } }} --profile={{ if target == "debug" {"dev"} else { target } }} --example wasi_examples
93+
7494
# warning, compares to and then OVERWRITES the given baseline
7595
bench-ci baseline target=default-target features="":
7696
cd src/hyperlight_wasm && cargo bench --profile={{ if target == "debug" {"dev"} else { target } }} {{ if features =="" {''} else { "--features " + features } }} -- --verbose --save-baseline {{baseline}}

README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ Make sure the following are installed:
2121
1. [pwsh](https://github.com/PowerShell/PowerShell)
2222
1. [git](https://gitforwindows.org/)
2323
1. [GitHub CLI](https://github.com/cli/cli#installation)
24+
1. [wasm-tools](https://github.com/bytecodealliance/wasm-tools?tab=readme-ov-file#installation)
25+
1. [cargo component](https://github.com/bytecodealliance/cargo-component?tab=readme-ov-file#installation)
2426

2527
Ensure that Windows Hypervisor Platform is enabled:
2628

@@ -38,6 +40,8 @@ Make sure the following are installed:
3840
1. [Rust](https://www.rust-lang.org/tools/install) `curl --proto '=https' --tlsv1.3 https://sh.rustup.rs -sSf | sh`
3941
1. [just](https://github.com/casey/just). is used as a command runner `cargo install just`. Do not install `just` through a package manager as it may install an older incompatible version, make sure to use at least version 1.5.0 if not installed through cargo.
4042
1. [GitHub CLI](https://github.com/cli/cli#installation)
43+
1. [wasm-tools](https://github.com/bytecodealliance/wasm-tools?tab=readme-ov-file#installation)
44+
1. [cargo component](https://github.com/bytecodealliance/cargo-component?tab=readme-ov-file#installation)
4145

4246
Ensure that KVM is enabled: On an Azure VM using a size that supports nested virtualisation:
4347

@@ -94,6 +98,17 @@ generate bindings from the same component type in the host. For a
9498
complete (albeit small) example of this, see [this
9599
example](https://aka.ms/hyperlight-wasm-sockets-sample).
96100

101+
### Debugging the macro
102+
103+
You can get more detailed error messages by expanding the Macro locally:
104+
105+
```
106+
cargo clean -p hyperlight-wasm
107+
WIT_WORLD=</path/to/output.wasm> HYPERLIGHT_COMPONENT_MACRO_DEBUG=/tmp/guest.rs cargo build -p hyperlight-wasm
108+
HYPERLIGHT_COMPONENT_MACRO_DEBUG=/tmp/host.rs cargo build
109+
```
110+
111+
97112
## Code of Conduct
98113

99114
This project has adopted the [Microsoft Open Source Code of

src/hyperlight_wasm/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ windows = { version = "0.61", features = ["Win32_System_Threading"] }
4444
page_size = "0.6.0"
4545

4646
[dev-dependencies]
47+
hyperlight-component-macro = "0.6.1"
4748
examples_common = { path = "../examples_common" }
4849
criterion = { version = "0.6.0", features = ["html_reports"] }
4950
crossbeam-queue = "0.3"
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
use bindings::wasi_sample::example::Adder;
2+
use examples_common::get_wasm_module_path;
3+
4+
extern crate alloc;
5+
mod bindings {
6+
hyperlight_component_macro::host_bindgen!("../wasi_samples/wit/component-world.wasm");
7+
}
8+
9+
pub struct State {}
10+
impl State {
11+
pub fn new() -> Self {
12+
State {}
13+
}
14+
}
15+
16+
impl Default for State {
17+
fn default() -> Self {
18+
Self::new()
19+
}
20+
}
21+
22+
impl bindings::wasi_sample::example::Host for State {
23+
fn r#print(&mut self, message: alloc::string::String) {
24+
println!("Logged from component: {message}");
25+
}
26+
27+
fn r#host_function(&mut self, input: alloc::string::String) -> alloc::string::String {
28+
format!("{input} and the host!")
29+
}
30+
}
31+
32+
#[allow(refining_impl_trait)]
33+
impl bindings::wasi_sample::example::ExampleImports for State {
34+
type Host = State;
35+
36+
fn r#host(&mut self) -> &mut Self {
37+
self
38+
}
39+
}
40+
41+
fn main() {
42+
let state = State::new();
43+
let mut sb: hyperlight_wasm::ProtoWasmSandbox = hyperlight_wasm::SandboxBuilder::new()
44+
.with_guest_input_buffer_size(70000000)
45+
.with_guest_heap_size(200000000)
46+
.with_guest_stack_size(100000000)
47+
.build()
48+
.unwrap();
49+
let rt = bindings::register_host_functions(&mut sb, state);
50+
51+
let sb = sb.load_runtime().unwrap();
52+
53+
let mod_path = get_wasm_module_path("wasi_samples.wasm").unwrap();
54+
let sb = sb.load_module(mod_path).unwrap();
55+
56+
let mut wrapped = bindings::ExampleSandbox { sb, rt };
57+
58+
let instance = bindings::wasi_sample::example::ExampleExports::adder(&mut wrapped);
59+
let result = instance.add(1, 2);
60+
assert_eq!(3, result);
61+
println!("Add result is {result}");
62+
let result = instance.add(4, 3);
63+
assert_eq!(7, result);
64+
println!("Add result is {result}");
65+
66+
let result = instance.call_host("Hello".to_string());
67+
assert_eq!("Hello from component and the host!", result);
68+
print!("Host Component interaction: {result}")
69+
}

src/wasi_samples/Cargo.lock

Lines changed: 25 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/wasi_samples/Cargo.toml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
[package]
2+
name = "wasi_samples"
3+
version = "0.1.0"
4+
edition = "2024"
5+
6+
[dependencies]
7+
wit-bindgen-rt = { version = "0.41.0", features = ["bitflags"] }
8+
9+
[lib]
10+
crate-type = ["cdylib"]
11+
12+
[package.metadata.component]
13+
package = "wasi-sample:example"
14+
15+
[package.metadata.component.target]
16+
path = "wit/example.wit"
17+
world = "example"
18+
19+
[package.metadata.component.target.dependencies]
20+

0 commit comments

Comments
 (0)