Skip to content

Commit a09f2e9

Browse files
authored
Add WASI P3 tabs to creating-runnable-components/rust.md (#350)
* docs(creating-runnable-components/rust): add WASI P3 tabs WASI 0.3.0 made `wasi:cli/run` an `async func`, so this page now teaches the P3 pattern alongside the existing P2 one. Tab the build and run invocations to cover the `wasm32-wasip3` nightly target and the `-Sp3 -W component-model-async=y` flags, tab the WIT to pin `wasi:cli/run@0.3.0`, and tab the Rust code to show the `async fn run()` signature that `wit-bindgen` with the `async` feature now generates. Signed-off-by: Eric Gregory <eric@cosmonic.com> * docs(creating-runnable-components/rust): revise P3 tabs against verified path Walked the page end-to-end against the current toolchain and reworked the P3 content to match what actually works on 2026-06-12: - Drop the P3 tab from "Creating a command component". `rustup target add wasm32-wasip3` fails (Tier 3, no prebuilt artifacts), and Rust's std has not yet migrated to use P3 imports, so the `fn main()` pattern has no honest P3 story today. Replace with a pointer to the library/reactor pattern below. - Library/reactor P3 tabs now build against `wasm32-wasip2` with a nightly toolchain (stable's bundled `wasm-component-ld` cannot decode the component-type custom section `wit-bindgen` 0.58 emits for P3 worlds). - Pin the P3 WIT example to `wasi:cli/run@0.3.0-rc-2026-03-15`. The published `0.3.0` tag fails at run time against current Wasmtime and `wit-bindgen` (the version-pinning trap we documented as a footnote is load-bearing today). - Note that `wkg` 0.15 or later is needed for `wkg wit fetch` on the P3 package. - Fix a long-standing path bug: cargo converts hyphens to underscores in library crate names, so the artifact is `runnable_example.wasm`, not `runnable-example.wasm`, and lives under `target/.../debug/`. - Update the top-of-page notice and the bottom version-pinning blockquote to capture the transitional state. Signed-off-by: Eric Gregory <eric@cosmonic.com> * docs: rename WASI P2/P3 to WASI 0.2/0.3 in rust runnable-components page Per WASI maintainer guidance, refer to the WASI specifications as "WASI 0.2" and "WASI 0.3" in prose. Technical identifiers like `wasm32-wasip3`, `-Sp3`, and `wasi:cli/run@0.3.0-rc-...` are unaffected. Signed-off-by: Eric Gregory <eric@cosmonic.com> --------- Signed-off-by: Eric Gregory <eric@cosmonic.com>
1 parent 856387d commit a09f2e9

1 file changed

Lines changed: 117 additions & 3 deletions

File tree

  • component-model/src/language-support/creating-runnable-components

component-model/src/language-support/creating-runnable-components/rust.md

Lines changed: 117 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# Creating Runnable Components (Rust)
22

3+
<div class="version-notice">
4+
5+
This page has content for both **WASI 0.2** and **WASI 0.3**. Use the tabs below to switch between versions where they differ.
6+
7+
> **WASI 0.3 toolchain note.** Rust's [`wasm32-wasip3` target](https://doc.rust-lang.org/nightly/rustc/platform-support/wasm32-wasip3.html) is currently Tier 3 with no prebuilt artifacts; building for it requires constructing the standard library from source. The 0.3 example on this page therefore uses the library/reactor pattern targeting `wasm32-wasip2`, where [`wit-bindgen`](https://crates.io/crates/wit-bindgen)'s `async` feature handles the 0.3 binding generation. There is no Rust-idiomatic 0.3 path for the `fn main()` command-component pattern yet.
8+
9+
</div>
10+
311
## Creating a command component
412

513
A _command_ is a component with a specific export that allows it to be executed directly by `wasmtime`
@@ -45,7 +53,7 @@ cargo build --target=wasm32-wasip2
4553

4654
The component can also be built in release mode:
4755

48-
```console
56+
```sh
4957
cargo build --target=wasm32-wasip2 --release
5058
```
5159

@@ -57,6 +65,8 @@ To run your command component:
5765
wasmtime run ./target/wasm32-wasip2/debug/runnable-example.wasm
5866
```
5967

68+
> For a runnable component that exports the 0.3 `wasi:cli/run` interface, see the library/reactor pattern below.
69+
6070
## Enabling a library component to be run via the `wasi:cli/run` interface
6171

6272
Sometimes, it is useful to create a component that can *both* be used as a library (via
@@ -91,15 +101,28 @@ crate-type = ['cdylib']
91101

92102
We'll also be generating Rust bindings from WIT interfaces, so add `wit-bindgen`:
93103

104+
{{#tabs global="wasi-version" }}
105+
{{#tab name="WASI 0.2" }}
94106
```sh
95107
cargo add wit-bindgen
96108
```
109+
{{#endtab }}
110+
{{#tab name="WASI 0.3" }}
111+
```sh
112+
cargo add wit-bindgen --features async
113+
```
114+
115+
The `async` feature enables `wit-bindgen`'s async code generation, which is needed for the 0.3 `async func run()` signature.
116+
{{#endtab }}
117+
{{#endtabs }}
97118

98119
### 2. Add the appropriate WIT interfaces
99120

100121
Then, add the appropriate WIT interfaces. For example a simple component that prints "Hello World", add the following
101122
contents to `runnable-example/wit/component.wit`:
102123

124+
{{#tabs global="wasi-version" }}
125+
{{#tab name="WASI 0.2" }}
103126
```wit
104127
package example:runnable;
105128
@@ -112,6 +135,26 @@ world greeter {
112135
export wasi:cli/run@0.2.7;
113136
}
114137
```
138+
{{#endtab }}
139+
{{#tab name="WASI 0.3" }}
140+
```wit
141+
package example:runnable;
142+
143+
interface greet {
144+
greet: func(name: string) -> string;
145+
}
146+
147+
world greeter {
148+
export greet;
149+
export wasi:cli/run@0.3.0-rc-2026-03-15;
150+
}
151+
```
152+
153+
In WASI 0.3, `wasi:cli/run` is declared as `run: async func() -> result`, so the generated `Guest` trait expects an `async fn`.
154+
155+
> The pin here is `0.3.0-rc-2026-03-15` rather than the published `0.3.0` because Wasmtime, `wit-bindgen`, and other toolchain components currently ship this snapshot of the WIT. They are expected to refresh to `0.3.0` in upcoming releases.
156+
{{#endtab }}
157+
{{#endtabs }}
115158

116159
Building a library component this way does two things:
117160

@@ -126,6 +169,8 @@ using `wkg`:
126169
wkg wit fetch
127170
```
128171

172+
> For WASI 0.3, use `wkg` 0.15 or later. Earlier versions fail to decode the `wasi:cli@0.3.0-rc-2026-03-15` package.
173+
129174
At this point, you should have a `wit` folder with a `deps` subfolder and your original `component.wit`.
130175

131176
The component we will create to satisfy the WIT above can be used as a library, as other components
@@ -137,6 +182,8 @@ with any tooling (ex. `wasmtime run`) that supports/recognizes the `wasi:cli` in
137182

138183
The following code can be inserted into `runnable-example/src/lib.rs`:
139184

185+
{{#tabs global="wasi-version" }}
186+
{{#tab name="WASI 0.2" }}
140187
```rust
141188
mod bindings {
142189
use super::Component;
@@ -164,9 +211,43 @@ impl bindings::exports::wasi::cli::run::Guest for Component {
164211
}
165212
}
166213
```
214+
{{#endtab }}
215+
{{#tab name="WASI 0.3" }}
216+
```rust
217+
mod bindings {
218+
use super::Component;
219+
220+
wit_bindgen::generate!();
221+
222+
export!(Component);
223+
}
224+
225+
/// Component off of which implementation will hang (this can be named anything)
226+
struct Component;
227+
228+
/// Implementation for the `greet` interface export
229+
impl bindings::exports::example::runnable::greet::Guest for Component {
230+
fn greet(name: String) -> String {
231+
format!("Hello {name}!")
232+
}
233+
}
234+
235+
/// Implementation for `wasi:cli/run` interface export.
236+
/// In WASI 0.3 the `run` function is asynchronous.
237+
impl bindings::exports::wasi::cli::run::Guest for Component {
238+
async fn run() -> Result<(), ()> {
239+
eprintln!("Hello World!");
240+
Ok(())
241+
}
242+
}
243+
```
244+
{{#endtab }}
245+
{{#endtabs }}
167246

168247
### 4. Build the component
169248

249+
{{#tabs global="wasi-version" }}
250+
{{#tab name="WASI 0.2" }}
170251
To build the component, use `cargo`:
171252

172253
```sh
@@ -175,16 +256,49 @@ cargo build --target=wasm32-wasip2
175256

176257
The component can also be built in release mode:
177258

178-
```console
259+
```sh
179260
cargo build --target=wasm32-wasip2 --release
180261
```
262+
{{#endtab }}
263+
{{#tab name="WASI 0.3" }}
264+
Build the component against `wasm32-wasip2` using a nightly Rust toolchain:
265+
266+
```sh
267+
cargo +nightly build --target=wasm32-wasip2
268+
```
269+
270+
Release mode:
271+
272+
```sh
273+
cargo +nightly build --target=wasm32-wasip2 --release
274+
```
275+
276+
> A nightly toolchain is required because the `wasm-component-ld` bundled with current stable Rust cannot decode the component-type custom section that `wit-bindgen` 0.58 emits for 0.3 worlds. Nightly ships a newer linker that handles it.
277+
{{#endtab }}
278+
{{#endtabs }}
181279

182280
### 5. Run the component with `wasmtime`
183281

282+
{{#tabs global="wasi-version" }}
283+
{{#tab name="WASI 0.2" }}
184284
You can run the component with `wasmtime`, and unlike a generic reactor component, you do not need to specify
185285
the interface and function to run (`wasi:cli/run` is detected and used automatically):
186286

187287
```console
188-
$ wasmtime run target/wasm32-wasip2/runnable-example.wasm
288+
$ wasmtime run target/wasm32-wasip2/debug/runnable_example.wasm
289+
Hello World!
290+
```
291+
292+
> Cargo converts hyphens to underscores in library crate names, so the artifact is `runnable_example.wasm` even though the package was created as `runnable-example`.
293+
{{#endtab }}
294+
{{#tab name="WASI 0.3" }}
295+
Enable the WASI 0.3 ABI when running a 0.3 component, with Wasmtime 43 or later:
296+
297+
```console
298+
$ wasmtime run -Sp3 -W component-model-async=y target/wasm32-wasip2/debug/runnable_example.wasm
189299
Hello World!
190300
```
301+
{{#endtab }}
302+
{{#endtabs }}
303+
304+
> **Version pinning.** WASI 0.3 tools (`wit-bindgen`, Wasmtime, jco, and so on) must all target the same WIT version. As of WASI 0.3.0's release on 2026-06-11, `wit-bindgen` 0.58 and Wasmtime 45 still ship the `0.3.0-rc-2026-03-15` snapshot of the WIT; pinning to the published `0.3.0` produces `no exported instance named wasi:cli/run@0.2.6` (or similar) errors at run time until those tools refresh. Use the RC pin until then.

0 commit comments

Comments
 (0)