Language Agnostic Tooling
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:
(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))
)
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:
docsis the package name.adderis the name of a world inside thedocspackage.addis the name of an interface defined in that world.- 0.1.0 is a version number.
- Separately,
addis the name of a function defined in theaddinterface. All of these pieces come from the specific.witfile we are using (see below).
There's much more than WAT can do; see the Mozilla Developer Network's a detailed guide to WAT for more information.
The wat2wasm 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
and simply adds two numbers.
-
Install
wasm-tools, a tool for low-level manipulation of Wasm modules and components. -
The
addfunction is defined inside the following world. Create a file calledadder.witwhose contents are as follows:
package docs:adder@0.1.0;
interface add {
add: func(x: u32, y: u32) -> u32;
}
world adder {
export add;
}
- Define an
addcore module in WAT that exports anaddfunction that adds two parameters. Create a file calledadd.watwhose contents are as follows (the same as the example in the WAT section):
(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))
)
-
Use
wasm-toolsto create a binary core module with component metadata embedded inside it:wasm-tools component embed adder.wit add.wat -o add.wasm -
Use
wasm-toolsto create a new component.wasmfile from the binary core module you just created:wasm-tools component new add.wasm -o add.component.wasmThe suffix
.component.wasmis just a convention. You could also name the output fileadd_component.wasmor anything else with the.wasmsuffix.
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 CLI,
we can execute the add function in the component you just built,
passing in arguments:
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.