From 2e207e41d470bca94b3f307fb5a9fc77e797bb71 Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Tue, 18 Mar 2025 16:43:43 -0500 Subject: [PATCH 01/13] initial prereqs commit --- .../src/language-support/javascript.md | 4 +- component-model/src/language-support/rust.md | 126 ++++++++++++------ 2 files changed, 86 insertions(+), 44 deletions(-) diff --git a/component-model/src/language-support/javascript.md b/component-model/src/language-support/javascript.md index b0640bae..eb17eec8 100644 --- a/component-model/src/language-support/javascript.md +++ b/component-model/src/language-support/javascript.md @@ -216,7 +216,7 @@ With `jco transpile` any WebAssembly binary (compiled from any language) can be Reactor components are WebAssembly components that are long running and meant to be called repeatedly over time. They're analogous to libraries of functionality rather than an executable (a "command" component). -Components expose their interfaces via [WebAssembly Interface Types][docs-wit], hand-in-hand with the [Component Model][docs-component-model] which enables components to use higher level types interchangably. +Components expose their interfaces via [WebAssembly Interface Types][docs-wit], hand-in-hand with the [Component Model][docs-component-model] which enables components to use higher level types interchangeably. [docs-wit]: ../design/wit.md @@ -312,7 +312,7 @@ You should see output like the following: OK Successfully written string-reverse.wasm. ``` -Now that we have a WebAssembly binary, we can *also* use `jco` to run it in a native JavaScript context by *transpiling* the WebAsssembly binary (which could have come from anywhere!) to a JavaScript module. +Now that we have a WebAssembly binary, we can *also* use `jco` to run it in a native JavaScript context by *transpiling* the WebAssembly binary (which could have come from anywhere!) to a JavaScript module. ```console npx jco transpile string-reverse.wasm -o dist/transpiled diff --git a/component-model/src/language-support/rust.md b/component-model/src/language-support/rust.md index 263bbaa1..fd3c577a 100644 --- a/component-model/src/language-support/rust.md +++ b/component-model/src/language-support/rust.md @@ -1,40 +1,80 @@ # Components in Rust -Rust has first-class support for the component model via [the `cargo component` tool](https://github.com/bytecodealliance/cargo-component). It is a `cargo` subcommand for -creating WebAssembly components using Rust as the component's implementation language. +Rust has first-class support for the component model via the [`cargo-component` +tool](https://github.com/bytecodealliance/cargo-component). We will be using +the `cargo component` subcommand to create WebAssembly components using Rust as +the component's implementation language. -## Installing `cargo component` +> [!NOTE] +> You can find more details about `cargo-component` on [crates.io](https://crates.io/crates/cargo-component). -To install `cargo component`, run: +## Prerequisites +Install [`cargo-component`](https://github.com/bytecodealliance/cargo-component#installation): ```sh -cargo install cargo-component +cargo install --locked cargo-component +``` +Install [`wasm-tools`](https://github.com/bytecodealliance/wasm-tools#installation): +```sh +cargo install --locked wasm-tools +``` +Install [`wasmtime`](https://github.com/bytecodealliance/wasmtime#installation): +```sh +curl https://wasmtime.dev/install.sh -sSf | bash +``` +Clone the [component-docs](https://github.com/bytecodealliance/component-docs) repo: +```sh +git clone https://github.com/bytecodealliance/component-docs ``` - -> You can find more details about `cargo component` in its [crates.io page](https://crates.io/crates/cargo-component). ## Building a Component with `cargo component` -Create a Rust library that implements the `add` function in the [`example` -world](https://github.com/bytecodealliance/component-docs/tree/main/component-model/examples/example-host/add.wit). First scaffold a project: +We will create a component in Rust that implements the `add` function exported +by the [`example:component/example`][example-component] world in the +`example:component` +[package](https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md#package-names). +First `cd` into the `tutorial` directory found in the repo we just cloned: +```sh +cd component-docs/component-model/examples/tutorial +``` + +Now create a new WebAssembly component package called `add`: ```sh $ cargo component new add --lib && cd add ``` -Note that `cargo component` generates the necessary bindings as a module called `bindings`. +> [!NOTE] +> `cargo-component` generates the necessary bindings for us in a module called `bindings` found in `src/bindings.rs`. + +Next change our generated `wit/world.wit` to match `example:component`: +```wit +{{#include ../../examples/example-host/add.wit}} +``` -Next, update `wit/world.wit` to match `add.wit` and modify the component package reference to change the -package name to `example:component`. The `component` section of `Cargo.toml` should look like the following: +Since our WIT file changed names (from `component:add` to +`example:component`) this needs to be reflected in our `Cargo.toml`, +let's change the `package.metadata.component.package` string to `"example:component"`: ```toml [package.metadata.component] package = "example:component" ``` -`cargo component` will generate bindings for the world specified in a package's `Cargo.toml`. In particular, it will create a `Guest` trait that a component should implement. Since our `example` world has no interfaces, the trait lives directly under the bindings module. Implement the `Guest` trait in `add/src/lib.rs` such that it satisfies the `example` world, adding an `add` function: +`cargo component` will generate bindings for the +`example:component/example` world we specified `Cargo.toml`, it will also +create a `Guest` trait that a component can implement. +Since our `example:component/example` world has no interfaces, our +generated `Guest` trait lives at the top of the `bindings` module. + +Implementing the `Guest` trait for our `Component` struct requires us +to match the structure specified by `example:component/example`, we do this by +implementing the `add` method with the equivalent function signature. Our +`src/lib.rs` should look similar to the following: ```rs +mod bindings; + struct Component; impl Guest for Component { @@ -42,18 +82,25 @@ impl Guest for Component { x + y } } + +bindings::export!(Component with_types_in bindings); ``` -Now, use `cargo component` to build the component, being sure to optimize with a release build. +Now, let's build our component with release optimizations: ```sh -$ cargo component build --release +cargo component build --release ``` -You can use `wasm-tools component wit` to output the WIT package of the component: +You can use `wasm-tools` to inspect the WIT package generated by `cargo-component`: ```sh -$ wasm-tools component wit target/wasm32-wasip1/release/add.wasm +wasm-tools component wit target/wasm32-wasip1/release/add.wasm +``` + +The command above should produce the output below: + +```wit package root:component; world root { @@ -64,7 +111,7 @@ world root { ### Running a Component from Rust Applications To verify that our component works, lets run it from a Rust application that knows how to run a -component targeting the [`example` world](https://github.com/bytecodealliance/component-docs/tree/main/component-model/examples/example-host/add.wit). +component targeting the [`example:component/example` world](#example-component). The application uses [`wasmtime`](https://github.com/bytecodealliance/wasmtime) crates to generate Rust bindings, bring in WASI worlds, and execute the component. @@ -77,41 +124,30 @@ $ cargo run --release -- 1 2 ../add/target/wasm32-wasip1/release/add.wasm ## Exporting an interface with `cargo component` -The [sample `add.wit` file](https://github.com/bytecodealliance/component-docs/tree/main/component-model/examples/example-host/add.wit) exports a function. However, you'll often prefer to export an interface, either to comply with an existing specification or to capture a set of functions and types that tend to go together. For example, to implement the following world: +Notice how our `example` world currently exports `add` as a function. It's +often preferable to export an interface rather than a function, either to +comply with an existing specification or to capture several functions and types +at once. +For example, to implement the [`docs:adder/adder`][docs-adder] world: ```wit -package docs:adder@0.1.0; - -interface add { - add: func(a: u32, b: u32) -> u32; -} - -world adder { - export add; -} +{{#include ../../examples/tutorial/wit/adder/world.wit}} ``` you would write the following Rust code: ```rust -mod bindings; -// Separating out the interface puts it in a sub-module -use bindings::exports::docs::adder::add::Guest; - -struct Component; - -impl Guest for Component { - fn add(a: u32, b: u32) -> u32 { - a + b - } -} +{{#include ../../examples/tutorial/adder/src/lib.rs}} ``` ## Importing an interface with `cargo component` The world file (`wit/world.wit`) generated for you by `cargo component new --lib` doesn't specify any imports. -> `cargo component build`, by default, uses the Rust `wasm32-wasi` target, and therefore automatically imports any required WASI interfaces - no action is needed from you to import these. This section is about importing custom WIT interfaces from library components. +> [!NOTE] +> This section is about importing custom WIT interfaces from library components. +> By default, `cargo component build` imports any required [WASI interfaces](https://wasi.dev/interfaces) +> for us without needing to explicitly declare them. If your component consumes other components, you can edit the `world.wit` file to import their interfaces. @@ -139,10 +175,13 @@ Because the `docs:adder` package is in a different project, we must first tell ` ```toml [package.metadata.component.target.dependencies] -"docs:adder" = { path = "../adder/wit" } # directory containing the WIT package +"docs:adder" = { path = "../wit/adder" } # directory containing the WIT package ``` -Note that the path is to the adder project's WIT _directory_, not to the `world.wit` file. A WIT package may be spread across multiple files in the same directory; `cargo component` will look at all the files. +> [!NOTE] +> The path for `docs:adder` is relative to the `wit` _directory_, not to the `world.wit` file. +> +> A WIT package may be spread across multiple files in the same directory; `cargo component` will search them all. ### Calling the import from Rust @@ -534,3 +573,6 @@ If you are hosting a Wasm runtime, you can export a resource from your host for // etc. } ``` + +[example-component]: https://github.com/bytecodealliance/component-docs/tree/main/component-model/examples/example-host/add.wit +[docs-adder]: https://github.com/bytecodealliance/component-docs/tree/main/component-model/examples/tutorial/wit/adder/world.wit From d22b4304800d2f3a34f0c58cc9a3a4d6bd538d19 Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Tue, 18 Mar 2025 16:56:55 -0500 Subject: [PATCH 02/13] added comment to adder/lib.rs --- component-model/examples/tutorial/adder/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/component-model/examples/tutorial/adder/src/lib.rs b/component-model/examples/tutorial/adder/src/lib.rs index ecab073e..ace111e1 100644 --- a/component-model/examples/tutorial/adder/src/lib.rs +++ b/component-model/examples/tutorial/adder/src/lib.rs @@ -1,6 +1,7 @@ #[allow(warnings)] mod bindings; +// Separating out the interface puts it in a sub-module use bindings::exports::docs::adder::add::Guest; struct Component; From 262d47f405833527528b61d8228cc09d14e7f69e Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Mon, 24 Mar 2025 17:19:17 -0500 Subject: [PATCH 03/13] removed numbered headers --- component-model/src/language-support/rust.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/component-model/src/language-support/rust.md b/component-model/src/language-support/rust.md index 4e217fd0..0f978bc3 100644 --- a/component-model/src/language-support/rust.md +++ b/component-model/src/language-support/rust.md @@ -8,7 +8,7 @@ the component's implementation language. > [!NOTE] > You can find more details about `cargo-component` on [crates.io](https://crates.io/crates/cargo-component). -## 1. Setup +## Setup Install [`cargo-component`][cargo-component-install]: ```sh @@ -27,7 +27,7 @@ Clone the [component-docs](https://github.com/bytecodealliance/component-docs) r git clone https://github.com/bytecodealliance/component-docs ``` -## 2. Scaffolding a Component +## Scaffolding a Component We will create a component in Rust that implements the `add` function exported by the [`docs:adder/adder`][docs-adder] world in the From 661ac99e40667850d1bc5b2e85a54a913367982f Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Mon, 24 Mar 2025 17:19:41 -0500 Subject: [PATCH 04/13] typos --- component-model/examples/example-host/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/component-model/examples/example-host/README.md b/component-model/examples/example-host/README.md index 651d66ca..67e543ef 100644 --- a/component-model/examples/example-host/README.md +++ b/component-model/examples/example-host/README.md @@ -35,7 +35,7 @@ $ cargo run --release -- 1 2 add.wasm ``` > [!NOTE] -> `add.wasm` is available in thsi folder, but can be replaced with your own built WebAssembly component +> `add.wasm` is available in this folder, but can be replaced with your own built WebAssembly component > at any time (written in any language that supports WebAssembly Components), given that it satisfies > the `adder` world described above. From d23903ddc28ea9115eacb1b69e934a3f1245a459 Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Mon, 24 Mar 2025 17:23:12 -0500 Subject: [PATCH 05/13] update some other broken links --- component-model/src/language-support/rust.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/component-model/src/language-support/rust.md b/component-model/src/language-support/rust.md index 0f978bc3..a67e267a 100644 --- a/component-model/src/language-support/rust.md +++ b/component-model/src/language-support/rust.md @@ -286,8 +286,8 @@ As mentioned above, `cargo component build` doesn't generate a WIT file for a co ```toml [package.metadata.component.target.dependencies] - "docs:calculator" = { path = "../calculator/wit" } - "docs:adder" = { path = "../adder/wit" } + "docs:calculator" = { path = "../wit/calculator" } + "docs:adder" = { path = "../wit/adder" } ``` > If the external package refers to other packages, you need to provide the paths to them as well. From a2228c0ae60cf2659ec3803099ab4b1601f8a572 Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Mon, 24 Mar 2025 17:26:09 -0500 Subject: [PATCH 06/13] remove extra example-component ref --- component-model/src/language-support/rust.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/component-model/src/language-support/rust.md b/component-model/src/language-support/rust.md index a67e267a..e5b24285 100644 --- a/component-model/src/language-support/rust.md +++ b/component-model/src/language-support/rust.md @@ -146,7 +146,7 @@ import their interfaces. > [!NOTE] > This section is about importing custom WIT interfaces from library components. -> By default, `cargo component build` imports any required [WASI interfaces](https://wasi.dev/interfaces) +> By default, `cargo-component` imports any required [WASI interfaces](https://wasi.dev/interfaces) > for us without needing to explicitly declare them. @@ -577,5 +577,4 @@ If you are hosting a Wasm runtime, you can export a resource from your host for [cargo-component]: https://github.com/bytecodealliance/cargo-component [cargo-component-install]: https://github.com/bytecodealliance/cargo-component#install -[example-component]: https://github.com/bytecodealliance/component-docs/tree/main/component-model/examples/example-host/add.wit [docs-adder]: https://github.com/bytecodealliance/component-docs/tree/main/component-model/examples/tutorial/wit/adder/world.wit From 02e4760e4352a5dceed10b30c78afcd29b8ff739 Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Tue, 25 Mar 2025 13:24:34 -0500 Subject: [PATCH 07/13] updated with feedback on add interface --- component-model/src/language-support/rust.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/component-model/src/language-support/rust.md b/component-model/src/language-support/rust.md index e5b24285..a29a78da 100644 --- a/component-model/src/language-support/rust.md +++ b/component-model/src/language-support/rust.md @@ -126,8 +126,8 @@ $ cargo run --release -- 1 2 ../add/target/wasm32-wasip1/release/add.wasm ## Exporting an interface -Notice how our `example` world currently exports `add` as a function. It's -often preferable to export an interface rather than a function, either to +Notice how our `root` world in the `wasm-tools` output exports `add` as part of an _interface_. +It's often preferable to export an interface rather than a function, either to comply with an existing specification or to capture several functions and types at once. From 5bbe8e45ca466445f83f196dc99e1c28a0b9f875 Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Wed, 9 Apr 2025 18:11:55 -0500 Subject: [PATCH 08/13] PR feedback on adder commentary --- .../examples/tutorial/adder/src/bindings.rs | 27 +++++++++++-------- .../examples/tutorial/adder/src/lib.rs | 7 ++++- component-model/src/language-support/rust.md | 7 ++--- 3 files changed, 24 insertions(+), 17 deletions(-) diff --git a/component-model/examples/tutorial/adder/src/bindings.rs b/component-model/examples/tutorial/adder/src/bindings.rs index 245617df..52775cd2 100644 --- a/component-model/examples/tutorial/adder/src/bindings.rs +++ b/component-model/examples/tutorial/adder/src/bindings.rs @@ -1,4 +1,4 @@ -// Generated by `wit-bindgen` 0.36.0. DO NOT EDIT! +// Generated by `wit-bindgen` 0.41.0. DO NOT EDIT! // Options used: // * runtime_path: "wit_bindgen_rt" #[rustfmt::skip] @@ -6,7 +6,7 @@ pub mod exports { pub mod docs { pub mod adder { - #[allow(dead_code, clippy::all)] + #[allow(dead_code, async_fn_in_trait, unused_imports, clippy::all)] pub mod add { #[used] #[doc(hidden)] @@ -25,9 +25,10 @@ pub mod exports { #[doc(hidden)] macro_rules! __export_docs_adder_add_0_1_0_cabi { ($ty:ident with_types_in $($path_to_types:tt)*) => { - const _ : () = { #[export_name = "docs:adder/add@0.1.0#add"] - unsafe extern "C" fn export_add(arg0 : i32, arg1 : i32,) -> i32 { - $($path_to_types)*:: _export_add_cabi::<$ty > (arg0, arg1) } }; + const _ : () = { #[unsafe (export_name = + "docs:adder/add@0.1.0#add")] unsafe extern "C" fn export_add(arg0 + : i32, arg1 : i32,) -> i32 { unsafe { $($path_to_types)*:: + _export_add_cabi::<$ty > (arg0, arg1) } } }; }; } #[doc(hidden)] @@ -38,6 +39,7 @@ pub mod exports { } #[rustfmt::skip] mod _rt { + #![allow(dead_code, clippy::all)] #[cfg(target_arch = "wasm32")] pub fn run_ctors_once() { wit_bindgen_rt::run_ctors_once(); @@ -102,8 +104,8 @@ mod _rt { } } } -/// Generates `#[no_mangle]` functions to export the specified type as the -/// root implementation of all generated traits. +/// Generates `#[unsafe(no_mangle)]` functions to export the specified type as +/// the root implementation of all generated traits. /// /// For more information see the documentation of `wit_bindgen::generate!`. /// @@ -133,14 +135,17 @@ macro_rules! __export_adder_impl { #[doc(inline)] pub(crate) use __export_adder_impl as export; #[cfg(target_arch = "wasm32")] -#[link_section = "component-type:wit-bindgen:0.36.0:docs:adder@0.1.0:adder:encoded world"] +#[unsafe( + link_section = "component-type:wit-bindgen:0.41.0:docs:adder@0.1.0:adder:encoded world" +)] #[doc(hidden)] +#[allow(clippy::octal_escapes)] pub static __WIT_BINDGEN_COMPONENT_TYPE: [u8; 203] = *b"\ \0asm\x0d\0\x01\0\0\x19\x16wit-component-encoding\x04\0\x07P\x01A\x02\x01A\x02\x01\ -B\x02\x01@\x02\x01ay\x01by\0y\x04\0\x03add\x01\0\x04\0\x14docs:adder/add@0.1.0\x05\ +B\x02\x01@\x02\x01xy\x01yy\0y\x04\0\x03add\x01\0\x04\0\x14docs:adder/add@0.1.0\x05\ \0\x04\0\x16docs:adder/adder@0.1.0\x04\0\x0b\x0b\x01\0\x05adder\x03\0\0\0G\x09pr\ -oducers\x01\x0cprocessed-by\x02\x0dwit-component\x070.220.0\x10wit-bindgen-rust\x06\ -0.36.0"; +oducers\x01\x0cprocessed-by\x02\x0dwit-component\x070.227.1\x10wit-bindgen-rust\x06\ +0.41.0"; #[inline(never)] #[doc(hidden)] pub fn __link_custom_section_describing_imports() { diff --git a/component-model/examples/tutorial/adder/src/lib.rs b/component-model/examples/tutorial/adder/src/lib.rs index 35381695..ee6a2b52 100644 --- a/component-model/examples/tutorial/adder/src/lib.rs +++ b/component-model/examples/tutorial/adder/src/lib.rs @@ -1,8 +1,13 @@ #[allow(warnings)] mod bindings; -// Separating out the interface puts it in a sub-module +// The comments that follow the use declaration below correlate the rust module path with their +// `world.wit` counterparts: use bindings::exports::docs::adder::add::Guest; +// <- items bundled with `export` keyword +// <- package namespace +// <- package field +// <- interface name struct Component; diff --git a/component-model/src/language-support/rust.md b/component-model/src/language-support/rust.md index 81e4c5d5..12a96ede 100644 --- a/component-model/src/language-support/rust.md +++ b/component-model/src/language-support/rust.md @@ -89,10 +89,7 @@ Now, let's build our component, being sure to optimize with a release build: cargo component build --release ``` -You can use `wasm-tools` to inspect the WIT package generated by `cargo-component`: - - -You can use `wasm-tools component wit` to output the WIT package of the component: +You can use `wasm-tools` to output the WIT package of the component: ```console wasm-tools component wit target/wasm32-wasip1/release/add.wasm @@ -118,7 +115,7 @@ package docs:adder@0.1.0 { ### Running a Component To verify that our component works, lets run it from a Rust application that knows how to run a -component targeting the [`docs:adder/adder`](#adding-the-wit-world) world. +component targeting the [`adder` world](#adding-the-wit-world). The application uses [`wasmtime`](https://github.com/bytecodealliance/wasmtime) crates to generate Rust bindings, bring in WASI worlds, and execute the component. From 688bbbdcb185668e1e0f46b7f4e2a18502448bbf Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Thu, 10 Apr 2025 10:47:12 -0500 Subject: [PATCH 09/13] Update component-model/src/language-support/rust.md Co-authored-by: Victor Adossi <123968127+vados-cosmonic@users.noreply.github.com> --- component-model/src/language-support/rust.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/component-model/src/language-support/rust.md b/component-model/src/language-support/rust.md index 12a96ede..2f347d3d 100644 --- a/component-model/src/language-support/rust.md +++ b/component-model/src/language-support/rust.md @@ -110,7 +110,10 @@ package docs:adder@0.1.0 { } ``` -> **WARNING:** Building with `--release` removes all debug-related information from the resulting .wasm file. When prototyping or testing locally, you might want to avoid `--release` to obtain useful backtraces in case of errors (for example, with `wasmtime::WasmBacktraceDetails::Enable`). Note: the resulting .wasm file will be considerably larger (likely 4MB+). +> [!WARNING] +> Building with `--release` removes all debug-related information from the resulting .wasm file. +> +> When prototyping or testing locally, you might want to avoid `--release` to obtain useful backtraces in case of errors (for example, with `wasmtime::WasmBacktraceDetails::Enable`). Note: the resulting .wasm file will be considerably larger (likely 4MB+). ### Running a Component From e63b3d1287a2d38b4281a4575d05a2ef6a276375 Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Thu, 10 Apr 2025 14:32:08 -0500 Subject: [PATCH 10/13] PR feedback about console vs sh and warnings --- component-model/src/language-support/rust.md | 38 ++++++++++---------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/component-model/src/language-support/rust.md b/component-model/src/language-support/rust.md index 2f347d3d..58757e43 100644 --- a/component-model/src/language-support/rust.md +++ b/component-model/src/language-support/rust.md @@ -11,19 +11,19 @@ the component's implementation language. ## 1. Setup Install [`cargo-component`][cargo-component-install]: -```console +```sh cargo install --locked cargo-component ``` Install [`wasm-tools`](https://github.com/bytecodealliance/wasm-tools#installation): -```console +```sh cargo install --locked wasm-tools ``` Install [`wasmtime`](https://github.com/bytecodealliance/wasmtime#installation): -```console +```sh curl https://wasmtime.dev/install.sh -sSf | bash ``` Clone the [component-docs](https://github.com/bytecodealliance/component-docs) repo: -```console +```sh git clone https://github.com/bytecodealliance/component-docs ``` @@ -35,12 +35,12 @@ by the [`adder` world][docs-adder] world in the [package](https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md#package-names). First `cd` into the `tutorial` directory found in the repo we just cloned: -```console +```sh cd component-docs/component-model/examples/tutorial ``` Now create a new WebAssembly component package called `add`: -```console +```sh cargo component new add --lib && cd add ``` @@ -64,7 +64,7 @@ package = "docs:adder" Now that we've updated our `world.wit` and `Cargo.toml`, we can re-generate bindings with the command below: -```console +```sh cargo component bindings ``` @@ -85,13 +85,21 @@ code should look something like the following: Now, let's build our component, being sure to optimize with a release build: -```console +```sh cargo component build --release ``` +> [!WARNING] +> Building with `--release` removes all debug-related information from the resulting .wasm file. +> +> When prototyping or testing locally, you might want to avoid `--release` to +> obtain useful backtraces in case of errors (for example, with +> `wasmtime::WasmBacktraceDetails::Enable`). Note: the resulting .wasm file +> will be considerably larger (likely 4MB+). + You can use `wasm-tools` to output the WIT package of the component: -```console +```sh wasm-tools component wit target/wasm32-wasip1/release/add.wasm ``` @@ -110,10 +118,6 @@ package docs:adder@0.1.0 { } ``` -> [!WARNING] -> Building with `--release` removes all debug-related information from the resulting .wasm file. -> -> When prototyping or testing locally, you might want to avoid `--release` to obtain useful backtraces in case of errors (for example, with `wasmtime::WasmBacktraceDetails::Enable`). Note: the resulting .wasm file will be considerably larger (likely 4MB+). ### Running a Component @@ -123,7 +127,7 @@ component targeting the [`adder` world](#adding-the-wit-world). The application uses [`wasmtime`](https://github.com/bytecodealliance/wasmtime) crates to generate Rust bindings, bring in WASI worlds, and execute the component. -```sh +```console $ cd examples/example-host $ cargo run --release -- 1 2 ../add/target/wasm32-wasip1/release/adder.wasm 1 + 2 = 3 @@ -175,9 +179,7 @@ world calculator { ### Referencing the package to import -Because the `docs:adder` package is in a different project, we must first tell -`cargo component` how to find it. To do this, add the following to the -`Cargo.toml` file: +Because the `docs:adder` package is in a different project, we must first tell `cargo component` how to find it. To do this, add the following to the `Cargo.toml` file: ```toml [package.metadata.component.target.dependencies] @@ -313,7 +315,7 @@ As mentioned above, `cargo component build` doesn't generate a WIT file for a co 6. Run the composed component: - ```sh + ```console $ wasmtime run ./my-composed-command.wasm 1 + 1 = 579 # might need to go back and do some work on the calculator implementation ``` From 917d2b0b0ebf820b23351a929ca3043b27e4a6fb Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Fri, 11 Apr 2025 00:24:11 -0500 Subject: [PATCH 11/13] partial git revert --- .../examples/tutorial/adder/src/lib.rs | 3 ++- component-model/src/language-support/rust.md | 20 +++++-------------- 2 files changed, 7 insertions(+), 16 deletions(-) diff --git a/component-model/examples/tutorial/adder/src/lib.rs b/component-model/examples/tutorial/adder/src/lib.rs index ee6a2b52..75a36fac 100644 --- a/component-model/examples/tutorial/adder/src/lib.rs +++ b/component-model/examples/tutorial/adder/src/lib.rs @@ -1,7 +1,8 @@ #[allow(warnings)] mod bindings; -// The comments that follow the use declaration below correlate the rust module path with their +// The comments that follow the `use` declaration below +// correlate the rust module path segments with their // `world.wit` counterparts: use bindings::exports::docs::adder::add::Guest; // <- items bundled with `export` keyword diff --git a/component-model/src/language-support/rust.md b/component-model/src/language-support/rust.md index 58757e43..d0918fd2 100644 --- a/component-model/src/language-support/rust.md +++ b/component-model/src/language-support/rust.md @@ -22,24 +22,14 @@ Install [`wasmtime`](https://github.com/bytecodealliance/wasmtime#installation): ```sh curl https://wasmtime.dev/install.sh -sSf | bash ``` -Clone the [component-docs](https://github.com/bytecodealliance/component-docs) repo: -```sh -git clone https://github.com/bytecodealliance/component-docs -``` ## 2. Scaffolding a Component We will create a component in Rust that implements the `add` function exported -by the [`adder` world][docs-adder] world in the -`docs:adder` +by the [`adder` world][docs-adder] world in the `docs:adder` [package](https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md#package-names). -First `cd` into the `tutorial` directory found in the repo we just cloned: -```sh -cd component-docs/component-model/examples/tutorial -``` - -Now create a new WebAssembly component package called `add`: +First, we will create a new WebAssembly component package called `add`: ```sh cargo component new add --lib && cd add ``` @@ -183,7 +173,7 @@ Because the `docs:adder` package is in a different project, we must first tell ` ```toml [package.metadata.component.target.dependencies] -"docs:adder" = { path = "../wit/adder" } # directory containing the WIT package +"docs:adder" = { path = "../adder/wit" } # directory containing the WIT package ``` > [!NOTE] @@ -294,8 +284,8 @@ As mentioned above, `cargo component build` doesn't generate a WIT file for a co ```toml [package.metadata.component.target.dependencies] - "docs:calculator" = { path = "../wit/calculator" } - "docs:adder" = { path = "../wit/adder" } + "docs:calculator" = { path = "../calculator/wit" } + "docs:adder" = { path = "../adder/wit" } ``` > If the external package refers to other packages, you need to provide the paths to them as well. From ec05fac0909dd0027fd805cd2654ed4c018726ea Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Fri, 11 Apr 2025 00:48:10 -0500 Subject: [PATCH 12/13] remove merge artifact --- component-model/src/language-support/rust.md | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/component-model/src/language-support/rust.md b/component-model/src/language-support/rust.md index d0918fd2..12d0ffab 100644 --- a/component-model/src/language-support/rust.md +++ b/component-model/src/language-support/rust.md @@ -123,20 +123,6 @@ $ cargo run --release -- 1 2 ../add/target/wasm32-wasip1/release/adder.wasm 1 + 2 = 3 ``` -## Exporting an interface - -Notice how our `root` world in the `wasm-tools` output exports `add` as part of an _interface_. -It's often preferable to export an interface rather than a function, either to -comply with an existing specification or to capture several functions and types -at once. - -For example, to implement the [`adder` world](#adding-the-wit-world), you would -write the following Rust code: - -```rust -{{#include ../../examples/tutorial/adder/src/lib.rs}} -``` - ## Importing an interface The world file (`wit/world.wit`) we generated doesn't specify any imports. If From 9102bc949bb408d58907bc6f718828202abcb294 Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Fri, 11 Apr 2025 20:35:23 -0500 Subject: [PATCH 13/13] update note wording --- .../examples/tutorial/adder/src/lib.rs | 2 +- component-model/src/language-support/rust.md | 19 ++++++++----------- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/component-model/examples/tutorial/adder/src/lib.rs b/component-model/examples/tutorial/adder/src/lib.rs index 75a36fac..20f59a38 100644 --- a/component-model/examples/tutorial/adder/src/lib.rs +++ b/component-model/examples/tutorial/adder/src/lib.rs @@ -7,7 +7,7 @@ mod bindings; use bindings::exports::docs::adder::add::Guest; // <- items bundled with `export` keyword // <- package namespace -// <- package field +// <- package // <- interface name struct Component; diff --git a/component-model/src/language-support/rust.md b/component-model/src/language-support/rust.md index 12d0ffab..ceecc827 100644 --- a/component-model/src/language-support/rust.md +++ b/component-model/src/language-support/rust.md @@ -1,8 +1,7 @@ # Components in Rust -Rust has first-class support for the component model via the [`cargo-component` -tool][cargo-component]. We will be using -the `cargo component` subcommand to create WebAssembly components using Rust as +Rust has first-class support for the component model via the [`cargo-component` tool][cargo-component]. +We will be using the `cargo component` subcommand to create WebAssembly components using Rust as the component's implementation language. > [!NOTE] @@ -64,8 +63,7 @@ implement. ## 5. Implementing the `Guest` trait -Implement the `Guest` trait in `src/lib.rs`, using the scaffolded code. Your -code should look something like the following: +Implement the `Guest` trait in `src/lib.rs`, using the scaffolded code. Your code should look something like the following: ```rs {{#include ../../examples/tutorial/adder/src/lib.rs}} @@ -80,12 +78,12 @@ cargo component build --release ``` > [!WARNING] -> Building with `--release` removes all debug-related information from the resulting .wasm file. +> Building with `--release` removes all debug-related information from the resulting `.wasm` file. > > When prototyping or testing locally, you might want to avoid `--release` to > obtain useful backtraces in case of errors (for example, with -> `wasmtime::WasmBacktraceDetails::Enable`). Note: the resulting .wasm file -> will be considerably larger (likely 4MB+). +> [`wasmtime::WasmBacktraceDetails::Enable`](https://docs.rs/wasmtime/latest/wasmtime/enum.WasmBacktraceDetails.html#variant.Enable)). +> Note: the resulting `.wasm` file will be considerably larger (likely 4MB+). You can use `wasm-tools` to output the WIT package of the component: @@ -125,9 +123,8 @@ $ cargo run --release -- 1 2 ../add/target/wasm32-wasip1/release/adder.wasm ## Importing an interface -The world file (`wit/world.wit`) we generated doesn't specify any imports. If -your component consumes other components, you can edit the `world.wit` file to -import their interfaces. +The world file (`wit/world.wit`) we generated doesn't specify any imports. +If your component consumes other components, you can edit the `world.wit` file to import their interfaces. > [!NOTE] > This section is about importing custom WIT interfaces from library components.