Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revamp wasi example and related docs #9788

Open
wants to merge 18 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 14 additions & 6 deletions docs/examples-rust-wasi.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,33 +5,41 @@ repository to run the example locally.

[code]: https://github.com/bytecodealliance/wasmtime/blob/main/examples/wasi/main.rs

This example shows how to use the [`wasi-common`] crate to define WASI
This example shows how to use the [`wasmtime-wasi`] crate to define WASI
functions within a [`Linker`] which can then be used to instantiate a
WebAssembly module.

[`wasi-common`]: https://crates.io/crates/wasi-common
[`wasmtime-wasi`]: https://crates.io/crates/wasmtime-wasi
[`Linker`]: https://docs.rs/wasmtime/*/wasmtime/struct.Linker.html

### WebAssembly module source code

For this WASI example, this Hello World program is compiled to a WebAssembly module using the WASI Preview 1 API.
For this WASI example, this Hello World program is compiled to a WebAssembly module using the WASI Preview 2 API.

`wasi.rs`
```rust
{{#include ../examples/wasi/wasm/wasi.rs}}
```

Building this program generates `target/wasm32-wasip1/debug/wasi.wasm`, used below.
> Building instructions:
> 1. Update your Rust toolchain if it is not >= 1.83.0, as Rust 1.83.0 brings Tier 2 support for WASI Preview 2.
> `rustup update stable`
ifsheldon marked this conversation as resolved.
Show resolved Hide resolved
> 2. Add WASIp2 target if you haven't already: `rustup target add wasm32-wasip2`
> 3. `cargo build --target wasm32-wasip2`

### Invoke the WASM module
Building this program generates `target/wasm32-wasip2/debug/wasi.wasm`, used below.

This example shows adding and configuring the WASI imports to invoke the above WASM module.
### Invoke the WASM component

This example shows adding and configuring the WASI imports to invoke the above WASM component.

`main.rs`
```rust,ignore
{{#include ../examples/wasi/main.rs}}
```

TODO: Update the following section after `../examples/wasi/main.rs` is fixed

## WASI state with other custom host state

The [`add_to_linker`] takes a second argument which is a closure to access `&mut
Expand Down
45 changes: 33 additions & 12 deletions examples/wasi/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,31 +6,52 @@ You can execute this example with:
cargo run --example wasi
*/

use wasi_common::sync::WasiCtxBuilder;
use wasmtime::*;
use wasmtime_wasi::{WasiCtx, WasiView, WasiCtxBuilder};
use wasmtime::component::{Component, Linker, ResourceTable};

pub struct ComponentRunStates {
// These two are required basically as a standard way to enable the impl of WasiView
// impl of WasiView is required by [`wasmtime_wasi::add_to_linker_sync`]
pub wasi_ctx: WasiCtx,
pub resource_table: ResourceTable,
}

impl WasiView for ComponentRunStates {
fn table(&mut self) -> &mut ResourceTable {
&mut self.resource_table
}
fn ctx(&mut self) -> &mut WasiCtx {
&mut self.wasi_ctx
}
}

fn main() -> Result<()> {
// Define the WASI functions globally on the `Config`.
let engine = Engine::default();
let mut linker = Linker::new(&engine);
wasi_common::sync::add_to_linker(&mut linker, |s| s)?;
wasmtime_wasi::add_to_linker_sync(&mut linker)?;

// Create a WASI context and put it in a Store; all instances in the store
// share this context. `WasiCtxBuilder` provides a number of ways to
// configure what the target program will have access to.
let wasi = WasiCtxBuilder::new()
.inherit_stdio()
.inherit_args()?
.inherit_args()
.build();
let mut store = Store::new(&engine, wasi);

// Instantiate our module with the imports we've created, and run it.
let module = Module::from_file(&engine, "target/wasm32-wasip1/debug/wasi.wasm")?;
linker.module(&mut store, "", &module)?;
linker
.get_default(&mut store, "")?
.typed::<(), ()>(&store)?
.call(&mut store, ())?;
let state = ComponentRunStates {
wasi_ctx: wasi,
resource_table: ResourceTable::new(),
};
let mut store = Store::new(&engine, state);

// Instantiate our component with the imports we've created, and run it.
let component = Component::from_file(&engine, "target/wasm32-wasip2/debug/wasi.wasm")?;
let instance = linker.instantiate(&mut store, &component)?;
let exp_idx= instance.get_export(&mut store, None, "wasi:cli/run@0.2.0").unwrap();
// FIXME: Why can't I get an exported function here? The exp_idx is valid
ifsheldon marked this conversation as resolved.
Show resolved Hide resolved
let func = instance.get_func(&mut store, exp_idx).unwrap();
let typed = func.typed::<(), ()>(&store)?;
typed.call(&mut store, ())?;
Ok(())
}
Loading