Build
The wash
CLI command includes a build
subcommand that can be used to build WebAssembly components.
See the wash build
CLI reference page for more information on available flags.
The rest of this page will focus on practical examples of using the wash build
command.
Language support
Some languages (like Rust and Go) have support built-in to wash
, while others require extra customization. A list of languages
with built-in support is published in the wasmcloud.toml
specification.
Example projects written in languages with native support can be built by running:
wash build
- Rust
- TinyGo
- TypeScript
- Python
- My Language Isn't Listed
While you can always use the standard Rust toolchain and Bytecode Alliance tooling (like wkg
for fetching WIT packages) to build your components,
wash build
's native support for Rust projects makes building components easier.
The wash build
subcommand performs the same tasks as the following commands using tooling from the wider ecosystem:
# Fetch wit dependencies (see https://github.com/bytecodealliance/wasm-pkg-tools)
wkg wit fetch
# Build the WebAssembly component with the native Rust toolchain
cargo build --release --target wasm32-wasip2
# Sign the built WebAssembly component with your generated keys, using information in wasmcloud.toml
wash claims sign ./target/wasm32-wasip2/release/http_hello_world.wasm --destination http_hello_world_s.wasm
With native support for Rust implemented in wash build
, the above simplifies to:
wash build
While you can always use the standard Go and TinyGo toolchains and Bytecode Alliance tooling (like wkg
for fetching WIT packages) to build your components,
wash build
's native support for Go projects makes building components easier.
The wash build
subcommand performs the same tasks as the following commands using tooling from the wider ecosystem:
# Fetch wit dependencies
wkg wit fetch
# Generate the types and bindings for the Wasm module
go generate
# Build the Wasm module
tinygo build -o ./build/module.wasm -target wasm32-wasi -scheduler none -no-debug .
# Embed the component wit metadata into the module
wasm-tools component embed wit ./build/module.wasm > ./build/embed.wasm
# Create a Wasm component from the embedded Wasm module by using the wasmtime adapter
wasm-tools component new ./build/embed.wasm -o ./build/component.wasm --adapt ./wasi_snapshot_preview1.wasm
# Sign the Wasm component with your generated keys, using information in wasmcloud.toml
wash claims sign ./build/component.wasm --destination ./build/component_s.wasm
# Remove temporarily created files
rm ./build/embed.wasm ./build/module.wasm
With native support for Go implemented in wash build
, the above simplifies to:
wash build
In a TypeScript project, the wash build
subcommand must be customized (via the [component]
section in wasmcloud.toml) to use external JS-native tooling.
TypeScript builds require an installation of NodeJS and npm
. After running npm install
,
jco
(and ComponentizeJS underneath) can be used to compile the transpiled JavaScript code into a WebAssembly Component.
[component]
build_command = "npm run build"
An example build
script in your package.json
might look like the following:
"scripts": {
"build:js": "tsc",
"build:component": "jco componentize -w wit -o dist/your-component.wasm dist/your-component.js",
"build": "npm run build:js && npm run build:component",
In our quickstart example, the wash build
subcommand performs the same tasks as the following commands using tooling from the wider ecosystem:
# Fetch wit dependencies
wkg wit fetch
# You must run `npm install` first
npm install
# Transpile TypeScript code to JavaScript
tsc
# Componentize JavaScript code
jco componentize -w wit -o dist/index.wasm dist/index.js
# Sign the Wasm component with your generated keys, using information in wasmcloud.toml
wash build --sign-only --config-path wasmcloud.toml
In a Python project, the wash build
subcommand must be customized (via the [component]
section in wasmcloud.toml
) to use external Python-native tooling.
Python builds require an installation of Python, pip
and componentize-py
(which can be installed with pip
).
With Python ecosystem tooling in place, we can compile Python code into a WebAssembly Component. Modify the [component]
section of
wasmcloud.toml
to have the following build_command
:
[component]
build_command = "componentize-py -d ./wit -w hello componentize app -o build/http_hello_world.wasm"
In our quickstart example, the wash build
subcommand performs the same tasks as the following commands using tooling from the wider ecosystem:
# Fetch wit dependencies
wkg wit fetch
# Componentize Python code into a WebAssembly Component
componentize-py -d ./wit -w hello componentize app -o build/http_hello_world.wasm
# Sign the Wasm component with your generated keys, using information in wasmcloud.toml
wash build --sign-only --config-path wasmcloud.toml
The wash build
subcommand allows for building arbitrary languages into WebAssembly components via configuring wasmcloud.toml
, for languages without built-in support.
For example, following the Javascript ComponentizeJS example documentation, you can set up your wasmcloud.toml
file like so:
name = "componentize-js"
language = "rust"
type = "component"
[component]
claims = ["wasmcloud:httpserver"]
build_command = "node componentize.mjs"
build_artifact = "hello.component.wasm"
destination = "hello_s.component.wasm"
Overriding the build_command
allows you to use an external script or command to build the component, then specifying where the build_artifact
is (wherever the component should be after the build command completes) lets wash
still
sign the component using your generated keys and other configuration in wasmcloud.toml
.
Note that running wash build
with a custom build_command
configured does not have full support for environment variables or multiple commands
and should be in the form of "command arg1 arg2 arg...". It's recommended to use a single external script to handle more complex build commands.
Interface dependencies and wash build
When you run wash build
, wash
reads the specified world in your WIT files and downloads the appropriate dependencies automatically into the wit/deps
directory. As such, in most cases you should add wit/deps
to your .gitignore
file and commit the generated wasmcloud.lock
file.
Without any additional configuration, wash
can download dependencies from the following namespaces (i.e. the wasi
in wasi:http@0.2.1
):
wasi
: Interfaces proposed for the common WebAssembly System Interface (WASI) standardwasmcloud
: Interfaces maintained as part of the wasmCloud project (see the Capability Catalog to find first-party interfaces)wrpc
: Interfaces maintained as part of the WIT-over-RPC (wRPC) projectba
: Interfaces maintained by the Bytecode Alliance
In most cases, dependency fetching and management should be fairly straightforward! As your usage of Wasm grows, however, you are likely to use dependencies that are not in the above namespaces (such as internal registries or other remappings). Also, if you plan to publish any custom interfaces, you will need to configure your registry with credentials. For instructions on registry authentication, see the Publish page.
WIT interfaces are packaged and distributed as OCI artifacts. You can learn more about how the wasmCloud ecosystem uses OCI artifacts on the Packaging page.
Migrating from wit-deps
Older versions of wash
required a separate step using a wit-deps
tool to download dependencies. This is no longer necessary with the newest versions of wash
. To preserve backwards compatibility, if a deps.toml
file is found in the wit
directory of the project, wash
will not fetch dependencies for you. To migrate to the new dependency management system, simply remove the deps.toml
file and run wash build
again. wash build
will automatically remove all the old dependencies and download the new ones into your wit/deps
directory.
If you are using some of the provided wrpc interfaces like wrpc:blobstore
, you will need to continue using wit-deps
. This is due to an issue where some of the wrpc interfaces use syntax that is not yet available in the main WIT parser (but will be when WASI 0.3 is released) which causes the dependency resolution to fail.