What to do with Linker if there's no import state or data? I have no idea what HelloWorld::add_to_linker(&mut linker, |state: &mut MyState| state)?;
would be for a WASM component that doesn't have an import. My WIT:
package eighty4:odd-or-even;
world lib {
export is-odd-or-even: func(number: s32) -> bool;
}
What trait should I add to my runtime state struct?
use wasmtime::{Config, Engine, Linker, Store};
use wasmtime::component::Component;
wasmtime::component::bindgen!({
path: "wit",
});
struct RuntimeState;
fn main() -> wasmtime::Result<()> {
println!("Hello, world!");
let mut config = Config::new();
config.wasm_component_model(true);
let engine = Engine::new(&config)?;
let component = Component::from_file(&engine, "./guest/golang/build/is_odd_or_even.component.wasm")?;
let mut linker = Linker::new(&engine);
let mut store = Store::new(&engine, RuntimeState {});
let (bindings, instance) = Lib::instantiate(&mut store, &component, &linker)?;
if bindings.call_is_odd_or_even(&store, 26)? {
println!("26 is even")
} else {
println!("26 is odd")
}
Ok(())
}
You can probably skip the add_to_linker
entirely if the world has no imports, but with no imports it should in theory have no extra trait bounds on the return value since I think the closure would largely go unused. Do you see a compile error though trying to use add_to_linker
?
I can't find add_to_linker. Is there a Rust standard way to see what generated code is created by a macro?
I've personally used cargo expand
before, but in this case I think it's because no add_to_linker
is generated since there are no imports.
Here's my error:
error[E0308]: mismatched types
--> src/main.rs:19:73
|
19 | let (bindings, instance) = Lib::instantiate(&mut store, &component, &linker)?;
| ---------------- ^^^^^^^ expected `&Linker<RuntimeState>`, found `&Linker<_>`
| |
| arguments to this function are incorrect
|
= note: expected reference `&wasmtime::component::Linker<RuntimeState>`
found reference `&wasmtime::Linker<_>`
note: associated function defined here
--> src/main.rs:4:1
|
4 | wasmtime::component::bindgen!();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: this error originates in the macro `wasmtime::component::bindgen` (in Nightly builds, run with -Z macro-backtrace for more info)```
Oh that's a slightly different error, you're using wasmtime::Linker
as opposed to wasmtime::component::Linker
(it's a bit buried in the error message)
:fireworks: for the compile, but now I have Error: import
wasi:io/error@0.2.0 has the wrong type
at runtime
Do I need to add the WASM that I used as an adapter to the runtime?
Ah yes so in this case that means that your wit world doesn't quite capture what the component fully does, which is to use WASI as well. You'll likely want to use wasmtime_wasi::command::sync::add_to_linker
for that you'll need to do a bit more as well, you can follow this example but swap out the async bits for sync bits
The plot thickens
If you're feeling intrepid there's also https://github.com/bytecodealliance/wasmtime/pull/8228 which improves documentation here, but currently wasmtime-wasi
is somewhat sparse on docs
I'm confused why I need to depend on any WASI interfaces, why I have to add all the imports for the WASI adapter to the WASM component, if my function interface is just a primitive number and boolean.
Could this example have worked without wasmtime-wasi if I didn't link the WASI adapter?
you don't have to depend on WASI, but language runtimes often bring in WASI symbols as a dependency, for example debug printing and environment variables or various things for the runtime
if you didn't link the wasi adapter then the example may work, but you may not have been able to produce a component in the first place
True story Error: failed to parse WebAssembly module
I'm kinda stumped... adding these capabilities to the WASI context because the WASM component has all these imports that my implementation code in the component doesn't use completely drops all the containerized security benefits of a WASM component that's just a pure function.
Well, before drawing dramatic conclusions, I'd caution you that it seems like there's a lot going on here and there's pieces you don't fully understand. It might be worth introspecting various steps along the way to see where WASI is required and what's pulling it in. I need to go for now, but as I mentioned earlier some language runtimes pull in WASI for various purposes, and it looks like you're using TinyGo, and I'm not sure TinyGo has a way to build without WASI. Rust, however, does have a way to do that, so this is not a property of wasm or components but probably moreso the language you're using.
I built a component with wit-bindgen as well and the Rust component added more WASI dependencies that TinyGo didn't include. Thanks for the assistance, Alex. I made great progress with your help today.
@adam definitely share the happy result tricks with tinygo here. Others might learn from your labors!
Last updated: Nov 22 2024 at 16:03 UTC