diff --git a/component-model/examples/tutorial/wat/adder/add.wat b/component-model/examples/tutorial/wat/adder/add.wat new file mode 100644 index 00000000..c442d71e --- /dev/null +++ b/component-model/examples/tutorial/wat/adder/add.wat @@ -0,0 +1,7 @@ +(module + (func $add (param $lhs i32) (param $rhs i32) (result i32) + local.get $lhs + local.get $rhs + i32.add) + (export "docs:adder/add@0.1.0#add" (func $add)) +) diff --git a/component-model/src/SUMMARY.md b/component-model/src/SUMMARY.md index bdad6f04..0bb86d31 100644 --- a/component-model/src/SUMMARY.md +++ b/component-model/src/SUMMARY.md @@ -15,13 +15,14 @@ # Using WebAssembly Components -- [Language Support for Components](./language-support.md) +- [Creating Components](./language-support.md) - [C/C++](./language-support/c.md) - [C#](./language-support/csharp.md) - [Go](./language-support/go.md) - [JavaScript](./language-support/javascript.md) - [Python](./language-support/python.md) - [Rust](./language-support/rust.md) + - [WebAssembly Text Format (WAT)](./language-support/wat.md) - [Running Components](./running-components.md) - [Wasmtime](./running-components/wasmtime.md) - [jco](./running-components/jco.md) diff --git a/component-model/src/language-support.md b/component-model/src/language-support.md index b1bc1084..beaf58c9 100644 --- a/component-model/src/language-support.md +++ b/component-model/src/language-support.md @@ -1,9 +1,9 @@ -# Wasm Language Support +# Creating components -WebAssembly can be targeted by the majority of top programming -languages; however, the level of -support varies. This document details the subset of languages that target WASI and support -components. +Many popular programming languages can be compiled to WebAssembly, +but the level of support varies across languages. +This document details languages with compilers and runtimes +that support WebAssembly with WASI as a target platform. > This is a living document, so if you are aware of advancements in a toolchain, please do not hesitate to [contribute documentation](https://github.com/bytecodealliance/component-docs/blob/main/CONTRIBUTING.md). You can find more information about the development of support for specific languages in the [Guest Languages Special Interest Group Proposal](https://github.com/bytecodealliance/governance/blob/main/SIGs/SIG-guest-languages/proposal.md) document. @@ -18,12 +18,11 @@ example host or from an application of that toolchain. This aims to provide a fu components within and among toolchains. Each section covers how to build and -run components for a given toolchain: +run components for a given toolchain. +The last section, on WebAssembly Text Format (WAT), +details how to write WebAssembly components by hand, +without using a higher-level language front-end. -- [Wasm Language Support](#wasm-language-support) - - [Language Agnostic Tooling](#language-agnostic-tooling) - - [Building a Component with `wasm-tools`](#building-a-component-with-wasm-tools) - - [Running a Component with Wasmtime](#running-a-component-with-wasmtime) - [C/C++ Tooling](./language-support/c.md) - [Building a Component with `wit-bindgen` and `wasm-tools`](./language-support/c.md#building-a-component-with-wit-bindgen-and-wasm-tools) - [Running a Component from C/C++ Applications](./language-support/c.md#running-a-component-from-cc-applications) @@ -38,55 +37,6 @@ run components for a given toolchain: - [Rust Tooling](./language-support/rust.md) - [Building a Component with `cargo component`](./language-support/rust.md#building-a-component-with-cargo-component) - [Running a Component from Rust Applications](./language-support/rust.md#running-a-component-from-rust-appliacations) - -## Language Agnostic Tooling - -### Building a Component with `wasm-tools` - -[`wasm-tools`](https://github.com/bytecodealliance/wasm-tools) provides a suite of subcommands for -working with WebAssembly modules and components. - -`wasm-tools` can be used to create a component from WebAssembly Text (WAT). This walks through creating a component from WAT that implements the [`adder` world](https://github.com/bytecodealliance/component-docs/blob/main/component-model/examples/tutorial/wit/adder/world.wit) and simply adds two numbers. - -1. Install [`wasm-tools`](https://github.com/bytecodealliance/wasm-tools/tree/main#installation), a - tool for low-level manipulation of Wasm modules and components. -2. The `add` function is defined inside the following `world` world: - - ```wit - package docs:adder@0.1.0; - - interface add { - add: func(x: u32, y: u32) -> u32; - } - - world adder { - export add; - } - ``` - -3. Define an `add` core module in WAT that exports an `add` function that adds two parameters: - - ```wat - (module - (func $add (param $lhs i32) (param $rhs i32) (result i32) - local.get $lhs - local.get $rhs - i32.add) - (export "docs:adder/add@0.1.0" (func $add)) - ) - ``` - -4. Use `wasm-tools` to create a component from the core module, first embedding component metadata - inside the core module and then encoding the WAT to a Wasm binary. - - ```sh - $ wasm-tools component embed adder/world.wit add.wat -o add.wasm - $ wasm-tools component new add.wasm -o add.component.wasm - ``` - -### Running a Component with Wasmtime - -You can "run" a component by calling one of its exports. Hosts and runtimes often only support -running components with certain exports. The [`wasmtime`](https://github.com/bytecodealliance/wasmtime) CLI can only run "command" components, so in -order to run the `add` function above, it first must be composed with a primary "command" component -that calls it. See [documentation on running components](./running-components/wasmtime.md) for more details. + - [WebAssembly Text Format (WAT)](./language-support/wat.md#wat-webassembly-text-format) + - [Building a Component from WAT with `wasm-tools`](./language-support/wat.md#building-a-component-with-wasm-tools) + - [Running a Component with Wasmtime](./language-support/wat.md#running-a-component-with-wasmtime) diff --git a/component-model/src/language-support/wat.md b/component-model/src/language-support/wat.md new file mode 100644 index 00000000..039e175a --- /dev/null +++ b/component-model/src/language-support/wat.md @@ -0,0 +1,115 @@ +## Language Agnostic Tooling + +[`wasm-tools`](https://github.com/bytecodealliance/wasm-tools) provides a suite of subcommands for +working with WebAssembly modules and components. + +### WAT (WebAssembly Text Format) + +WAT (WebAssembly Text Format) is a text-based language +that can be compiled to the WebAssembly binary format +by `wasm-tools` and other tools. +It's useful for writing small examples for testing and experimentation. + +Here's an example of a module expressed in WAT: +```wat +{{#include ../../examples/tutorial/wat/adder/add.wat}} +``` + +The module contains two top-level declarations, a function and an export. + +The function declaration declares a function named `$add` +with two arguments, `$lhs` and `$rhs`. +(Variable names in WAT always start with a `$`.) +Argument and result types need to be provided explicitly. +In this case, the types of both arguments and the result +are `i32` (32-bit integer). +The body of the function is a list of WebAssembly instructions. +The two `local.get` instructions push the values of `$lhs` and `$rhs` +onto the stack. +The `i32.add` instruction pops the two top values off the stack +and adds them, leaving the result on the stack. + +The `export` declaration connects the function that was just declared +to a name that should be used for calling it externally. +We want to use this WAT code to implement the interface specified in a WIT file, +so the external name has to follow a certain convention. +The name `"docs:adder/add@0.1.0#add"` can be broken down as follows: +* `docs` is the package name. +* `adder` is the name of a world inside the `docs` package. +* `add` is the name of an interface defined in that world. +* 0.1.0 is a version number. +* Separately, `add` is the name of a function defined in the `add` interface. +All of these pieces come from the specific `.wit` file we are using +(see below). + +There's much more than WAT can do; +see the Mozilla Developer Network's [a detailed guide to WAT](https://developer.mozilla.org/en-US/docs/WebAssembly/Guides/Understanding_the_text_format) +for more information. + +The [wat2wasm](https://github.com/WebAssembly/wabt) tool converts +from WAT to the binary `.wasm` format, +but it does not create components. + +### Building a Component from WAT with `wasm-tools` + +`wasm-tools` can be used to create a component from WAT. +Here's how to create a component from WAT +that implements the [`adder` world](https://github.com/bytecodealliance/component-docs/blob/main/component-model/examples/tutorial/wit/adder/world.wit) +and simply adds two numbers. + +1. Install [`wasm-tools`](https://github.com/bytecodealliance/wasm-tools/tree/main#installation), a + tool for low-level manipulation of Wasm modules and components. + +2. The `add` function is defined inside the following world. + Create a file called `adder.wit` whose contents are as follows: + + ```wit + {{#include ../../examples/tutorial/wit/adder/world.wit}} + ``` + +3. Define an `add` core module in WAT that exports an `add` function that adds two parameters. + Create a file called `add.wat` whose contents are as follows + (the same as the example in the WAT section): + +```wat +{{#include ../../examples/tutorial/wat/adder/add.wat}} +``` + +4. Use `wasm-tools` to create a binary core module with component metadata embedded inside it: + + ```sh + wasm-tools component embed adder.wit add.wat -o add.wasm + ``` + +5. Use `wasm-tools` to create a new component `.wasm` file + from the binary core module you just created: + + ```sh + wasm-tools component new add.wasm -o add.component.wasm + ``` + + The suffix `.component.wasm` is just a convention. + You could also name the output file `add_component.wasm` or anything else + with the `.wasm` suffix. + +### Running a Component with Wasmtime + +You can "run" a component by calling one of its exports. +Hosts and runtimes often only support running components with certain exports. + +Using the [`wasmtime`](https://github.com/bytecodealliance/wasmtime) CLI, +we can execute the `add` function in the component you just built, +passing in arguments: + +```sh +wasmtime run --invoke 'add(1, 2)' add.component.wasm +``` + +The output is ```3```. +You can try passing other arguments to `add()` +by changing the arguments inside the parentheses. + +This example was tested with `wasmtime` 34.0.1. +Earlier versions of `wasmtime` may not support the `--invoke` option. +Any other compliant WebAssembly runtime that supports components +can also run this component.