Skip to content

Commit 54b2731

Browse files
chore(lang/rust): add command component section
1 parent c58c2b6 commit 54b2731

File tree

1 file changed

+40
-42
lines changed
  • component-model/src/language-support/creating-runnable-components

1 file changed

+40
-42
lines changed

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

Lines changed: 40 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,7 @@ contents to `runnable-example/wit/component.wit`:
3939
```wit
4040
package example:runnable;
4141
42-
interface greet {
43-
greet: func(name: string) -> string;
44-
}
45-
4642
world greeter {
47-
export greet;
4843
export wasi:cli/[email protected];
4944
}
5045
```
@@ -72,41 +67,19 @@ The following code can be inserted into `runnable-example/src/lib.rs`:
7267

7368
```rust
7469
mod bindings {
75-
wit_bindgen::generate!()
76-
}
77-
70+
use super::Component;
7871

79-
package example:runnable;
80-
81-
interface greet {
82-
greet: func(name: string) -> string;
83-
}
72+
wit_bindgen::generate!();
8473

85-
world greeter {
86-
export greet;
87-
export wasi:cli/run@0.2.7;
74+
export!(Component);
8875
}
8976

9077
/// Component off of which implementation will hang (this can be named anything)
9178
struct Component;
9279

93-
impl Component {
94-
fn greet(s: impl AsRef<str>) -> String {
95-
format!("hello {s}!");
96-
}
97-
}
98-
99-
export bindings::example::runnable::greet::Guest for Component {
100-
fn greet(&self, s: String) -> String {
101-
self.greet(s)
102-
}
103-
}
104-
10580
export bindings::wasi::cli::run::Guest for Component {
10681
fn run(&self) -> Result<(), ()> {
107-
// NOTE: here, we would normally use more of the wasi:cli interface
108-
// to grab arguments and other information from the execution environment.
109-
eprintln!("CLI => {}", self.greet("CLI User"));
82+
eprintln!("Hello World!");
11083
Ok(())
11184
}
11285
}
@@ -127,34 +100,59 @@ the interface and function to run (`wasi:cli/run` is detected and used automatic
127100

128101
```console
129102
$ wasmtime run target/wasm32-wasip2/runnable-example.wasm
130-
CLI => hello CLI User!
103+
Hello World!
131104
```
132105

133106
## Creating a command component
134107

135-
A _command_ is a component with a specific export that allows it to be executed directly by `wasmtime` (or other `wasi:cli` hosts). In Rust terms, it's the equivalent of an application (`bin`) package with a `main` function, instead of a library crate (`lib`) package.
108+
A _command_ is a component with a specific export that allows it to be executed directly by `wasmtime`
109+
(or other `wasi:cli` hosts). In Rust terms, it's the equivalent of an application (`bin`) package with
110+
a `main` function, instead of a library crate (`lib`) package.
111+
112+
### 1. Create a new Rust binary project
136113

137-
To create a command with cargo component, run:
114+
To create a command with cargo, run:
138115

139116
```sh
140-
cargo component new <name>
117+
cargo new runnable-example
141118
```
142119

143-
Unlike library components, this does _not_ have the `--lib` flag. You will see that the created project is different too:
120+
Unlike library components, this does _not_ have the `--lib` flag (`--bin` is the default for `cargo new`).
144121

145-
- It doesn't contain a `.wit` file. `cargo component build` will automatically export the `wasi:cli/run` interface for Rust `bin` packages, and hook it up to `main`.
146-
- Because there's no `.wit` file, `Cargo.toml` doesn't contain a `package.metadata.component.target` section.
147-
- The Rust file is called `main.rs` instead of `lib.rs`, and contains a `main` function instead of an interface implementation.
122+
The created Rust source file is called `main.rs` instead of `lib.rs`, and contains a `main` function.
148123

149124
You can write Rust in this project, just as you normally would, including importing your own or third-party crates.
150125

151126
> All the crates that make up your project are linked together at build time, and compiled to a _single_ Wasm component. In this case, all the linking is happening at the Rust level: no WITs or component composition is involved. Only if you import Wasm interfaces do WIT and composition come into play.
152127
128+
### 2. Write the relevant Rust
129+
130+
The following code can be inserted into `runnable-example/src/main.rs`:
131+
132+
```rust
133+
pub fn main() {
134+
eprintln!("Hello World!");
135+
}
136+
```
137+
138+
### 3. Build the component
139+
140+
To build the component, use `cargo`:
141+
142+
```sh
143+
cargo build --target=wasm32-wasip2
144+
```
145+
146+
### 4. Run the component with `wasmtime`
147+
153148
To run your command component:
154149

155150
```sh
156-
cargo component build
157-
wasmtime run ./target/wasm32-wasip1/debug/<name>.wasm
151+
wasmtime run ./target/wasm32-wasip2/debug/runnable-example.wasm
158152
```
159153

160-
> **WARNING:** If your program prints to standard out or error, you may not see the printed output! Some versions of `wasmtime` have a bug where they don't flush output streams before exiting. To work around this, add a `std::thread::sleep()` with a 10 millisecond delay before exiting `main`.
154+
> [!WARNING]
155+
> If your program prints to standard out or error, you may not see the printed output!
156+
>
157+
> Some versions of `wasmtime` have a bug where they don't flush output streams before exiting. To work
158+
> around this, add a `std::thread::sleep()` with a 10 millisecond delay before exiting `main`.

0 commit comments

Comments
 (0)