bytecodealliance / wasmtime

A fast and secure runtime for WebAssembly

Home Page:https://wasmtime.dev/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Satisfying imports for `wasmtime::component::bindgen!`

hone opened this issue · comments

Hi, I'm fairly new to all of this. If there's someplace else I should be going, please let me know. Thanks!

I'm trying to use bindgen! with a simple hello world WASM Component Model. I've built a simple one using:

$ cargo component new --lib hello
$ cd hello
$ cargo component build

The generated wit looks like the following:

package root:component;

world root {
  import wasi:cli/environment@0.2.0;
  import wasi:cli/exit@0.2.0;
  import wasi:io/error@0.2.0;
  import wasi:io/streams@0.2.0;
  import wasi:cli/stdin@0.2.0;
  import wasi:cli/stdout@0.2.0;
  import wasi:cli/stderr@0.2.0;
  import wasi:clocks/wall-clock@0.2.0;
  import wasi:filesystem/types@0.2.0;
  import wasi:filesystem/preopens@0.2.0;

  export hello: func() -> string;
}

When I manually use add_to_linker I can get it to work:

use std::error::Error;
use wasmtime::{
    component::{Component, Linker},
    {Config, Engine, Store},
};
use wasmtime_wasi::{
    bindings, {WasiCtxBuilder, WasiP1Ctx},
};

fn main() -> Result<(), Box<dyn Error>> {
    let engine = Engine::new(Config::new().wasm_component_model(true))?;

    let component = Component::from_file(&engine, "hello.wasm")?;

    let mut linker = Linker::<WasiP1Ctx>::new(&engine);
    bindings::cli::environment::add_to_linker(&mut linker, |x| x)?;
    bindings::wasi::cli::exit::add_to_linker(&mut linker, |x| x)?;
    bindings::wasi::io::error::add_to_linker(&mut linker, |x| x)?;
    bindings::sync_io::io::streams::add_to_linker(&mut linker, |x| x)?;
    bindings::wasi::cli::stdin::add_to_linker(&mut linker, |x| x)?;
    bindings::wasi::cli::stdout::add_to_linker(&mut linker, |x| x)?;
    bindings::wasi::cli::stderr::add_to_linker(&mut linker, |x| x)?;
    bindings::sync_io::filesystem::types::add_to_linker(&mut linker, |x| x)?;
    bindings::wasi::filesystem::preopens::add_to_linker(&mut linker, |x| x)?;

    let wasi_ctx = WasiCtxBuilder::new().build_p1();
    let mut store = Store::new(&engine, wasi_ctx);

    let instance = linker.instantiate(&mut store, &component)?;

    let func = instance
        .get_func(&mut store, "hello")
        .expect("hello export not found");
    let mut result = [wasmtime::component::Val::String("".into())];
    func.call(&mut store, &[], &mut result)?;

    println!("{:?}", result);

    Ok(())
}

I'm trying to follow the documentation on using wasmtime::components::bindgen!:

wasmtime::component::bindgen!({
    with: {
        "wasi:cli/environment@0.2.0": wasmtime_wasi::bindings::wasi::cli::environment,
        "wasi": "wasmtime_wasi::bindings",
     },
});

I can't seem to get around this error:

error: failed to resolve directory while parsing WIT for path [/home/hone/Projects/rust/wasm/wasmtime_component_hello/wit]
                                                                                                                               
       Caused by:                                                                                                              
           package not found                                                                                                   
                --> /home/hone/Projects/rust/wasm/wasmtime_component_hello/wit/hello.wit:4:10
                 |                                  
               4 |   import wasi:cli/environment@0.2.0;
                 |          ^-------     

Hello and thanks for the report! One issue here is that the WIT tooling isn't in a great place to give a good error message about this. Right now WIT directories need to be "self contained" meaning that if they refer to something, like wasi:cli/environment, then that needs to be in the WIT directory. For that you'll need to copy WASI WITs locally to work with them.

You can copy the WITs from the upstream repositories or from Wasmtime itself for now. In the future we hope to improve the copy-things-around situation but we're not quite there yet.

Right now WIT directories need to be "self contained" meaning that if they refer to something, like wasi:cli/environment, then that needs to be in the WIT directory

Because it wasn't clear to me, and this issue came up in my search: put the additional .wit files in deps, e.g. I made wit/deps/network.wit to re-use types from wasi:sockets/network.