Add example wasm component and runner which embeds the component

This commit is contained in:
michaelpivato
2024-05-11 14:22:49 +09:30
commit fca84b9240
10 changed files with 1560 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
/target
bindings.rs

1436
Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

6
Cargo.toml Normal file
View File

@@ -0,0 +1,6 @@
[workspace]
members = [
"component",
"runner",
]

33
README.md Normal file
View File

@@ -0,0 +1,33 @@
# Wasmtime test
Example project showcasing how to run a wasm component with wasmtime, and how to build the runnable component using cargo component.
## Structure
### component
This package includes an example wasm component, which simply calls a `hello()` function provided by the runner.
### runner
This package includes an example runtime, to run the built wasm component from the component package.
## Build
First run `cargo component build -p component --release` to build the wasm component.
Then run `cargo run -p runner --release` to run the runner with the build wasm component from the previous step.
## Troubleshooting
If you see errors about imports missing when trying to run the compiled component, it's likely there's a dependency on std that isn't supported by the runtime linker (e.g. by calling `println!()`).
To build without std components, run the following:
`cargo component build --target wasm32-unknown-unknown --release`
Note this is only required when using std components. Preferably don't do this, and instead
use #![no_std] to not accidentally use std. Otherwise, you'll need to either use a runtime that includes std (e.g. wasmtime cli), or add the appropriate imports to the runtime linker.
To check the imports and exports for a compiled .wasm component, run the following (where component.wasm is the compiled .wasm file to inspect):
`wasm-tools component wit component.wasm`

13
component/Cargo.toml Normal file
View File

@@ -0,0 +1,13 @@
[package]
name = "component"
version = "0.1.0"
edition = "2021"
[dependencies]
wit-bindgen-rt = { version = "0.24.0", features = ["bitflags"] }
[lib]
crate-type = ["cdylib"]
[package.metadata.component]
package = "component:test"

14
component/src/lib.rs Normal file
View File

@@ -0,0 +1,14 @@
#[allow(warnings)]
mod bindings;
use bindings::{hello, Guest};
struct Component;
impl Guest for Component {
fn greet() {
hello();
}
}
bindings::export!(Component with_types_in bindings);

6
component/wit/test.wit Normal file
View File

@@ -0,0 +1,6 @@
package my:project;
world test {
import hello: func();
export greet: func();
}

7
runner/Cargo.toml Normal file
View File

@@ -0,0 +1,7 @@
[package]
name = "wasmtime-test"
version = "0.1.0"
edition = "2021"
[dependencies]
wasmtime = {version = "20.0.2", features = ["component-model"]}

37
runner/src/main.rs Normal file
View File

@@ -0,0 +1,37 @@
use wasmtime::{
component::{bindgen, Component, Linker},
Config, Engine, Store,
};
// Defaults to 'wit' folder adjacent to cargo.toml.
// Change folder by using: bindgen!(in "other/with/folder")
bindgen!();
struct TestState {
name: String,
}
impl TestImports for TestState {
fn hello(&mut self) -> std::result::Result<(), wasmtime::Error> {
println!("{}", self.name);
Ok(())
}
}
fn main() -> wasmtime::Result<()> {
let mut config = Config::new();
config.wasm_component_model(true);
let engine = Engine::new(&config)?;
let component = Component::from_file(&engine, "target/wasm32-wasi/release/component.wasm")?;
let mut linker = Linker::new(&engine);
Test::add_to_linker(&mut linker, |state: &mut TestState| state)?;
let mut store = Store::new(
&engine,
TestState {
name: "Hello World".to_string(),
},
);
let (bindings, _) = Test::instantiate(&mut store, &component, &linker)?;
bindings.call_greet(&mut store)?;
Ok(())
}

6
runner/wit/test.wit Normal file
View File

@@ -0,0 +1,6 @@
package my:project;
world test {
import hello: func();
export greet: func();
}