🧱
WadoでコンパイルしたWasmをWasmtimeで動かす
前回のあらすじ
Wadoに入門してmusl libcでビルドされた小さなWadoランタイムを作りました。
今回はこのWadoランタイムでコンパイルしたWasmをWasmtimeで動かしてみたいと思います。
$ wado --version
wado 0.1.0
$ wado compile --help
Usage: wado compile [options] <file.wado>
Compile a Wado source file to WebAssembly.
Options:
-o <file> Output file path (default: <input>.wasm)
--format <fmt> Output format: wasm, wat (default: guessed from -o extension)
--wat-to-stdout Output WAT to stdout (shorthand for --format wat -o /dev/stdout)
--world <name> Target world (default: wasi:cli/command)
Use 'test' to export test functions only
-O <n> Optimization level: -O0, -O1, -O2, -O3, -Os
--log-level <level> Log level: debug, info, warn, error, off (default: info)
--no-validate Skip Wasm validation (output raw bytes even if invalid)
--help Show this help message
Wasmtime
cargo install wasmtime-cliでもインストールできますが、インストールスクリプトを使ったほうが早いので下記コマンドでインストールします。
curl https://wasmtime.dev/install.sh -sSf | bash
$ wasmtime -V
wasmtime 41.0.3 (db1c043b5 2026-02-04)
wado runとwado serveで使用しているWasmtimeの設定を参考にしてオプションフラグをコマンドに渡したいところですが、コマンドがめちゃくちゃ長くなってしまうのでconfig.tomlに書いて--configフラグに渡します。
config.toml
[wasm]
simd = true
threads = true
component-model = true
component-model-async = true
component-model-async-builtins = true
component-model-async-stackful = true
component-model-gc = true
function-references = true
# stack-switching = true
gc = true
wide-arithmetic = true
[wasi]
p3 = true
asyncのstack-switchingが現状linux-x64でしか動かないらしいのでコメントアウトしておきます。[1]
config.tomlチートシート (wasmtime 41.0.3 (db1c043b5 2026-02-04))
$ wasmtime -O help-long
$ wasmtime -C help-long
$ wasmtime -D help-long
$ wasmtime -W help-long
-W simd[=y|n] --
Configure support for the simd proposal.
-W threads[=y|n] --
Configure support for the threads proposal.
-W component-model[=y|n] --
Configure support for the component-model proposal.
-W component-model-async[=y|n] --
Component model support for async lifting/lowering.
-W component-model-async-builtins[=y|n] --
Component model support for async lifting/lowering: this corresponds
to the 🚝 emoji in the component model specification.
-W component-model-async-stackful[=y|n] --
Component model support for async lifting/lowering: this corresponds
to the 🚟 emoji in the component model specification.
-W component-model-gc[=y|n] --
GC support in the component model: this corresponds to the 🛸 emoji
in the component model specification.
-W function-references[=y|n] --
Configure support for the function-references proposal.
-W stack-switching[=y|n] --
Configure support for the stack-switching proposal.
-W gc[=y|n] --
Configure support for the GC proposal.
-W wide-arithmetic[=y|n] --
Configure support for the wide-arithmetic proposal.
$ wasmtime -S help-long
-S p3[=y|n] --
Enable support for WASIp3 APIs.
{
"optimize": ["opt-level", "regalloc-algorithm", "memory-may-move", "memory-reservation", "memory-reservation-for-growth", "memory-guard-size", "guard-before-linear-memory", "table-lazy-init", "pooling-allocator", "pooling-decommit-batch-size", "pooling-memory-keep-resident", "pooling-table-keep-resident", "pooling-memory-protection-keys", "pooling-max-memory-protection-keys", "memory-init-cow", "memory-guaranteed-dense-image-size", "pooling-total-core-instances", "pooling-total-component-instances", "pooling-total-memories", "pooling-total-tables", "pooling-total-stacks", "pooling-max-memory-size", "pooling-table-elements", "pooling-max-core-instance-size", "pooling-max-unused-warm-slots", "pooling-async-stack-keep-resident", "pooling-max-component-instance-size", "pooling-max-core-instances-per-component", "pooling-max-memories-per-component", "pooling-max-tables-per-component", "pooling-max-tables-per-module", "pooling-max-memories-per-module", "pooling-total-gc-heaps", "signals-based-traps", "dynamic-memory-guard-size", "static-memory-guard-size", "static-memory-forced", "static-memory-maximum-size", "dynamic-memory-reserved-for-growth", "pooling-pagemap-scan"],
"codegen": ["compiler", "collector", "cranelift-debug-verifier", "cache", "cache-config", "parallel-compilation", "pcc", "native-unwind-info", "inlining", "cranelift"],
"debug": ["debug-info", "guest-debug", "address-map", "logging", "log-to-files", "coredump"],
"wasm": ["nan-canonicalization", "fuel", "epoch-interruption", "max-wasm-stack", "async-stack-size", "async-stack-zeroing", "unknown-exports-allow", "unknown-imports-trap", "unknown-imports-default", "wmemcheck", "max-memory-size", "max-table-elements", "max-instances", "max-tables", "max-memories", "trap-on-grow-failure", "timeout", "all-proposals", "bulk-memory", "multi-memory", "multi-value", "reference-types", "simd", "relaxed-simd", "relaxed-simd-deterministic", "tail-call", "threads", "shared-memory", "shared-everything-threads", "memory64", "component-model", "component-model-async", "component-model-async-builtins", "component-model-async-stackful", "component-model-threading", "component-model-error-context", "component-model-gc", "function-references", "stack-switching", "gc", "custom-page-sizes", "wide-arithmetic", "extended-const", "exceptions", "gc-support"],
"wasi": ["cli", "cli-exit-with-code", "common", "nn", "threads", "http", "http-outgoing-body-buffer-chunks", "http-outgoing-body-chunk-size", "config", "keyvalue", "listenfd", "tcplisten", "tls", "preview2", "inherit-network", "allow-ip-name-lookup", "tcp", "udp", "network-error-code", "preview0", "inherit-env", "p3"]
}
Run
hello.wadoをhello.wasmにコンパイルしてHello, World!を表示してみます。
touch hello.wado
hello.wado
#!/usr/bin/env -S wado run
use { println, Stdout } from "core:cli";
export fn run() with Stdout {
println("Hello, World!");
}
$ wado compile hello.wado
Generated: hello.wasm
$ wasmtime run --config=config.toml --invoke='run()' hello.wasm
Hello, World!
ok
Wasmtimeで表示できました。
Serve
ok.wadoをok.wasmにコンパイルしてHTTPサーバーを動かしてみたいと思います。
touch ok.wado
ok.wado
#!/usr/bin/env -S wado serve
use { Request, Response, ErrorCode, Fields, Trailers } from "wasi:http";
export async fn handle(request: Request) -> Result<Response, ErrorCode> {
let [trailers_future, trailers_tx] = Future::<Result<Option<Trailers>, ErrorCode>>::new();
let headers = Fields::new();
let [response, _tx_future] = Response::new(headers, null, trailers_future);
task return Result::<Response, ErrorCode>::Ok(response);
trailers_tx.write(Result::<Option<Trailers>, ErrorCode>::Ok(null));
}
$ wado compile --world=wasi:http/service ok.wado
Generated: ok.wasm
$ wasmtime serve --config=config.toml ok.wasm
Serving HTTP on http://0.0.0.0:8080/
$ curl -i http://localhost:8080/
HTTP/1.1 200 OK
transfer-encoding: chunked
date: Sun, 22 Feb 2026 14:00:00 GMT
Wasmtimeで起動して200 OKが返ってくることがわかりました。
Discussion