From 7ea483eb98ac30550d4f03087f374abc7c5b0d38 Mon Sep 17 00:00:00 2001 From: Kate Goldenring Date: Thu, 24 Apr 2025 20:52:16 -0700 Subject: [PATCH] Update rust guide and tutorial examples to use registries for WITs Signed-off-by: Kate Goldenring --- .../tutorial/adder/Cargo-component.lock | 12 ++ .../examples/tutorial/adder/Cargo.toml | 18 ++- .../examples/tutorial/adder/src/bindings.rs | 16 +-- .../examples/tutorial/calculator/Cargo.toml | 21 ++- .../tutorial/calculator/src/bindings.rs | 125 ++++++++---------- component-model/src/language-support/rust.md | 25 ++-- 6 files changed, 117 insertions(+), 100 deletions(-) create mode 100644 component-model/examples/tutorial/adder/Cargo-component.lock diff --git a/component-model/examples/tutorial/adder/Cargo-component.lock b/component-model/examples/tutorial/adder/Cargo-component.lock new file mode 100644 index 0000000..ce555ee --- /dev/null +++ b/component-model/examples/tutorial/adder/Cargo-component.lock @@ -0,0 +1,12 @@ +# This file is automatically generated by cargo-component. +# It is not intended for manual editing. +version = 1 + +[[package]] +name = "docs:adder" +registry = "ghcr.io/bytecodealliance" + +[[package.version]] +requirement = "^0.1.0" +version = "0.1.0" +digest = "sha256:d4cb950366f8756821c401ec496ad43b35ffb0df3b2e757eb6aa3c1fa30d38c2" diff --git a/component-model/examples/tutorial/adder/Cargo.toml b/component-model/examples/tutorial/adder/Cargo.toml index 7578216..b4e028e 100644 --- a/component-model/examples/tutorial/adder/Cargo.toml +++ b/component-model/examples/tutorial/adder/Cargo.toml @@ -9,11 +9,17 @@ wit-bindgen-rt = { version = "0.37.0", features = ["bitflags"] } [lib] crate-type = ["cdylib"] -[package.metadata.component] +# Tell cargo-component where to find the package for the target world +# The following tells cargo-component to fetch the WIT from ghcr.io/bytecodealliance/docs/adder:0.1.0 +[package.metadata.component.target] +# The registry which contains the package +registry = "ghcr.io/bytecodealliance" +# The package name package = "docs:adder" +# The package version +version = "0.1.0" -[package.metadata.component.dependencies] - -[package.metadata.component.target] -path = "../wit/adder" -world = "adder" +# # To instead use a WIT on the local filesystem, uncomment the following lines +# [package.metadata.component.target] +# # Path to the directory containing the WIT +# path = "../wit/adder" \ No newline at end of file diff --git a/component-model/examples/tutorial/adder/src/bindings.rs b/component-model/examples/tutorial/adder/src/bindings.rs index 52775cd..28bd96b 100644 --- a/component-model/examples/tutorial/adder/src/bindings.rs +++ b/component-model/examples/tutorial/adder/src/bindings.rs @@ -122,7 +122,7 @@ mod _rt { /// ``` #[allow(unused_macros)] #[doc(hidden)] -macro_rules! __export_adder_impl { +macro_rules! __export_root_impl { ($ty:ident) => { self::export!($ty with_types_in self); }; @@ -133,19 +133,19 @@ macro_rules! __export_adder_impl { }; } #[doc(inline)] -pub(crate) use __export_adder_impl as export; +pub(crate) use __export_root_impl as export; #[cfg(target_arch = "wasm32")] #[unsafe( - link_section = "component-type:wit-bindgen:0.41.0:docs:adder@0.1.0:adder:encoded world" + link_section = "component-type:wit-bindgen:0.41.0:root:component:root: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\ +pub static __WIT_BINDGEN_COMPONENT_TYPE: [u8; 199] = *b"\ +\0asm\x0d\0\x01\0\0\x19\x16wit-component-encoding\x04\0\x07M\x01A\x02\x01A\x02\x01\ 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.227.1\x10wit-bindgen-rust\x06\ -0.41.0"; +\0\x04\0\x13root:component/root\x04\0\x0b\x0a\x01\0\x04root\x03\0\0\0G\x09produc\ +ers\x01\x0cprocessed-by\x02\x0dwit-component\x070.227.1\x10wit-bindgen-rust\x060\ +.41.0"; #[inline(never)] #[doc(hidden)] pub fn __link_custom_section_describing_imports() { diff --git a/component-model/examples/tutorial/calculator/Cargo.toml b/component-model/examples/tutorial/calculator/Cargo.toml index 6f6f717..5235794 100644 --- a/component-model/examples/tutorial/calculator/Cargo.toml +++ b/component-model/examples/tutorial/calculator/Cargo.toml @@ -9,14 +9,21 @@ wit-bindgen-rt = { version = "0.24.0", features = ["bitflags"] } [lib] crate-type = ["cdylib"] -[package.metadata.component] -package = "docs:calculator" - -[package.metadata.component.target.dependencies] -"docs:adder" = { path = "../wit/adder" } # directory containing the WIT package - +# Tell cargo-component where to find the package for the target world +# The following tells cargo-component to fetch the WIT from a local directory [package.metadata.component.target] +# Path to the directory containing the WIT path = "../wit/calculator" +# World within the package to target world = "calculator" -[package.metadata.component.dependencies] +[package.metadata.component.target.dependencies] +# Tell cargo-component where to find the package for the dependencies +"docs:adder" = { path = "../wit/adder" } + +## To instead fetch the package and it's dependencies from a registry, uncomment the following lines +# [package.metadata.component.target] +# package = "docs:calculator" +# version = "0.1.0" +# registry = "ghcr.io/bytecodealliance" +# world = "calculator" \ No newline at end of file diff --git a/component-model/examples/tutorial/calculator/src/bindings.rs b/component-model/examples/tutorial/calculator/src/bindings.rs index 8511915..ec0a2ec 100644 --- a/component-model/examples/tutorial/calculator/src/bindings.rs +++ b/component-model/examples/tutorial/calculator/src/bindings.rs @@ -1,80 +1,74 @@ -// Generated by `wit-bindgen` 0.25.0. DO NOT EDIT! +// Generated by `wit-bindgen` 0.41.0. DO NOT EDIT! // Options used: -#[allow(dead_code)] +// * runtime_path: "wit_bindgen_rt" +#[rustfmt::skip] +#[allow(dead_code, clippy::all)] pub mod docs { - #[allow(dead_code)] 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)] - #[cfg(target_arch = "wasm32")] - static __FORCE_SECTION_REF: fn() = - super::super::super::__link_custom_section_describing_imports; + static __FORCE_SECTION_REF: fn() = super::super::super::__link_custom_section_describing_imports; use super::super::super::_rt; #[allow(unused_unsafe, clippy::all)] pub fn add(x: u32, y: u32) -> u32 { unsafe { #[cfg(target_arch = "wasm32")] #[link(wasm_import_module = "docs:adder/add@0.1.0")] - extern "C" { + unsafe extern "C" { #[link_name = "add"] - fn wit_import(_: i32, _: i32) -> i32; + fn wit_import0(_: i32, _: i32) -> i32; } - #[cfg(not(target_arch = "wasm32"))] - fn wit_import(_: i32, _: i32) -> i32 { + unsafe extern "C" fn wit_import0(_: i32, _: i32) -> i32 { unreachable!() } - let ret = wit_import(_rt::as_i32(&a), _rt::as_i32(&b)); + let ret = unsafe { wit_import0(_rt::as_i32(&x), _rt::as_i32(&y)) }; ret as u32 } } } } } -#[allow(dead_code)] +#[rustfmt::skip] +#[allow(dead_code, clippy::all)] pub mod exports { - #[allow(dead_code)] pub mod docs { - #[allow(dead_code)] pub mod calculator { - #[allow(dead_code, clippy::all)] + #[allow(dead_code, async_fn_in_trait, unused_imports, clippy::all)] pub mod calculate { #[used] #[doc(hidden)] - #[cfg(target_arch = "wasm32")] - static __FORCE_SECTION_REF: fn() = - super::super::super::super::__link_custom_section_describing_imports; + static __FORCE_SECTION_REF: fn() = super::super::super::super::__link_custom_section_describing_imports; use super::super::super::super::_rt; #[repr(u8)] - #[derive(Clone, Copy, Eq, PartialEq)] + #[derive(Clone, Copy, Eq, Ord, PartialEq, PartialOrd)] pub enum Op { Add, } impl ::core::fmt::Debug for Op { - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::fmt::Result { match self { Op::Add => f.debug_tuple("Op::Add").finish(), } } } - impl Op { #[doc(hidden)] pub unsafe fn _lift(val: u8) -> Op { if !cfg!(debug_assertions) { return ::core::mem::transmute(val); } - match val { 0 => Op::Add, - _ => panic!("invalid enum discriminant"), } } } - #[doc(hidden)] #[allow(non_snake_case)] pub unsafe fn _export_eval_expression_cabi( @@ -82,112 +76,102 @@ pub mod exports { arg1: i32, arg2: i32, ) -> i32 { - #[cfg(target_arch = "wasm32")] - _rt::run_ctors_once(); - let result0 = - T::eval_expression(Op::_lift(arg0 as u8), arg1 as u32, arg2 as u32); + #[cfg(target_arch = "wasm32")] _rt::run_ctors_once(); + let result0 = T::eval_expression( + Op::_lift(arg0 as u8), + arg1 as u32, + arg2 as u32, + ); _rt::as_i32(result0) } pub trait Guest { fn eval_expression(op: Op, x: u32, y: u32) -> u32; } #[doc(hidden)] - - macro_rules! __export_docs_calculator_calculate_0_1_0_cabi{ - ($ty:ident with_types_in $($path_to_types:tt)*) => (const _: () = { - - #[export_name = "docs:calculator/calculate@0.1.0#eval-expression"] - unsafe extern "C" fn export_eval_expression(arg0: i32,arg1: i32,arg2: i32,) -> i32 { - $($path_to_types)*::_export_eval_expression_cabi::<$ty>(arg0, arg1, arg2) - } - };); - } + macro_rules! __export_docs_calculator_calculate_0_1_0_cabi { + ($ty:ident with_types_in $($path_to_types:tt)*) => { + const _ : () = { #[unsafe (export_name = + "docs:calculator/calculate@0.1.0#eval-expression")] unsafe extern + "C" fn export_eval_expression(arg0 : i32, arg1 : i32, arg2 : + i32,) -> i32 { unsafe { $($path_to_types)*:: + _export_eval_expression_cabi::<$ty > (arg0, arg1, arg2) } } }; + }; + } #[doc(hidden)] pub(crate) use __export_docs_calculator_calculate_0_1_0_cabi; } } } } +#[rustfmt::skip] mod _rt { - + #![allow(dead_code, clippy::all)] pub fn as_i32(t: T) -> i32 { t.as_i32() } - pub trait AsI32 { fn as_i32(self) -> i32; } - impl<'a, T: Copy + AsI32> AsI32 for &'a T { fn as_i32(self) -> i32 { (*self).as_i32() } } - impl AsI32 for i32 { #[inline] fn as_i32(self) -> i32 { self as i32 } } - impl AsI32 for u32 { #[inline] fn as_i32(self) -> i32 { self as i32 } } - impl AsI32 for i16 { #[inline] fn as_i32(self) -> i32 { self as i32 } } - impl AsI32 for u16 { #[inline] fn as_i32(self) -> i32 { self as i32 } } - impl AsI32 for i8 { #[inline] fn as_i32(self) -> i32 { self as i32 } } - impl AsI32 for u8 { #[inline] fn as_i32(self) -> i32 { self as i32 } } - impl AsI32 for char { #[inline] fn as_i32(self) -> i32 { self as i32 } } - impl AsI32 for usize { #[inline] fn as_i32(self) -> i32 { self as i32 } } - #[cfg(target_arch = "wasm32")] pub fn run_ctors_once() { wit_bindgen_rt::run_ctors_once(); } } - -/// 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!`. /// @@ -204,31 +188,34 @@ mod _rt { /// ``` #[allow(unused_macros)] #[doc(hidden)] - macro_rules! __export_calculator_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::calculate::__export_docs_calculator_calculate_0_1_0_cabi!($ty with_types_in $($path_to_types_root)*::exports::docs::calculator::calculate); - ) + ($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::calculate::__export_docs_calculator_calculate_0_1_0_cabi!($ty + with_types_in $($path_to_types_root)*:: exports::docs::calculator::calculate); + }; } #[doc(inline)] pub(crate) use __export_calculator_impl as export; - #[cfg(target_arch = "wasm32")] -#[link_section = "component-type:wit-bindgen:0.25.0:calculator:encoded world"] +#[unsafe( + link_section = "component-type:wit-bindgen:0.41.0:docs:calculator@0.1.0:calculator:encoded world" +)] #[doc(hidden)] +#[allow(clippy::octal_escapes)] 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\ -.208.1\x10wit-bindgen-rust\x060.25.0"; - +A\x04\x01B\x02\x01@\x02\x01xy\x01yy\0y\x04\0\x03add\x01\0\x03\0\x14docs:adder/ad\ +d@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\0\x1fdocs:calculator/calculate@\ +0.1.0\x05\x01\x04\0\x20docs:calculator/calculator@0.1.0\x04\0\x0b\x10\x01\0\x0ac\ +alculator\x03\0\0\0G\x09producers\x01\x0cprocessed-by\x02\x0dwit-component\x070.\ +227.1\x10wit-bindgen-rust\x060.41.0"; #[inline(never)] #[doc(hidden)] -#[cfg(target_arch = "wasm32")] pub fn __link_custom_section_describing_imports() { wit_bindgen_rt::maybe_link_cabi_realloc(); } diff --git a/component-model/src/language-support/rust.md b/component-model/src/language-support/rust.md index ceecc82..af7d240 100644 --- a/component-model/src/language-support/rust.md +++ b/component-model/src/language-support/rust.md @@ -35,19 +35,25 @@ cargo component new add --lib && cd add ## 3. Adding the WIT world -We now need to change our generated `wit/world.wit` to match `docs:adder`: -```wit -{{#include ../../examples/tutorial/wit/adder/world.wit}} -``` - -The `package.metadata.component` section of our `Cargo.toml` should be changed -to the following: +Now, that we have a template generated for our app, we can use `cargo-component`'s registries support to fetch the `docs:adder` package and generate bindings for our component. Modify the `package` section of our `Cargo.toml` to only contain the following target definition: ```toml -[package.metadata.component] +[package.metadata.component.target] package = "docs:adder" +version = "0.1.0" +registry = "ghcr.io/bytecodealliance" ``` +This tells `cargo-component` to fetch the world from `ghcr.io/bytecodealliance/docs/adder:0.1.0`. + +> [!NOTE] +> Instead of using registries, you can also point to a package in your local file system. For example, if your package is at `/path/to/wit/directory/adder.wit`, you could specify this in your `Cargo.toml` as follows: +> ```toml +> [package.metadata.component.target] +> # Path to the directory containing the WIT +> path = "/path/to/wit/directory" +> ``` + ## 4. Generating bindings Now that we've updated our `world.wit` and `Cargo.toml`, we can re-generate @@ -106,11 +112,10 @@ 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 [`adder` world](#adding-the-wit-world). +component targeting the [`adder` world](#3-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.