|
1 | 1 | # Creating Runnable Components (Rust) |
2 | 2 |
|
3 | | -## Exporting the `wasi:cli/run` interface |
| 3 | +## Creating a command component |
| 4 | + |
| 5 | +A _command_ is a component with a specific export that allows it to be executed directly by `wasmtime` |
| 6 | +(or other `wasi:cli` hosts). In Rust terms, it's the equivalent of an application (`bin`) package with |
| 7 | +a `main` function, instead of a library crate (`lib`) package. |
| 8 | + |
| 9 | +Command components work by including a WebAssembly core export `_start` that indicates the component |
| 10 | +has a natural `main`-like starting point. |
| 11 | + |
| 12 | +### 1. Create a new Rust binary project |
| 13 | + |
| 14 | +To create a command with cargo, run: |
| 15 | + |
| 16 | +```sh |
| 17 | +cargo new runnable-example |
| 18 | +``` |
| 19 | + |
| 20 | +Unlike library components, this does _not_ have the `--lib` flag (`--bin` is the default for `cargo new`). |
| 21 | + |
| 22 | +The created Rust source file is called `main.rs` instead of `lib.rs`, and contains a `main` function. |
| 23 | + |
| 24 | +You can write Rust in this project, just as you normally would, including importing your own or third-party crates. |
| 25 | + |
| 26 | +> 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. |
| 27 | +
|
| 28 | +### 2. Write the relevant Rust |
| 29 | + |
| 30 | +The following code can be inserted into `runnable-example/src/main.rs`: |
| 31 | + |
| 32 | +```rust |
| 33 | +pub fn main() { |
| 34 | + eprintln!("Hello World!"); |
| 35 | +} |
| 36 | +``` |
| 37 | + |
| 38 | +### 3. Build the component |
| 39 | + |
| 40 | +To build the component, use `cargo`: |
| 41 | + |
| 42 | +```sh |
| 43 | +cargo build --target=wasm32-wasip2 |
| 44 | +``` |
| 45 | + |
| 46 | +The component can also be built in release mode: |
| 47 | + |
| 48 | +```console |
| 49 | +cargo build --target=wasm32-wasip2 --release |
| 50 | +``` |
| 51 | + |
| 52 | +### 4. Run the component with `wasmtime` |
| 53 | + |
| 54 | +To run your command component: |
| 55 | + |
| 56 | +```sh |
| 57 | +wasmtime run ./target/wasm32-wasip2/debug/runnable-example.wasm |
| 58 | +``` |
| 59 | + |
| 60 | +> [!WARNING] |
| 61 | +> If your program prints to standard out or error, you may not see the printed output! |
| 62 | +> |
| 63 | +> Some versions of `wasmtime` have a bug where they don't flush output streams before exiting. To work |
| 64 | +> around this, add a `std::thread::sleep()` with a 10 millisecond delay before exiting `main`. |
| 65 | +
|
| 66 | +## Enabling a library component to be run via the `wasi:cli/run` interface |
4 | 67 |
|
5 | 68 | Any reactor (library-like) component can *also* export the [`run` interface][wasi-cli-iface-run] inside [WASI CLI][wasi-cli], |
6 | 69 | and signal to consumers that the library can also be run similarly to a binary. |
7 | 70 |
|
| 71 | +Unlike command components, library components have no `_start`, but by exporting the `wasi:cli/run` interface, |
| 72 | +tooling that recognizes these exports can easily execute the given WebAssembly binary (e.g. `wasmtime run`). |
| 73 | + |
8 | 74 | [wasi-cli-iface-run]: https://github.com/WebAssembly/wasi-cli/tree/main/wit/run.wit |
9 | 75 | [wasi-cli]: https://github.com/WebAssembly/wasi-cli |
10 | 76 |
|
@@ -125,63 +191,3 @@ the interface and function to run (`wasi:cli/run` is detected and used automatic |
125 | 191 | $ wasmtime run target/wasm32-wasip2/runnable-example.wasm |
126 | 192 | Hello World! |
127 | 193 | ``` |
128 | | - |
129 | | -## Creating a command component |
130 | | - |
131 | | -A _command_ is a component with a specific export that allows it to be executed directly by `wasmtime` |
132 | | -(or other `wasi:cli` hosts). In Rust terms, it's the equivalent of an application (`bin`) package with |
133 | | -a `main` function, instead of a library crate (`lib`) package. |
134 | | - |
135 | | -### 1. Create a new Rust binary project |
136 | | - |
137 | | -To create a command with cargo, run: |
138 | | - |
139 | | -```sh |
140 | | -cargo new runnable-example |
141 | | -``` |
142 | | - |
143 | | -Unlike library components, this does _not_ have the `--lib` flag (`--bin` is the default for `cargo new`). |
144 | | - |
145 | | -The created Rust source file is called `main.rs` instead of `lib.rs`, and contains a `main` function. |
146 | | - |
147 | | -You can write Rust in this project, just as you normally would, including importing your own or third-party crates. |
148 | | - |
149 | | -> 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. |
150 | | -
|
151 | | -### 2. Write the relevant Rust |
152 | | - |
153 | | -The following code can be inserted into `runnable-example/src/main.rs`: |
154 | | - |
155 | | -```rust |
156 | | -pub fn main() { |
157 | | - eprintln!("Hello World!"); |
158 | | -} |
159 | | -``` |
160 | | - |
161 | | -### 3. Build the component |
162 | | - |
163 | | -To build the component, use `cargo`: |
164 | | - |
165 | | -```sh |
166 | | -cargo build --target=wasm32-wasip2 |
167 | | -``` |
168 | | - |
169 | | -The component can also be built in release mode: |
170 | | - |
171 | | -```console |
172 | | -cargo build --target=wasm32-wasip2 --release |
173 | | -``` |
174 | | - |
175 | | -### 4. Run the component with `wasmtime` |
176 | | - |
177 | | -To run your command component: |
178 | | - |
179 | | -```sh |
180 | | -wasmtime run ./target/wasm32-wasip2/debug/runnable-example.wasm |
181 | | -``` |
182 | | - |
183 | | -> [!WARNING] |
184 | | -> If your program prints to standard out or error, you may not see the printed output! |
185 | | -> |
186 | | -> Some versions of `wasmtime` have a bug where they don't flush output streams before exiting. To work |
187 | | -> around this, add a `std::thread::sleep()` with a 10 millisecond delay before exiting `main`. |
|
0 commit comments