diff --git a/component-model/examples/tutorial/README.md b/component-model/examples/tutorial/README.md index c5c1d1b..3beb5eb 100644 --- a/component-model/examples/tutorial/README.md +++ b/component-model/examples/tutorial/README.md @@ -5,15 +5,9 @@ The WIT package for the calculator consists of a world for each mathematical ope add an `op` enum that delineates each operator. The following example interface only has an `add` operation: -```wit -package docs:calculator@0.1.0; +```wit adder +package docs:adder@0.1.0; -interface calculate { - enum op { - add, - } - eval-expression: func(op: op, x: u32, y: u32) -> u32; -} interface add { add: func(a: u32, b: u32) -> u32; @@ -22,13 +16,30 @@ interface add { world adder { export add; } +``` + + +```wit calculator +package docs:calculator@0.1.0; + +interface calculate { + enum op { + add, + } + eval-expression: func(op: op, x: u32, y: u32) -> u32; +} world calculator { export calculate; - import add; + import docs:adder/add; +} + +world app { + import calculate; } ``` + To expand the exercise to add more components, add another operator world, expand the enum, and modify the `command` component to call it. ## Building and running the example @@ -39,13 +50,14 @@ To compose a calculator component with an add operator, run the following: (cd calculator && cargo component build --release) (cd adder && cargo component build --release) (cd command && cargo component build --release) +cd .. wasm-tools compose calculator/target/wasm32-wasi/release/calculator.wasm -d adder/target/wasm32-wasi/release/adder.wasm -o composed.wasm -wasm-tools compose command/target/wasm32-wasi/release/command.wasm -d composed.wasm -o command.wasm +wasm-tools compose command/target/wasm32-wasi/release/command.wasm -d composed.wasm -o final.wasm ``` Now, run the component with wasmtime: ```sh -wasmtime run command.wasm 1 2 add +wasmtime run final.wasm 1 2 add 1 + 2 = 3 ``` diff --git a/component-model/examples/tutorial/adder/Cargo.lock b/component-model/examples/tutorial/adder/Cargo.lock index 2b32d89..90e9875 100644 --- a/component-model/examples/tutorial/adder/Cargo.lock +++ b/component-model/examples/tutorial/adder/Cargo.lock @@ -6,15 +6,14 @@ version = 3 name = "adder" version = "0.1.0" dependencies = [ - "bitflags", "wit-bindgen-rt", ] [[package]] name = "bitflags" -version = "2.4.2" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" +checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" [[package]] name = "wit-bindgen-rt" diff --git a/component-model/examples/tutorial/adder/Cargo.toml b/component-model/examples/tutorial/adder/Cargo.toml index a6dfd29..d710b68 100644 --- a/component-model/examples/tutorial/adder/Cargo.toml +++ b/component-model/examples/tutorial/adder/Cargo.toml @@ -4,17 +4,16 @@ version = "0.1.0" edition = "2021" [dependencies] -bitflags = "2.4.2" wit-bindgen-rt = { version = "0.24.0", features = ["bitflags"] } [lib] crate-type = ["cdylib"] [package.metadata.component] -package = "docs:calculator" +package = "docs:adder" + +[package.metadata.component.dependencies] [package.metadata.component.target] -path = "../wit/calculator.wit" +path = "../wit/adder" world = "adder" - -[package.metadata.component.dependencies] diff --git a/component-model/examples/tutorial/adder/src/bindings.rs b/component-model/examples/tutorial/adder/src/bindings.rs index d991f90..762a1ff 100644 --- a/component-model/examples/tutorial/adder/src/bindings.rs +++ b/component-model/examples/tutorial/adder/src/bindings.rs @@ -5,7 +5,7 @@ pub mod exports { #[allow(dead_code)] pub mod docs { #[allow(dead_code)] - pub mod calculator { + pub mod adder { #[allow(dead_code, clippy::all)] pub mod add { #[used] @@ -27,17 +27,17 @@ pub mod exports { } #[doc(hidden)] - macro_rules! __export_docs_calculator_add_0_1_0_cabi{ + macro_rules! __export_docs_adder_add_0_1_0_cabi{ ($ty:ident with_types_in $($path_to_types:tt)*) => (const _: () = { - #[export_name = "docs:calculator/add@0.1.0#add"] + #[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) } };); } #[doc(hidden)] - pub(crate) use __export_docs_calculator_add_0_1_0_cabi; + pub(crate) use __export_docs_adder_add_0_1_0_cabi; } } } @@ -142,7 +142,7 @@ mod _rt { macro_rules! __export_adder_impl { ($ty:ident) => (self::export!($ty with_types_in self);); ($ty:ident with_types_in $($path_to_types_root:tt)*) => ( - $($path_to_types_root)*::exports::docs::calculator::add::__export_docs_calculator_add_0_1_0_cabi!($ty with_types_in $($path_to_types_root)*::exports::docs::calculator::add); + $($path_to_types_root)*::exports::docs::adder::add::__export_docs_adder_add_0_1_0_cabi!($ty with_types_in $($path_to_types_root)*::exports::docs::adder::add); ) } #[doc(inline)] @@ -151,12 +151,12 @@ pub(crate) use __export_adder_impl as export; #[cfg(target_arch = "wasm32")] #[link_section = "component-type:wit-bindgen:0.24.0:adder:encoded world"] #[doc(hidden)] -pub static __WIT_BINDGEN_COMPONENT_TYPE: [u8; 213] = *b"\ -\0asm\x0d\0\x01\0\0\x19\x16wit-component-encoding\x04\0\x07Z\x01A\x02\x01A\x02\x01\ -B\x02\x01@\x02\x01ay\x01by\0y\x04\0\x03add\x01\0\x04\x01\x19docs:calculator/add@\ -0.1.0\x05\0\x04\x01\x1bdocs:calculator/adder@0.1.0\x04\0\x0b\x0b\x01\0\x05adder\x03\ -\0\0\0G\x09producers\x01\x0cprocessed-by\x02\x0dwit-component\x070.202.0\x10wit-\ -bindgen-rust\x060.24.0"; +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\x01\x14docs:adder/add@0.1.0\ +\x05\0\x04\x01\x16docs:adder/adder@0.1.0\x04\0\x0b\x0b\x01\0\x05adder\x03\0\0\0G\ +\x09producers\x01\x0cprocessed-by\x02\x0dwit-component\x070.202.0\x10wit-bindgen\ +-rust\x060.24.0"; #[inline(never)] #[doc(hidden)] diff --git a/component-model/examples/tutorial/adder/src/lib.rs b/component-model/examples/tutorial/adder/src/lib.rs index 0afc22d..ecab073 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; -use crate::bindings::exports::docs::calculator::add::Guest; +use bindings::exports::docs::adder::add::Guest; struct Component; diff --git a/component-model/examples/tutorial/calculator/Cargo.lock b/component-model/examples/tutorial/calculator/Cargo.lock index 3b6c9fd..143b7b4 100644 --- a/component-model/examples/tutorial/calculator/Cargo.lock +++ b/component-model/examples/tutorial/calculator/Cargo.lock @@ -12,7 +12,6 @@ checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" name = "calculator" version = "0.1.0" dependencies = [ - "bitflags", "wit-bindgen-rt", ] diff --git a/component-model/examples/tutorial/calculator/Cargo.toml b/component-model/examples/tutorial/calculator/Cargo.toml index 762844f..6f6f717 100644 --- a/component-model/examples/tutorial/calculator/Cargo.toml +++ b/component-model/examples/tutorial/calculator/Cargo.toml @@ -4,7 +4,6 @@ version = "0.1.0" edition = "2021" [dependencies] -bitflags = "2.4.2" wit-bindgen-rt = { version = "0.24.0", features = ["bitflags"] } [lib] @@ -13,8 +12,11 @@ crate-type = ["cdylib"] [package.metadata.component] package = "docs:calculator" +[package.metadata.component.target.dependencies] +"docs:adder" = { path = "../wit/adder" } # directory containing the WIT package + [package.metadata.component.target] -path = "../wit/calculator.wit" +path = "../wit/calculator" world = "calculator" [package.metadata.component.dependencies] diff --git a/component-model/examples/tutorial/calculator/src/bindings.rs b/component-model/examples/tutorial/calculator/src/bindings.rs index 94b1483..ee0f517 100644 --- a/component-model/examples/tutorial/calculator/src/bindings.rs +++ b/component-model/examples/tutorial/calculator/src/bindings.rs @@ -3,7 +3,7 @@ #[allow(dead_code)] pub mod docs { #[allow(dead_code)] - pub mod calculator { + pub mod adder { #[allow(dead_code, clippy::all)] pub mod add { #[used] @@ -16,7 +16,7 @@ pub mod docs { pub fn add(a: u32, b: u32) -> u32 { unsafe { #[cfg(target_arch = "wasm32")] - #[link(wasm_import_module = "docs:calculator/add@0.1.0")] + #[link(wasm_import_module = "docs:adder/add@0.1.0")] extern "C" { #[link_name = "add"] fn wit_import(_: i32, _: i32) -> i32; @@ -216,14 +216,14 @@ pub(crate) use __export_calculator_impl as export; #[cfg(target_arch = "wasm32")] #[link_section = "component-type:wit-bindgen:0.24.0:calculator:encoded world"] #[doc(hidden)] -pub static __WIT_BINDGEN_COMPONENT_TYPE: [u8; 313] = *b"\ -\0asm\x0d\0\x01\0\0\x19\x16wit-component-encoding\x04\0\x07\xb8\x01\x01A\x02\x01\ -A\x04\x01B\x02\x01@\x02\x01ay\x01by\0y\x04\0\x03add\x01\0\x03\x01\x19docs:calcul\ -ator/add@0.1.0\x05\0\x01B\x04\x01m\x01\x03add\x04\0\x02op\x03\0\0\x01@\x03\x02op\ -\x01\x01xy\x01yy\0y\x04\0\x0feval-expression\x01\x02\x04\x01\x1fdocs:calculator/\ -calculate@0.1.0\x05\x01\x04\x01\x20docs:calculator/calculator@0.1.0\x04\0\x0b\x10\ -\x01\0\x0acalculator\x03\0\0\0G\x09producers\x01\x0cprocessed-by\x02\x0dwit-comp\ -onent\x070.202.0\x10wit-bindgen-rust\x060.24.0"; +pub static __WIT_BINDGEN_COMPONENT_TYPE: [u8; 308] = *b"\ +\0asm\x0d\0\x01\0\0\x19\x16wit-component-encoding\x04\0\x07\xb3\x01\x01A\x02\x01\ +A\x04\x01B\x02\x01@\x02\x01ay\x01by\0y\x04\0\x03add\x01\0\x03\x01\x14docs:adder/\ +add@0.1.0\x05\0\x01B\x04\x01m\x01\x03add\x04\0\x02op\x03\0\0\x01@\x03\x02op\x01\x01\ +xy\x01yy\0y\x04\0\x0feval-expression\x01\x02\x04\x01\x1fdocs:calculator/calculat\ +e@0.1.0\x05\x01\x04\x01\x20docs:calculator/calculator@0.1.0\x04\0\x0b\x10\x01\0\x0a\ +calculator\x03\0\0\0G\x09producers\x01\x0cprocessed-by\x02\x0dwit-component\x070\ +.202.0\x10wit-bindgen-rust\x060.24.0"; #[inline(never)] #[doc(hidden)] diff --git a/component-model/examples/tutorial/calculator/src/lib.rs b/component-model/examples/tutorial/calculator/src/lib.rs index 5eb86f1..9ea0247 100644 --- a/component-model/examples/tutorial/calculator/src/lib.rs +++ b/component-model/examples/tutorial/calculator/src/lib.rs @@ -1,9 +1,10 @@ +#[allow(warnings)] mod bindings; use bindings::exports::docs::calculator::calculate::{Guest, Op}; // Bring the imported add function into scope -use bindings::docs::calculator::add::add; +use bindings::docs::adder::add::add; struct Component; diff --git a/component-model/examples/tutorial/command/Cargo.lock b/component-model/examples/tutorial/command/Cargo.lock index 5e091db..a5dffcc 100644 --- a/component-model/examples/tutorial/command/Cargo.lock +++ b/component-model/examples/tutorial/command/Cargo.lock @@ -58,9 +58,9 @@ checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" [[package]] name = "bitflags" -version = "2.4.2" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" +checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" [[package]] name = "clap" @@ -113,7 +113,6 @@ name = "command" version = "0.1.0" dependencies = [ "anyhow", - "bitflags", "clap", "wit-bindgen-rt", ] @@ -135,9 +134,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.35" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] @@ -161,9 +160,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" [[package]] name = "utf8parse" @@ -233,9 +232,9 @@ checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" [[package]] name = "windows_x86_64_msvc" -version = "0.52.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" [[package]] name = "wit-bindgen-rt" diff --git a/component-model/examples/tutorial/command/Cargo.toml b/component-model/examples/tutorial/command/Cargo.toml index c395a7e..98ef459 100644 --- a/component-model/examples/tutorial/command/Cargo.toml +++ b/component-model/examples/tutorial/command/Cargo.toml @@ -3,15 +3,14 @@ name = "command" version = "0.1.0" edition = "2021" -[package.metadata.component] -package = "docs:calculator" +[dependencies] +anyhow = "1" +wit-bindgen-rt = { version = "0.24.0", features = ["bitflags"] } +clap = { version = "4.3.19", features = ["derive"] } [package.metadata.component.target] -path = "../wit/calculator.wit" +path = "../wit/calculator" world = "app" -[dependencies] -anyhow = "1" -clap = { version = "4.3.19", features = ["derive"] } -bitflags = "2.4.2" -wit-bindgen-rt = { version = "0.24.0", features = ["bitflags"] } +[package.metadata.component.target.dependencies] +"docs:adder" = { path = "../wit/adder" } diff --git a/component-model/examples/tutorial/wit/adder/world.wit b/component-model/examples/tutorial/wit/adder/world.wit new file mode 100644 index 0000000..328f7f4 --- /dev/null +++ b/component-model/examples/tutorial/wit/adder/world.wit @@ -0,0 +1,9 @@ +package docs:adder@0.1.0; + +interface add { + add: func(a: u32, b: u32) -> u32; +} + +world adder { + export add; +} \ No newline at end of file diff --git a/component-model/examples/tutorial/wit/calculator.wit b/component-model/examples/tutorial/wit/calculator/world.wit similarity index 68% rename from component-model/examples/tutorial/wit/calculator.wit rename to component-model/examples/tutorial/wit/calculator/world.wit index ebfd234..c775b84 100644 --- a/component-model/examples/tutorial/wit/calculator.wit +++ b/component-model/examples/tutorial/wit/calculator/world.wit @@ -7,17 +7,9 @@ interface calculate { eval-expression: func(op: op, x: u32, y: u32) -> u32; } -interface add { - add: func(a: u32, b: u32) -> u32; -} - -world adder { - export add; -} - world calculator { export calculate; - import add; + import docs:adder/add@0.1.0; } world app { diff --git a/component-model/src/tutorial.md b/component-model/src/tutorial.md index 819c765..68dc04b 100644 --- a/component-model/src/tutorial.md +++ b/component-model/src/tutorial.md @@ -15,26 +15,41 @@ Wasm components, we will compose them into a single runnable component, and test ## The calculator interface -For tutorial purposes, we are going to define all our interfaces in one WIT package (in fact, one -`.wit` file). This file defines: +For tutorial purposes, we are going to put our "calculator engine" and "addition operation" interfaces into two separate WIT packages, each containing one WIT file. This may seem excessive, but the reason is to illustrate real-world use cases where components come from different authors and packages. +These files can be found in the component book repository in the [`wit` directory](https://github.com/bytecodealliance/component-docs/tree/main/component-model/examples/tutorial/wit) under `wit/adder/world.wit` and `wit/calculator/world.wit`. These files define: + +* A world describing an world that exports the "add" interface. Again, components such as the calculator can call it when + they need to add numbers. + +```wit +// wit/adder/world.wit +package docs:adder@0.1.0; + +interface add { + add: func(a: u32, b: u32) -> u32; +} + +world adder { + export add; +} +``` * An interface for the calculator itself. We'll use this later to carry out calculations. It contains an evaluate function, and an enum that delineates the operations that can be involved in a calculation. In this tutorial, the only operation is `add`. * Interfaces for the various operations the calculator might need to carry out as part of a - calculation. For the tutorial, again, the only interface we define is for the "add" operation. + calculation. For the tutorial, again, the only import we define is for the "add" operation from + the "docs:adder" world defined previously. * A world describing the calculator component. This world exports the calculator interface, meaning that other components can call it to perform calculations. It imports the operation interfaces (such as "add"), meaning it relies on other components to perform those operations. -* A world describing each operator component. Again, there's just the "adder" world right now, and - this exports the "add" interface, meaning that components such as the calculator can call it when - they need to add numbers. * A world describing the "primary" app component, which imports the "calculate" interface. This is the component will take in command line arguments and pass them to the "eval-expression" function of the calculator component. + ```wit -// calculator.wit +// wit/calculator/world.wit package docs:calculator@0.1.0; interface calculate { @@ -44,17 +59,9 @@ interface calculate { eval-expression: func(op: op, x: u32, y: u32) -> u32; } -interface add { - add: func(a: u32, b: u32) -> u32; -} - -world adder { - export add; -} - world calculator { export calculate; - import add; + import docs:adder/add@0.1.0; } world app { @@ -67,14 +74,14 @@ world app { Reference the [language guide](language-support.md) and [authoring components documentation](creating-and-consuming/authoring.md) to create a component that implements the -`adder` world of `calculator.wit`. For reference, see the completed +`adder` world of `adder/wit/world.wit`. For reference, see the completed [example](https://github.com/bytecodealliance/component-docs/tree/main/component-model/examples/tutorial/adder/). ## Create a `calculator` component Reference the [language guide](language-support.md) and [authoring components documentation](creating-and-consuming/authoring.md) to create a component that implements the -`calculator` world of `calculator.wit`. For reference, see the completed +`calculator` world of `wit/calculator/world.wit`. For reference, see the completed [example](https://github.com/bytecodealliance/component-docs/tree/main/component-model/examples/tutorial/calculator/). The component should import the `add` function from the `adder` world and call it if the `op` enum matches `add`. @@ -93,14 +100,19 @@ cargo component new command --command This component will implement the [`app`](https://github.com/bytecodealliance/component-docs/tree/main/component-model/examples/tutorial/wit/calculator.wit) world, which imports the `calculate` interface. In `Cargo.toml`, point `cargo-component` to the WIT file and -specify that it should pull in bindings for the `app` world: +specify that it should pull in bindings for the `app` world from the path to `calculator.wit`: ```toml [package.metadata.component.target] -path = "../path/to/calculator.wit" +path = "../wit/calculator/world.wit" world = "app" ``` +Since the calculator world imports the `add` interface, the command component needs to pull in the `adder` WIT as a dependency, as well. +```toml +[package.metadata.component.target.dependencies] +"docs:adder" = { path = "../wit/adder" } +``` Now, implement a command line application that: 1. takes in three arguments: two operands and the name of an operator ("1 2 add")