Technical Documentation: wasmerio/wasmer
ℹ️ Provenance: Multi-Tier Ingestion · CodeWiki Reference
Overview (`README.md`)
Wasmer runs your apps in fast, secure, and lightweight sandboxes: locally,
in the cloud, or in your browser.
- Secure by default. You control file, network, and environment access.
- Lightweight. Fast startup with a small memory footprint.
- Ready to run. Python, JavaScript, Bash, and more from the registry.
- Embeddable. Add sandboxes to your app with the Wasmer SDK.
Run your first sandbox
Install the CLI on macOS or Linux:
curl https://get.wasmer.io -sSfL | shWindows and other installation options
Windows (PowerShell)
iwr https://win.wasmer.io -useb | iexHomebrew (macOS / Linux)
brew install wasmerSee the installation guide for more options.
Run Python in a sandbox:
wasmer run python/python -- -c "print('Hello from Wasmer')"Hello from WasmerOr try a shell command and Cowsay:
wasmer run wasmer/bash -- -c "echo 'Hello from Wasmer'"
wasmer run syrusakbary/cowsay -- "Hello from Wasmer"Wasmer downloads the package and caches it for future runs. Use -- to separate
Wasmer options from the arguments passed to your program. To work with local
files, grant access to a directory with --volume; enable host networking with--net when your program needs it. See the
CLI guide for details.
No installation needed: open wasmer.sh to try a sandbox
in your browser.
Wasmer SDK
Create a sandbox, choose your tools, and run code directly in your app with the
Wasmer SDK.
Install the SDK
JavaScript / TypeScript (Node.js 20 or newer):
npm install @wasmer/sdkRust
The Rust SDK currently uses a source dependency. Clonewasmerio/wasmer-sdk, then point your
application at its rust directory:
[dependencies]
wasmer-sdk = { path = "../wasmer-sdk/rust" }
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }Follow the Rust setup guide
for the required toolchain and workspace patches. Crates.io publishing is
currently disabled.
Python
python -m pip install wasmer-sdkThe SDK's Python wheels support macOS and Linux on Intel and ARM64.
See the Python guide.
Swift (iOS and macOS)
Use Swift 6 or newer. The SDK supports macOS 12+ and iOS 27+; iOS apps require
Xcode 27 or newer.
Add the package to your Package.swift dependencies:
.package(
url: "https://github.com/wasmerio/wasmer-sdk.git",
revision: "wasmer-sdk-swift-v0.4.0"
)Then add the product to your target's dependencies:
.product(name: "WasmerSDK", package: "wasmer-sdk")In Xcode, you can instead add the repository URL, selectwasmer-sdk-swift-v0.4.0 as a revision, and choose the WasmerSDK product.
SwiftPM downloads the prebuilt macOS binaries and iOS runtime resources.
For iOS, set the deployment target to iOS 27.0 and allow local networking
in your app's Info.plist:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsLocalNetworking</key>
<true/>
</dict>Both platforms use import WasmerSDK and the same API. On iOS, the SDK manages
a hidden WKWebView; your app does not need to display one. See the
Swift guide and
iOS setup guide
for more details.
Run code in a sandbox
JavaScript / TypeScript
Save this as sandbox.mjs:
import { Wasmer } from "@wasmer/sdk/node";
const wasmer = new Wasmer();
const sandbox = await wasmer.sandboxes.create({
packages: ["python/python@=3.13.20"],
});
const output = await sandbox
.command("python", ["-c", "print('Hello from Wasmer')"])
.run();
console.log(output.text());Run it with node sandbox.mjs. Python executes inside the sandbox; you don't
need Python installed on the host. See the
JavaScript guide.
Python example
Save this as sandbox.py:
import asyncio
from wasmer_sdk import Wasmer
async def main():
wasmer = Wasmer()
sandbox = await wasmer.sandboxes.create(
packages=["python/python@=3.13.20"],
)
output = await sandbox.command(
"python", ["-c", "print('Hello from Wasmer')"]
).run()
print(output.text())
asyncio.run(main())Run it with python sandbox.py. See the
Python guide.
Swift example (iOS and macOS)
Use this code in an async throws context:
import WasmerSDK
let wasmer = try Wasmer()
let sandbox = try await wasmer.sandboxes.create(
packages: ["python/python@=3.13.20"]
)
let output = try await sandbox.command(
"python", ["-c", "print('Hello from Swift!')"]
).run(timeout: 30)
print(try output.text())See the Swift guide
for embedding in an iOS or macOS app and more examples.
JavaScript in the browser
Use the same JavaScript sandbox API with the @wasmer/sdk/browser import.
Execution happens in the browser. Your page needs cross-origin isolation
(Cross-Origin-Opener-Policy: same-origin andCross-Origin-Embedder-Policy: require-corp) for worker-backed execution.
Follow the browser setup guide
or explore wasmer.sh.
Rust example
use wasmer_sdk::{Result, Wasmer};
#[tokio::main]
async fn main() -> Result<()> {
let wasmer = Wasmer::new()?;
let sandbox = wasmer
.sandboxes()
.create()
.package("python/python@=3.13.20")
.await?;
let output = sandbox
.command("python")
.args(["-c", "print('Hello from Wasmer')"])
.run()
.await?;
println!("{}", output.text()?);
Ok(())
}See the Rust guide
for workspace setup and more examples.
Go further
Build more with the sandbox API:
- Commands. Run code and capture output.
- Processes. Stream output and manage long-running tasks.
- Files. Read and write the sandbox workspace.
- Tools. Combine languages and packages in one sandbox.
- Services. Run servers with explicit network access.
The SDK is currently alpha. See the language guides for platform support and
capabilities, and the SDK examples
for Python scripts, an Edge.js HTTP server, PostgreSQL, and multiple tools sharing
one sandbox.
Software you can run
Start with packages from the registry:
| Software | Package |
|---|---|
| Python | python/python |
| JavaScript / Node.js-compatible apps | wasmer/edgejs |
| Bash | wasmer/bash |
| PHP | php/php |
| PostgreSQL | wasmer/pglite |
| SQLite | sqlite/sqlite |
| FFmpeg | wasmer/ffmpeg |
Explore more packages,
package your own software, or
deploy an application to Wasmer Edge.
Develop and contribute
This repository contains the Wasmer runtime and CLI that power the sandbox
experience. The sandbox SDKs live inwasmerio/wasmer-sdk.
For lower-level WebAssembly embedding, see the Rust API
and C API.
Contributions are welcome. For guidance on getting started, read
Contributing to Complex Projects.
Wasmer is MIT licensed.
Community
Get help, share what you're building, and meet other Wasmer users:
Community translations (may describe an earlier version)
中文 ·
Deutsch ·
Español ·
Français ·
日本語 ·
한국어
Overview (`assets/README.md`)
Wasmer Documentation Assets
This directory contains documentation assets.
logo.svg contains the Wasmer wordmark from the inline Logo SVG on
wasmer.io, retrieved on September 17, 2026. The original
view box and path geometry are preserved; website-specific attributes are removed.logo-white.svg uses the same paths with a white fill for dark backgrounds.
The root README uses these SVGs; the PNGs remain for older documentation.
Overview (`benches/README.md`)
Wasmer Benches
This directory contains small, punctual benches. Other benchmarks are
landing somewhere else. We will update this section soon.
Overview (`docs/README.md`)
Wasmer Documentation
Wasmer provides multiple documentations. Here are some pointers:
- The Wasmer runtime
README.md
is a good start for the first steps, like installations, first runs etc., - The public documentation contains all the
documentation you need to learn about Wasmer and WebAssembly, - The Rust crates documentations
contain all the documentations to use thewasmer-*Rust crates,
with many examples, - The collection of
examples
illustrates how to use Wasmer and its numerous features through very
commented examples, - Documentations for all embeddings/language
integrations:
the Wasmer runtime can be embedded in various languages or
environments, each embedding provides its own documentation, book
etc., - OS distro packaging
notes
contains notes about how to package Wasmer for OS distributions.
For contributors, one document per concern:
CONTRIBUTING.md, ARCHITECTURE.md,
BUILD.md, TEST.md,
SECURITY.md. The root AGENTS.md indexes
them for coding agents and covers debugging the runtime.
Overview (`examples/README.md`)
Wasmer Examples
This directory contains a collection of examples. This isn't an
exhaustive collection though, if one example is missing, please ask,
we will be happy to fulfill your needs!
Handy Diagrams
As a quick introduction to Wasmer's main workflows, here are three
diagrams. We hope it provides an overview of how the crates assemble
together.
Module compilation, illustrates how WebAssembly bytes are
validated, parsed, and compiled, with the help of thewasmer::Module,wasmer_engine::Engine, andwasmer_compiler::CompilerAPI.Module serialization, illustrates how a module can be
serialized and deserialized, with the help ofwasmer::Module::serializeandwasmer::Module::deserialize. The
important part is that the engine can changed between those two
steps, and thus how a headless engine can be used for the
deserialization.Module instantiation, illustrates what happens when
wasmer::Instance::newis called.
Examples
The examples are written in a difficulty/discovery order. Concepts that
are explained in an example is not necessarily re-explained in a next
example.
Basics
Hello World, explains the core concepts of the Wasmer
API for compiling and executing WebAssembly.Keywords: introduction, instance, module.
Execute the example
shell$ cargo run --example hello-world --release --features "cranelift"Instantiating a module, explains the basics of using Wasmer
and how to create an instance out of a Wasm module.Keywords: instance, module.
Execute the example
shell$ cargo run --example instance --release --features "cranelift"Handling errors, explains the basics of interacting with
Wasm module memory.Keywords: instance, error.
Execute the example
shell$ cargo run --example errors --release --features "cranelift"Interacting with memory, explains the basics of interacting with
Wasm module memory.Keywords: memory, module.
Execute the example
shell$ cargo run --example memory --release --features "cranelift"
Exports
Exported global, explains how to work with
exported globals: get/set their value, have information about their
type.Keywords: export, global.
Execute the example
shell$ cargo run --example exported-global --release --features "cranelift"Exported function, explains how to get and
how to call an exported function. They come in 2 flavors: dynamic,
and “static”/native. The pros and cons are discussed briefly.Keywords: export, function, dynamic, static, native.
Execute the example
shell$ cargo run --example exported-function --release --features "cranelift"Exported memory, explains how to read from
and write to exported memory.Keywords: export, memory.
Execute the example
shell$ cargo run --example exported-memory --release --features "cranelift"
Imports
Imported global, explains how to work with
imported globals: create globals, import them, get/set their value.Keywords: import, global.
Execute the example
shell$ cargo run --example imported-global --release --features "cranelift"Imported function, explains how to define
an imported function. They come in 2 flavors: dynamic,
and “static”/native.Keywords: import, function, dynamic, static, native.
Execute the example
shell$ cargo run --example imported-function --release --features "cranelift"
Externs
Table, explains how to use Wasm Tables from the Wasmer API.
Keywords: basic, table, call_indirect
Execute the example
shell$ cargo run --example table --release --features "cranelift"Memory, explains how to use Wasm Memories from
the Wasmer API. Memory example is a work in progress.Keywords: basic, memory
Execute the example
shell$ cargo run --example memory --release --features "cranelift"
Tunables
Limit memory, explains how to use Tunables to limit the
size of an exported Wasm memoryKeywords: basic, tunables, memory
Execute the example
shell$ cargo run --example tunables-limit-memory --release --features "cranelift"
Engines
Engine, explains what an engine is and how to set it up. The
example completes itself with the compilation of the Wasm module, its
instantiation, and finally, by calling an exported function.Keywords: engine, in-memory, executable code.
Execute the example
shell$ cargo run --example engine --release --features "cranelift"Headless engines, explains what a headless
engine is, what problem it does solve, and what are the benefits of
it. The example completes itself with the instantiation of a
pre-compiled Wasm module, and finally, by calling an exported
function.Keywords: native, engine, constrained environment, ahead-of-time
compilation, cross-compilation, executable code, serialization.Execute the example
shell$ cargo run --example engine-headless --release --features "cranelift"Cross-compilation, illustrates the power
of the abstraction over the engines and the compilers, such as it
is possible to cross-compile a Wasm module for a custom target.Keywords: engine, compiler, cross-compilation.
Execute the example
shell$ cargo run --example cross-compilation --release --features "cranelift"Features, illustrates how to enable WebAssembly
features that aren't yet stable.Keywords: engine, features.
Execute the example
shell$ cargo run --example features --release --features "cranelift"
Compilers
Singlepass compiler, explains how to use
thewasmer-compiler-singlepasscompiler.Keywords: compiler, singlepass.
Execute the example
shell$ cargo run --example compiler-singlepass --release --features "singlepass"Cranelift compiler, explains how to use
thewasmer-compiler-craneliftcompiler.Keywords: compiler, cranelift.
Execute the example
shell$ cargo run --example compiler-cranelift --release --features "cranelift"LLVM compiler, explains how to use the
wasmer-compiler-llvmcompiler.Keywords: compiler, llvm.
Execute the example
shell$ cargo run --example compiler-llvm --release --features "llvm"
Integrations
WASI, explains how to use the WebAssembly System
Interface (WASI), i.e. thewasmer-wasicrate.Keywords: wasi, system, interface
Execute the example
shell$ cargo run --example wasi --release --features "cranelift,wasi"WASI Pipes, builds on the WASI example to show off
stdio piping in Wasmer.Keywords: wasi, system, interface
Execute the example
shell$ cargo run --example wasi-pipes --release --features "cranelift,wasi"
Overview (`fuzz/README.md`)
Wasmer Fuzz Testing
Fuzz testing is:
An automated testing technique that involves providing invalid,
unexpected, or random data as inputs to a program.
We use fuzz testing to automatically discover bugs in the Wasmer runtime.
This fuzz/ directory contains the configuration and the fuzz tests
for Wasmer. To generate and to run the fuzz tests, we use thecargo-fuzz library.
Installation
You may need to install the cargo-fuzz library to get the cargo fuzz subcommand. Use
$ cargo install cargo-fuzzcargo-fuzz is documented in the Rust Fuzz
Book.
Running a fuzzer
This directory provides multiple fuzzers, like for example validate. You can run it with:
$ cargo fuzz run validateAnother example with the cranelift fuzzer:
$ cargo fuzz run craneliftSee thefuzz/fuzz_targets
directory for the full list of fuzzers.
You should see output that looks something like this:
#1408022 NEW cov: 115073 ft: 503843 corp: 4659/1807Kb lim: 4096 exec/s: 889 rss: 857Mb L: 2588/4096 MS: 1 ChangeASCIIInt-
#1408273 NEW cov: 115073 ft: 503844 corp: 4660/1808Kb lim: 4096 exec/s: 888 rss: 857Mb L: 1197/4096 MS: 1 ShuffleBytes-
#1408534 NEW cov: 115073 ft: 503866 corp: 4661/1809Kb lim: 4096 exec/s: 886 rss: 857Mb L: 977/4096 MS: 1 ShuffleBytes-
#1408540 NEW cov: 115073 ft: 503869 corp: 4662/1811Kb lim: 4096 exec/s: 886 rss: 857Mb L: 2067/4096 MS: 1 ChangeBit-
#1408831 NEW cov: 115073 ft: 503945 corp: 4663/1811Kb lim: 4096 exec/s: 885 rss: 857Mb L: 460/4096 MS: 1 CMP- DE: "\x16\x00\x00\x00\x00\x00\x00\x00"-
#1408977 NEW cov: 115073 ft: 503946 corp: 4664/1813Kb lim: 4096 exec/s: 885 rss: 857Mb L: 1972/4096 MS: 1 ShuffleBytes-
#1408999 NEW cov: 115073 ft: 503949 corp: 4665/1814Kb lim: 4096 exec/s: 884 rss: 857Mb L: 964/4096 MS: 2 ChangeBit-ShuffleBytes-
#1409040 NEW cov: 115073 ft: 503950 corp: 4666/1814Kb lim: 4096 exec/s: 884 rss: 857Mb L: 90/4096 MS: 1 ChangeBit-
#1409042 NEW cov: 115073 ft: 503951 corp: 4667/1814Kb lim: 4096 exec/s: 884 rss: 857Mb L: 174/4096 MS: 2 ChangeByte-ChangeASCIIInt-It will continue to generate random inputs forever, until it finds a
bug or is terminated. The testcases for bugs it finds go intofuzz/artifacts/cranelift and you can rerun the fuzzer on a
single input by passing it on the command line cargo fuzz run cranelift /path/to/testcase.
The corpus
Each fuzzer has an individual corpus under fuzz/corpus/test_name,
created on first run if not already present. The fuzzers usewasm-smith which means that the testcase files are random number
seeds input to the Wasm generator, not .wasm files themselves. In
order to debug a testcase, you may find that you need to convert it
into a .wasm file. Using the standalone wasm-smith tool doesn't
work for this purpose because we use a custom configuration to ourwasm_smith::Module. Instead, our fuzzers use an environment variableDUMP_TESTCASE=path. For example:
$ DUMP_TESTCASE=/tmp/crash.wasm cargo fuzz run --features=singlepass singlepass fuzz/artifacts/singlepass/crash-0966412eab4f89c52ce5d681807c8030349470f6Overview (`lib/README.md`)
The Wasmer runtime crates
The philosophy of Wasmer is to be very modular by design. It's
composed of a set of crates. We can group them as follows:
api— The public Rust or JS API exposes everything a user needs to use Wasmer
programmatically through thewasmercrate,c-api— The public C API exposes everything a C user needs to use
Wasmer programmatically,cache— The traits and types to cache compiled WebAssembly
modules,cli— The Wasmer CLI itself,compiler— The base for the compiler implementations, it defines
the framework for the compilers and provides everything they need:compiler-cranelift— A WebAssembly compiler based on the
Cranelift compiler infrastructure,compiler-llvm— A WebAssembly compiler based on the LLVM
compiler infrastructure; recommended for runtime speed
performance,compiler-singlepass— A WebAssembly compiler based on our own
compilation infrastructure; recommended for compilation-time speed
performance.
derive— A set of procedural macros used inside Wasmer,- ABI:
wasi— WASI ABI implementation inside Wasmer:wasi-types— All the WASI types,
engine— The general abstraction for creating an engine, which is
responsible of leading the compiling and running flow. Using the
same compiler, the runtime performance will be approximately the
same, however the way it stores and loads the executable code will
differ:engine— stores the code in a custom file format, and
loads it in memory,object— A library to cross-generate native objects for various
platforms.
middlewares— A collection of middlewares, likemeteringthat
tracks how many operators are executed in total and putting a limit
on the total number of operators executed,types— The basic structures to use WebAssembly,vm— The Wasmer VM runtime library, the low-level base of
everything.
Overview (`docs/cn/README.md`)
Wasmer 提供基于 WebAssembly 的超轻量级容器,其可以在任何地方运行:从桌面到云、以及 IoT 设备,并且也能嵌入到 任何编程语言 中.
其他语言的 Readme: 🇩🇪 Deutsch-德語 • 🇬🇧 English-英文 • 🇪🇸 Español-西班牙语 • 🇫🇷 Français-法语 • 🇯🇵 日本語-日文.
特性
快速又安全. Wasmer在完全沙盒化的环境中以“接近本机”的速度运行 WebAssembly。
可插拔. Wasmer 可以根据你的需求支持不同的编译框架 (LLVM,Cranelift ...).
通用的. 你可以在任何平台(macOS, Linux and Windows) 和芯片组运行 Wasmer.
符合标准. 运行时通过了官方WebAssembly测试集 支持WASI 和Emscripten.
快速开始
Wasmer 不需要安装其他依赖. 你可以使用以下安装程序进行安装:
curl https://get.wasmer.io -sSfL | sh使用Powershell (Windows)
iwr https://win.wasmer.io -useb | iex有关更多安装选项,请参见 wasmer-install: Homebrew, Scoop, Cargo...
执行WebAssembly文件
安装Wasmer之后,你已经准备好执行第一个WebAssembly文件了! 🎉
您可以通过运行 QuickJS 开始: qjs.wasm
$ wasmer qjs.wasm
QuickJS - Type "\h" for help
qjs > const i = 1 + 2;
qjs > console.log("hello " + i);
hello 3接下来是你可以做的:
语言整合
📦 Wasmer 运行时能以库的形式嵌入到不同的语言,因此你可以在任何地方使用WebAssembly.
| 语言 | 程序包 | 文档 | |
|---|---|---|---|
| Rust | wasmer Rust crate |
文档 | |
| C | [wasm.h header] |
文档 | |
| ![C++ logo] | C++ | [wasm.hh header] |
文档 |
| C# | WasmerSharp NuGet package |
文档 | |
| D | wasmer Dub package |
文档 | |
| Python | wasmer PyPI package |
文档 | |
| Javascript | @wasmerio NPM packages |
文档 | |
| Go | wasmer Go package |
文档 | |
| PHP | wasm PECL package |
文档 | |
| Ruby | wasmer Ruby Gem |
文档 | |
| Java | wasmer/wasmer-jni Bintray package |
文档 | |
| Elixir | wasmex hex package |
文档 | |
| R | 没有已发布的软件包 | 文档 | |
| Postgres | 没有已发布的软件包 | 文档 | |
| Swift | 没有已发布的软件包 | ||
| Zig | no published package | ||
| OCaml | wasmer OCaml package |
贡献
我们欢迎任何形式的贡献,尤其是来自社区新成员的贡献 💜
你可以在我们的出色文档 中学习如何构建 Wasmer 运行时!
测试
想要测试吗? 参考 Wasmer 文档.
社区
Wasmer 拥有一个由出色的开发人员和贡献者组成的社区。 欢迎你,请加入我们! 👋
频道
Overview (`docs/de/README.md`)
Wasmer ist eine schnelle und sichere WebAssembly Runtime, die das Ausführen von
schlanken Containern überall ermöglicht: auf dem Desktop in der Cloud, so wie auf Edge und IoT Geräten.
Die README ist auch in folgenden Sprachen verfügbar:
🇨🇳 中文-Chinesisch •
🇬🇧 English-Englisch •
🇪🇸 Español-Spanisch •
🇫🇷 Français-Französisch •
🇯🇵 日本語-Japanisch.
Leistungsmerkmale
- Standardmäßig sicher. Kein Datei-, Netzwerk- oder Umgebungszugriff, sofern nicht explizit aktiviert.
- Unterstützt WASI und Emscripten standardmäßig.
- Schnell. Führt WebAssembly in nahezu nativer Geschwindigkeit aus.
- Einbettbar in mehrere Programmiersprachen
- Kompatibel mit den neuesten Empfehlungen für WebAssembly (SIMD, Referenztypen, Threads, ...)
Installation
Wasmer CLI wird als eine einzige ausführbare Datei ohne Abhängigkeiten ausgeliefert.
curl https://get.wasmer.io -sSfL | shWeitere Installationsmöglichkeiten (Powershell, Brew, Cargo, ...)
Wasmer kann über verschiedene Paketmanager installiert werden. Wählen Sie den für Ihre Umgebung am besten geeigneten aus:
Powershell (Windows)
powershelliwr https://win.wasmer.io -useb | iexHomebrew (macOS, Linux)
shbrew install wasmerScoop (Windows)
shscoop install wasmerChocolatey (Windows)
shchoco install wasmer-
Notiz: Alle verfügbaren Merkmale sind in der
wasmer-cli
crate Dokumentation
beschrieben.shcargo install wasmer-cli
Suchen Sie nach weiteren Installationsmöglichkeiten? Im
wasmer-install
Repository können Si mehr erfahren!
Schnellstart
Sie können beginnen,
QuickJS auszuführen, eine kleine und
einbettbare Javascript Engine, die als WebAssembly Modul kompiliert ist: (qjs.wasm):
$ wasmer qjs.wasm
QuickJS - Type "\h" for help
qjs > const i = 1 + 2;
qjs > console.log("hello " + i);
hello 3Folgendes können Sie als nächstes tun:
📦 Unterstützte Sprachen
Die Wasmer-Laufzeit kann als Bibliothek eingebettet in verschiedenen
Sprachen verwendet werden, so dass Sie WebAssembly überall einsetzen können.
| Sprache | Paket | Dokumentation | |
|---|---|---|---|
| Rust | wasmer Rust crate |
Lernen | |
| C/C++ | wasmer.h header |
Lernen | |
| C# | [WasmerSharp NuGet Paket] |
Lernen | |
| D | [wasmer Dub Paket] |
Lernen | |
| Python | [wasmer PyPI Paket] |
Lernen | |
| Javascript | [@wasmerio NPM Paket] |
Lernen | |
| Go | [wasmer Go Paket] |
Lernen | |
| PHP | [wasm PECL Paket] |
Lernen | |
| Ruby | wasmer Ruby Gem |
Lernen | |
| Java | [wasmer/wasmer-jni Bintray Paket] |
Lernen | |
| Elixir | [wasmex hex Paket] |
Lernen | |
| R | kein Paket veröffentlicht | Lernen | |
| Postgres | kein Paket veröffentlicht | Lernen | |
| Swift | kein Paket veröffentlicht | ||
| Zig | kein Paket veröffentlicht | ||
| Dart | [wasm pub Paket] |
||
| OCaml | wasmer OCaml package |
Unterstützen
Wir sind dankbar für Ihre Hilfe! 💜
Lesen Sie in unserer Dokumentation nach, wie man Wasmer aus dem
Quellcode kompiliert oder testen Sie Änderungen.
Community
Wasmer hat eine wunderbare Community von Entwicklern und Mitwirkenden. Sie sind herzlich willkommen, bitte machen Sie mit! 👋
Overview (`docs/es/README.md`)
Wasmer hace posible tener contenedores ultraligeros basados en WebAssembly que pueden ser ejecutados en cualquier sitio: desde tu ordenador hasta la nube y dispositivos de IoT, además de poder ser ejecutados en cualquier lenguaje de programación.
This README is also available in: 🇩🇪 Deutsch-Alemán • 🇬🇧 English-Inglés • 🇫🇷 Français-Francés • 🇨🇳 中文-Chino • 🇯🇵 日本語-japonés.
Funcionalidades
Rápido y Seguro. Wasmer ejecuta WebAssembly a velocidades nativas en un entorno completamente protegido.
Extendible. Wasmer soporta diferentes métodos de compilación dependiendo de tus necesidades (LLVM, Cranelift...).
Universal. Puedes ejecutar Wasmer en cualquier platforma (macOS, Linux y Windows) y chip.
Respeta los estándares. Wasmer pasa los tests oficiales de WebAssembly siendo compatible con WASI y Emscripten.
Empezamos?
Wasmer no requiere ninguna dependencia. Puedes instalarlo con uno de estos instaladores:
curl https://get.wasmer.io -sSfL | shCon PowerShell (Windows)
iwr https://win.wasmer.io -useb | iexVisita wasmer-install para más opciones de instalación: Homebrew, Scoop, Cargo...
Ejecuta un archivo WebAssembly
¡Después de instalar Wasmer deberías estar listo para ejecutar tu primer módulo de WebAssembly! 🎉
Puedes empezar corriendo QuickJS: qjs.wasm
$ wasmer qjs.wasm
QuickJS - Type "\h" for help
qjs >Esto es lo que puedes hacer:
Integraciones en diferentes Lenguajes
📦 Wasmer puede ser usado como una librería integrada en diferentes lenguajes de programación, para que puedas ejecutar WebAssembly en cualquier sitio.
| Lenguaje | Librería | Documentación | |
|---|---|---|---|
| Rust | wasmer en crates.io |
Documentación | |
| C/C++ | cabecera wasmer.h |
Documentación | |
| C# | WasmerSharp en NuGet |
Documentación | |
| D | [wasmer en Dug] |
Documentación | |
| Python | wasmer en PyPI |
Documentación | |
| Javascript | @wasmerio en NPM |
Documentación | |
| Go | wasmer en Go |
Documentación | |
| PHP | wasm en PECL |
Documentación | |
| Ruby | wasmer en Ruby Gems |
Documentación | |
| Java | wasmer/wasmer-jni en Bintray |
Documentación | |
| Elixir | wasmex en hex |
Documentación | |
| R | sin paquete publicado | Documentación | |
| Postgres | sin paquete publicado | Documentación | |
| Swift | sin paquete publicado | ||
| Zig | no published package | ||
| OCaml | wasmer OCaml package |
Contribuye
Damos la bienvenida a cualquier forma de contribución, especialmente a los nuevos miembros de la comunidad 💜
¡Puedes ver cómo crear el binario de Wasmer con nuestros increíbles documentos!
Tests
¿Quieres testear? Los documentos de Wasmer te enseñarán cómo.
Comunidad
Wasmer tiene una comunidad increíble de desarrolladores y colaboradores ¡Bienvenido, únete a nosotros! 👋
Medios
Overview (`docs/fr/README.md`)
Wasmer permet l'utilisation de conteneurs super légers basés sur WebAssembly qui peuvent fonctionner n'importe où : du bureau au cloud en passant par les appareils IoT, et également intégrés dans une multitude de langages de programmation.
This readme is also available in: 🇩🇪 Deutsch-Allemand • 🇬🇧 English-Anglaise • 🇪🇸 Español-Espagnol • 🇨🇳 中文-Chinoise • 🇯🇵 日本語-japonais
Fonctionnalités
Rapide et sûr. Wasmer exécute WebAssembly à une vitesse quasi native dans un environnement entièrement contrôlé (bac à sable, sandbox).
Modulaire. Wasmer prend en charge différents frameworks de compilation pour répondre au mieux à vos besoins (LLVM, Cranelift ...).
Universel. Vous pouvez exécuter Wasmer sur n'importe quelle plate-forme (macOS, Linux et Windows) et processeur.
Conforme aux normes. Wasmer passe la suite de tests officielle de WebAssembly prenant en charge WASI et Emscripten
Quickstart
Wasmer est livré sans aucune dépendance. Vous pouvez l'installer à l'aide des programmes d'installation ci-dessous :
curl https://get.wasmer.io -sSfL | shAvec PowerShell (Windows)
iwr https://win.wasmer.io -useb | iexVoir wasmer-install pour plus d'options d'installation: Homebrew, Scoop, Cargo...
Exécution d'un fichier WebAssembly
Après avoir installé Wasmer, vous devriez être prêt à exécuter votre premier fichier WebAssemby ! 🎉
Vous pouvez commencer par exécuter QuickJS : qjs.wasm
$ wasmer qjs.wasm
QuickJS - Type "\h" for help
qjs >Voici ce que vous pouvez faire ensuite
- Utilisez Wasmer depuis votre application Rust
- Publier un paquet Wasm sur WAPM
- En savoir plus sur Wasmer
Intégrations
📦 Wasmer peut être utilisé comme une bibliothèque intégrée dans différents langages, vous pouvez donc utiliser WebAssembly n'import où.
| Langage de programmation | Package | Docs | |
|---|---|---|---|
| Rust | wasmer Rust crate |
Docs | |
| C/C++ | wasmer.h headers |
Docs | |
| C# | WasmerSharp NuGet package |
Docs | |
| D | wasmer Dub package |
Docs | |
| Python | wasmer PyPI package |
Docs | |
| Javascript | @wasmerio NPM packages |
Docs | |
| Go | wasmer Go package |
Docs | |
| PHP | wasm PECL package |
Docs | |
| Ruby | wasmer Ruby Gem |
Docs | |
| Java | wasmer/wasmer-jni Bintray package |
Docs | |
| Elixir | wasmex hex package |
Docs | |
| R | no published package | Docs | |
| Postgres | no published package | Docs | |
| Swift | no published package | ||
| Zig | no published package | ||
| OCaml | wasmer OCaml package |
Contribuer
Nous accueillons toutes formes de contributions, en particulier de la part des nouveaux membres de notre communauté. 💜
Vous pouvez vérifier comment compiler Wasmer dans notre documentation!
Test
Vous voulez des tests ? La documentation de Wasmer vous montrera comment les exécuter.
Communauté
Wasmer a une incroyable communauté de développeurs et de contributeurs. Bienvenue et rejoignez-nous ! 👋
Canaux de communications
Overview (`docs/ja/README.md`)
Wasmer は、WebAssembly をベースとした非常に軽量なコンテナを実現します。デスクトップからクラウドや IoT デバイス上まで、どんな環境でも実行でき、さらに任意のプログラミング言語に埋め込むこともできます。
この readme は、次の言語でも利用可能です。🇩🇪 Deutsch-ドイツ語 • 🇨🇳 中文-Chinese • 🇬🇧 English-英語 • 🇪🇸 Español-Spanish • 🇫🇷 Français-French
機能
高速かつ安全。WebAssembly を完全なサンドボックス環境内でネイティブに近いスピードで実行します。
プラガブル。異なるコンパイルフレームワーク (LLVM、Cranelift など...) をサポートしているため、ニーズに合った最適なフレームワークを選択できます。
ユニバーサル。どんなプラットフォーム上 (macOS、Linux、Windows) でも、どんなチップセット上でも実行できます。
標準に準拠。ランタイムは公式の WebAssembly テストスイートに通っており、WASI と Emscripten をサポートします。
クイックスタート
Wasmer は依存関係なしで動作します。以下のコマンドでインストーラーを使用してインストールできます。
curl https://get.wasmer.io -sSfL | shPowerShell の場合 (Windows)
iwr https://win.wasmer.io -useb | iexHomebrew、Scoop、Cargo など、他のインストール方法については、wasmer-install を参照してください。
WebAssembly ファイルの実行
Wasmer をインストールしたら、初めての WebAssembly ファイルの実行準備が完了です! 🎉
QuickJS (qjs.wasm) を実行することで、すぐに始められます。
$ wasmer qjs.wasm
QuickJS - Type "\h" for help
qjs >次にできること
他の言語とのインテグレーション
📦 Wasmer ランタイムは他の言語に組み込んで使用できるため、WebAssembly はどんな場所でも利用できます。
| Language | Package | Docs | |
|---|---|---|---|
| Rust | wasmer Rust crate |
Docs | |
| C/C++ | wasmer.h headers |
Docs | |
| C# | WasmerSharp NuGet package |
Docs | |
| D | wasmer Dub package |
Docs | |
| Python | wasmer PyPI package |
Docs | |
| Javascript | @wasmerio NPM packages |
Docs | |
| Go | wasmer Go package |
Docs | |
| PHP | wasm PECL package |
Docs | |
| Ruby | wasmer Ruby Gem |
Docs | |
| Java | wasmer/wasmer-jni Bintray package |
Docs | |
| Elixir | wasmex hex package |
Docs | |
| R | 公開パッケージなし | Docs | |
| Postgres | 公開パッケージなし | Docs | |
| Swift | 公開パッケージなし | ||
| Zig | no published package | ||
| OCaml | wasmer OCaml package |
コントリビューション
どんな形での貢献も歓迎です。コミュニティの新しいメンバーからの貢献は特に歓迎します。 💜
Wasmer ランタイムのビルド方法は、素晴らしいドキュメントで確認できます!
テスト
テストを実行したいですか? Wasmer docs で方法を説明しています。
コミュニティ
Wasmer には、開発者とコントリビューターの素晴らしいコミュニティがあります。ようこそ! あなたも是非参加してください! 👋
チャンネル
Overview (`docs/ko/README.md`)
Wasmer는 초경량 컨테이너 를 Desktop에서부터 Cloud, Edge, IoT 기기들까지 어디에서나 실행할 수 있는 빠르고 안전한 WebAssembly 런타임 입니다.
이 문서는 아래와 같은 언어들을 지원합니다.:
🇨🇳 中 文 -Chinese •
🇩🇪 Deutsch-German •
🇪🇸 Español-Spanish •
🇫🇷 Français-French •
🇯🇵 日本 語 -Japanese.
🇰🇷 한국어 -Korean_.
특징
- 기본적으로 안전합니다. 명시적으로 설정하지 않는 한 파일, 네트워크 또는 환경에 액세스할 수 없습니다.
- WASI와 Emscripten을 즉시 지원합니다.
- 빠릅니다. native에 가까운 속도로 WebAssembly를 실행합니다.
- 여러 프로그래밍 언어에 임베디드 가능합니다.
- 최신 WebAssembly 제안(SIMD, Reference Types, Threads, ...)을 준수합니다.
설치
Wasmer CLI는 종속성이 없는 단일 실행 파일로 제공됩니다.
curl https://get.wasmer.io -sSfL | sh다른 설치 옵션 (Powershell, Brew, Cargo, ...)
Wasmer는 다양한 패키지 매니저를 통해 설치 할 수 있습니다. 환경에 가장 적합한 것을 선택하십시오.:
Powershell (Windows)
powershelliwr https://win.wasmer.io -useb | iexHomebrew (macOS, Linux)
shbrew install wasmerScoop (Windows)
shscoop install wasmerChocolatey (Windows)
shchoco install wasmer-
Note: 사용 가능한 모든 기능은
wasmer-cli
crate docs 문서에 설명되어 있습니다.shcargo install wasmer-cli
더 많은 설치 옵션을 찾고 계십니까? 자세한 내용은 the
wasmer-install
repository를 참조하십시오!
빠른 시작
WebAssembly 모듈(qjs.wasm)로 컴파일된
작고 포함 가능한 Javascript 엔진인 QuickJS를 실행하여 시작할 수 있습니다.:
$ wasmer qjs.wasm
QuickJS - Type "\h" for help
qjs > const i = 1 + 2;
qjs > console.log("hello " + i);
hello 3다음에 할 수 있는 일 :
📦 다른 언어와의 통합
Wasmer 런타임은 다른 언어에 내장된 라이브러리로 사용할 수 있으므로 어디에서나 WebAssembly를 사용할 수 있습니다.
| Language | Package | Documentation | |
|---|---|---|---|
| Rust | wasmer Rust crate |
Learn | |
| C/C++ | wasmer.h header |
Learn | |
| C# | WasmerSharp NuGet package |
Learn | |
| D | wasmer Dub package |
Learn | |
| Python | wasmer PyPI package |
Learn | |
| Javascript | @wasmerio NPM packages |
Learn | |
| Go | wasmer Go package |
Learn | |
| PHP | wasm PECL package |
Learn | |
| Ruby | wasmer Ruby Gem |
Learn | |
| Java | wasmer/wasmer-jni Bintray package |
Learn | |
| Elixir | wasmex hex package |
Learn | |
| R | 공개 패키지 없음 | Learn | |
| Postgres | 공개 패키지 없음 | Learn | |
| Swift | 공개 패키지 없음 | ||
| Zig | 공개 패키지 없음 | ||
| Dart | wasm pub package |
||
| Lisp | under heavy development - no published package | ||
| OCaml | wasmer OCaml package |
기여
도움을 주셔서 감사합니다! 💜
Wasmer를 빌드하거나 변경 사항을 테스트하는 방법에 대한 문서를 확인하십시오.
커뮤니티
Wasmer에는 개발자의 기여가 있는 훌륭한 커뮤니티가 있습니다. 환영합니다! 꼭 참여해주세요! 👋
Overview (`lib/api/README.md`)
`wasmer` [](https://github.com/wasmerio/wasmer/actions?query=workflow%3Abuild) [](https://slack.wasmer.io) [](https://github.com/wasmerio/wasmer/blob/main/LICENSE) [](https://crates.io/crates/wasmer)
Wasmer is the most popular
WebAssembly runtime for Rust. It supports JIT (Just
In Time), AOT (Ahead Of Time) compilation, an experimental interpreter as well
as pluggable compilers suited to your needs.
It's designed to be safe and secure, and runnable in any kind of environment.
Usage
Here is a small example of using Wasmer to run a WebAssembly module
written with its WAT format (textual format):
use wasmer::{Store, Module, Instance, Value, imports};
fn main() -> anyhow::Result<()> {
let module_wat = r#"
(module
(type $t0 (func (param i32) (result i32)))
(func $add_one (export "add_one") (type $t0) (param $p0 i32) (result i32)
local.get $p0
i32.const 1
i32.add))
"#;
let mut store = Store::default();
let module = Module::new(&store, &module_wat)?;
// The module doesn't import anything, so we create an empty import object.
let import_object = imports! {};
let instance = Instance::new(&mut store, &module, &import_object)?;
let add_one = instance.exports.get_function("add_one")?;
let result = add_one.call(&mut store, &[Value::I32(42)])?;
assert_eq!(result[0], Value::I32(43));
Ok(())
}Discover the full collection of examples.
Features
Wasmer is not only fast, but also designed to be highly customizable:
Pluggable compilers — A compiler is used by the engine to
transform WebAssembly into executable code:wasmer-compiler-singlepassprovides a fast compilation-time
but an unoptimized runtime speed,wasmer-compiler-craneliftprovides the right balance between
compilation-time and runtime performance, useful for development,wasmer-compiler-llvmprovides a deeply optimized executable
code with the fastest runtime speed, ideal for production.
Headless mode — Once a WebAssembly module has been compiled, it
is possible to serialize it in a file for example, and later execute
it with Wasmer with headless mode turned on. Headless Wasmer has no
compiler, which makes it more portable and faster to load. It's
ideal for constrained environments.Cross-compilation — Most compilers support cross-compilation. It
means it possible to pre-compile a WebAssembly module targeting a
different architecture or platform and serialize it, to then run it
on the targeted architecture and platform later.Run Wasmer in a JavaScript environment — With the
jsCargo
feature, it is possible to compile a Rust program using Wasmer to
WebAssembly. In this context, the resulting WebAssembly module will
expect to run in a JavaScript environment, like a browser, Node.js,
Deno and so on. In this specific scenario, there is no engines or
compilers available, it's the one available in the JavaScript
environment that will be used.
Wasmer ships by default with the Cranelift compiler as its great for
development purposes. However, we strongly encourage to use the LLVM
compiler in production as it performs about 50% faster, achieving
near-native speeds.
Note: if one wants to use multiple compilers at the same time, it's
also possible! One will need to import them directly via each of the
compiler crates.
Read the documentation to learn
more.
Made with ❤️ by the Wasmer team, for the community
Overview (`lib/backend-api/README.md`)
wasmer-backend-api
GraphQL API client for the Wasmer backend.
Development
This client is built on the cynic crate,
a GraphQL client library that allows tight integration between Rust and
GraphQL types.
It was chosen over other implementations like graphql-client because it
significantly reduces boilerplate and improves the development experience.
The downside is that the underlying GraphQL queries are much less obvious when
looking at the code. This can be remedied with some strategies mentioned below.
Consult the Cynic docs at cynic-rs.dev for more
information.
Backend GraphQL Schema
The GraphQL schema for the backend is stored in ./schema.graphql.
To update the schema, simply download the latest version and replace the local
file.
It can be retrieved from
https://github.com/wasmerio/backend/blob/main/backend/graphql/schema.graphql.
Writing/Updating Queries
You can use the Cynic web UI to easily create the types for new
queries.
Simply upload the local schema from ./schema.graphql and use the UI to build
your desired query.
NOTE: Where possible, do not duplicate types that are already defined,
and instead reuse/extend them where possible.
This is not always sensible though, depending on which nested data you want to
fetch.
Overview (`lib/c-api/README.md`)
`wasmer-c-api` [](https://github.com/wasmerio/wasmer/actions?query=workflow%3Abuild) [](https://slack.wasmer.io) [](https://github.com/wasmerio/wasmer/blob/main/LICENSE)
This crate exposes a C and a C++ API for the Wasmer runtime. It also fully supports the wasm-c-api common API.
Usage
Once you install Wasmer in your system, the shared object files and the headers are available inside the Wasmer installed path.
$WASMER_DIR/
lib/
libwasmer.{so,dylib,dll}
include/
wasm.h
wasmer.h
wasmer.hhWasmer binary also ships with wasmer-config
an utility tool that outputs config information needed to compile programs which use Wasmer.
The full C API documentation can be found here.
Here is a simple example to use the C API:
/* Detailed source-code truncated for AI context efficiency. */Building
You can compile Wasmer shared library from source:
make build-capiThis will generate the shared library (depending on your system):
- Windows:
target/release/libwasmer_c_api.dll - macOS:
target/release/libwasmer_runtime_c_api.dylib - Linux:
target/release/libwasmer_runtime_c_api.so
If you want to generate the library and headers in a friendly format as shown in Usage, you can execute the following in Wasmer root:
make package-capiThis command will generate a package directory, that you can then use easily in the Wasmer C API examples.
Testing
Tests are run using the release build of the library. If you make
changes or compile with non-default features, please ensure you
rebuild in release mode for the tests to see the changes.
To run all the full suite of tests, enter Wasmer root directory
and run the following commands:
$ make test-capi`wasmer config`
wasmer config output various configuration information needed to compile programs which use Wasmer.
`wasmer config --pkg-config`
It outputs the necessary details for compiling and linking a program to Wasmer,
using the pkg-config format:
$ wasmer config --pkg-config > $PKG_CONFIG_PATH/wasmer.pc`wasmer config --includedir`
Directory containing Wasmer headers:
$ wasmer config --includedir
/users/myuser/.wasmer/include`wasmer config --libdir`
Directory containing Wasmer libraries:
$ wasmer config --libdir
/users/myuser/.wasmer/lib`wasmer config --libs`
Libraries needed to link against Wasmer components:
$ wasmer config --libs
-L/Users/myuser/.wasmer/lib -lwasmer`wasmer config --cflags`
Headers needed to build against Wasmer components:
$ wasmer config --cflags
-I/Users/myuser/.wasmer/include/wasmerLicense
Wasmer is primarily distributed under the terms of the MIT
license (LICENSE).
Overview (`lib/cache/README.md`)
`wasmer-cache` [](https://github.com/wasmerio/wasmer/actions?query=workflow%3Abuild) [](https://slack.wasmer.io) [](https://github.com/wasmerio/wasmer/blob/main/LICENSE)
The wasmer-cache crate allows to cache WebAssembly modules (of kindwasmer::Module) in your system, so that next uses of the module does
imply a compilation time.
Usage
The Cache trait represents a generic cache for storing and loading
compiled WebAssembly modules. The FileSystemCache type implementsCache to store cache on the file system.
use wasmer::{DeserializeError, Module, SerializeError};
use wasmer_cache::{Cache, FileSystemCache, Hash};
fn store_module(module: &Module, bytes: &[u8]) -> Result<(), SerializeError> {
// Create a new file system cache.
let mut fs_cache = FileSystemCache::new("some/directory/goes/here")?;
// Compute a key for a given WebAssembly binary
let hash = Hash::generate(bytes);
// Store a module into the cache given a key
fs_cache.store(hash, module.clone())?;
Ok(())
}Overview (`lib/cli/README.md`)
`wasmer-cli` [](https://github.com/wasmerio/wasmer/actions?query=workflow%3Abuild) [](https://slack.wasmer.io) [](https://github.com/wasmerio/wasmer/blob/main/LICENSE)
This crate is the Wasmer CLI.
The recommended way to install wasmer is via the wasmer-installer.
However, you can also install wasmer via Cargo (you will need to specify the compilers to use):
cargo install wasmer-cli --features "singlepass,cranelift"Or by building it inside the codebase:
cargo build --release --features "singlepass,cranelift"Features
The Wasmer supports the following features:
wat(default): support for executing WebAssembly text files.wast(default): support for running wast test files.cache(default): support or automatically caching compiled artifacts.wasi(default): support for WASI.singlepass: support for the Singlepass compiler.cranelift: support for the Cranelift compiler.llvm: support for the LLVM compiler.
CLI commands
Once you have Wasmer installed, you can start executing WebAssembly files easily:
Get the current Wasmer version:
wasmer -VExecute a WebAssembly file:
wasmer run myfile.wasmCompile a WebAssembly file:
wasmer compile myfile.wasm -o myfile.wasmuRun a compiled WebAssembly file (fastest):
wasmer run myfile.wasmuOverview (`lib/compiler-cranelift/README.md`)
`wasmer-compiler-cranelift` [](https://github.com/wasmerio/wasmer/actions?query=workflow%3Abuild) [](https://slack.wasmer.io) [](https://github.com/wasmerio/wasmer/blob/main/LICENSE) [](https://crates.io/crates/wasmer-compiler-cranelift)
This crate contains a compiler implementation based on Cranelift.
Usage
use wasmer::{Store, sys::EngineBuilder};
use wasmer_compiler_cranelift::Cranelift;
let compiler = Cranelift::new();
let mut store = Store::new(compiler);Note: you can find a full working example using Cranelift compiler
here.
When to use Cranelift
We recommend using this compiler crate only for development
proposes. For production we recommend using wasmer-compiler-llvm
as it offers a much better runtime speed (50% faster on average).
Acknowledgments
This project borrowed some of the function lowering fromcranelift-wasm.
Please check Wasmer ATTRIBUTIONS to further see licenses and other
attributions of the project.
Overview (`lib/compiler-llvm/README.md`)
`wasmer-compiler-llvm` [](https://github.com/wasmerio/wasmer/actions?query=workflow%3Abuild) [](https://slack.wasmer.io) [](https://github.com/wasmerio/wasmer/blob/main/lib/compiler-llvm/LICENSE) [](https://crates.io/crates/wasmer-compiler-llvm)
This crate contains a compiler implementation based on the LLVM Compiler Infrastructure.
Usage
use wasmer::{Store, EngineBuilder};
use wasmer_compiler_llvm::LLVM;
let compiler = LLVM::new();
let mut store = Store::new(compiler);Note: you can find a full working example using LLVM compiler here.
When to use LLVM
We recommend using LLVM as the default compiler when running WebAssembly
files on any production system, as it offers maximum performance near
to native speeds.
Requirements
The LLVM compiler requires a valid installation of LLVM in your system.
It currently requires LLVM 22.
You can install LLVM easily on your Debian-like system via this command:
wget https://apt.llvm.org/llvm.sh -O /tmp/llvm.sh
sudo bash /tmp/llvm.sh 22
sudo apt install libpolly-22-devOr in macOS:
brew install llvm@22Or via any of the pre-built binaries that LLVM offers.
Overview (`lib/compiler-singlepass/README.md`)
`wasmer-compiler-singlepass`
This crate contains a compiler implementation based on the Singlepass linear compiler.
Supported targets:
- x86_64
- aarch64
- riscv64 (experimental)
Usage
use wasmer::{Store, sys::EngineBuilder};
use wasmer_compiler_singlepass::Singlepass;
let compiler = Singlepass::new();
let mut store = Store::new(compiler);Note: you can find a full working example using Singlepass compiler
here.
When to use Singlepass
Singlepass is designed to emit compiled code at linear time, as such
is not prone to JIT bombs and also offers great compilation
performance orders of magnitude faster thanwasmer-compiler-cranelift and wasmer-compiler-llvm, however
with a bit slower runtime speed.
The fact that singlepass is not prone to JIT bombs and offers a very
predictable compilation speed makes it ideal for blockchains and other
systems where fast and consistent compilation times are very critical.
Overview (`lib/compiler/README.md`)
`wasmer-compiler` [](https://github.com/wasmerio/wasmer/actions?query=workflow%3Abuild) [](https://slack.wasmer.io) [](https://github.com/wasmerio/wasmer/blob/main/LICENSE)
This crate is the base for Compiler implementations.
It performs the translation from a Wasm module into a basicModuleInfo, but leaves the Wasm function bytecode translation to the
compiler implementor.
Here are some of the Compilers provided by Wasmer:
How to create a compiler
To create a compiler, one needs to implement two traits:
CompilerConfig, that configures and creates a new compiler,Compiler, the compiler itself that will compile a module.
/// The compiler configuration options.
pub trait CompilerConfig {
/// Gets the custom compiler config
fn compiler(&self) -> Box<dyn Compiler>;
}
/// An implementation of a compiler from parsed WebAssembly module to compiled native code.
pub trait Compiler {
/// Compiles a parsed module.
///
/// It returns the [`Compilation`] or a [`CompileError`].
fn compile_module<'data, 'module>(
&self,
target: &Target,
compile_info: &'module CompileModuleInfo,
module_translation: &ModuleTranslationState,
// The list of function bodies
function_body_inputs: PrimaryMap<LocalFunctionIndex, FunctionBodyData<'data>>,
) -> Result<Compilation, CompileError>;
}Acknowledgments
This project borrowed some of the code structure from thecranelift-wasm crate, however it's been adapted to not depend on
any specific IR and be abstract of any compiler.
Please check Wasmer ATTRIBUTIONS to further see licenses and other
attributions of the project.
Overview (`lib/config/README.md`)
wasmer-config
(API Docs)
Provides configuration types for Wasmer.
For Developers
Releasing
This repository uses Release Please to automate a lot of the
work around creating releases.
Every time a commit following the Conventional Commit Style is merged
into main, the release-please.yml
workflow will run and update the "Release PR" to reflect the new changes.
For commits that just fix bugs (i.e. the message starts with "fix: "), the
associated crate will receive a changelog entry and a patch version bump.
Similarly, adding a new feature (i.e. "feat:") does a minor version bump and
adding breaking changes (i.e. "fix!:" or "feat!:") will result in a major
version bump.
When the release PR is merged, the updated changelogs and bumped version numbers
will be merged into the main branch, the release-please.yml workflow will
automatically generate GitHub Releases, and CI will publish the crate if
necessary.
TL;DR:
- Use Conventional Commit Messages whenever you make a noteworthy change
- Merge the release PR when ready to release
- Let the automation do everything else
License
This project is licensed under the MIT license (LICENSE or
http://opensource.org/licenses/MIT).
It is recommended to always use cargo crev to verify the
trustworthiness of each of your dependencies, including this one.
Overview (`lib/middlewares/README.md`)
Wasmer Middlewares
The wasmer-middlewares crate is a collection of various useful
middlewares:
metering: A middleware for tracking how many operators are
executed in total and putting a limit on the total number of
operators executed.See the
metering
example
to get a concrete and complete example.
Overview (`lib/package-sdk/README.md`)
wasmer-sdk
The wasmer-sdk provides convenient wrappers to work with the Wasmer ecosystem,
including functionality for:
- Building and publishing packages
- Deploying apps
- ...
Architecture Support
This crate currently only works on native architectures, and does not support
browser Webassembly yet. Support will likely added in the future.
Overview (`lib/types/README.md`)
`wasmer-types` [](https://github.com/wasmerio/wasmer/actions?query=workflow%3Abuild) [](https://slack.wasmer.io) [](https://github.com/wasmerio/wasmer/blob/main/LICENSE)
This library provides all the types and traits necessary to use
WebAssembly easily anywhere.
Among other things, it defines the following types:
unitslikePagesorBytestypesandvalueslikeI32,I64,F32,F64,ExternRef,FuncRef,V128, value conversions,ExternType,FunctionType
etc.nativecontains a set of trait and implementations to deal with
WebAssembly types that have a direct representation on the host,memory_view, an API to read/write memories when bytes are
interpreted as particular types (i8,i16,i32etc.)indexescontains all the possible WebAssembly module indexes for
various typesinitializersfor tables, data etc.featuresto enable or disable some WebAssembly features inside the
Wasmer runtime
Acknowledgments
This project borrowed some of the code for the entity structure from cranelift-entity.
We decided to move it here to help on serialization/deserialization.
Please check Wasmer ATTRIBUTIONS to further see licenses and other attributions of the project.
Overview (`lib/vm/README.md`)
`wasmer-vm` [](https://github.com/wasmerio/wasmer/actions?query=workflow%3Abuild) [](https://slack.wasmer.io) [](https://github.com/wasmerio/wasmer/blob/main/LICENSE)
This crate contains the Wasmer VM runtime library, supporting the Wasm ABI used by wasmer.
The Wasmer runtime is modular by design, and provides several
libraries where each of them provides a specific set of features. Thiswasmer-vm library contains the low-level foundation for the runtime
itself.
It provides all the APIs wasmer needs to operate,
from the instance, to memory, probestack, signature registry, trap,table, VMContext, libcalls etc.
It is very unlikely that a user will need to deal with wasmer-vm
directly. The wasmer crate provides types that embed types fromwasmer-vm with a higher-level API.
Acknowledgments
This project borrowed some of the code for the VM structure and trapping from the wasmtime-runtime.
Please check Wasmer ATTRIBUTIONS to further see licenses and other attributions of the project.
Overview (`lib/wai-bindgen-wasmer/README.md`)
wai-bindgen-wasmer
Runtime utility crate for Wasmer host WAI bindings generated by wai-bindgen-gen-wasmer.
This crate was moved from the https://github.com/wasmerio/wai repository.
wai-bindgen-wasmer needs Wasmer as a dependency, which makes it extremely awkward to use if the
crate is not in the same repo.
This is necessary because wai is now used for wasix_http_client bindings, and will also be used
for all WASI and WASIX syscalls in the future.
The medium-term plan is to rewrite wai-bindgen-gen-wasmer to make this create redundant.
See https://github.com/wasmerio/wai/issues/31 .
Overview (`lib/wasi-types/README.md`)
wasmer-wasix-types
This crate contains WASI(X) type definitions used by wasmer-wasix.
Overview (`lib/wasix/README.md`)
`wasmer-wasi` [](https://github.com/wasmerio/wasmer/actions?query=workflow%3Abuild) [](https://slack.wasmer.io) [](https://github.com/wasmerio/wasmer/blob/main/LICENSE) [](https://crates.io/crates/wasmer-wasi)
This crate provides the necessary imports to use WASI easily from Wasmer.
WebAssembly System Interface
(WASI for short) is a modular system interface for WebAssembly. WASI
is being standardized in the WebAssembly subgroup.
Very succinctly, from the user perspective, WASI is a set of
WebAssembly module imports under a specific namespace (which
varies based on the WASI version). A program compiled for thewasm32-wasip1 target will be able to support standard I/O, file I/O,
filesystem manipulation, memory management, time, string, environment
variables, program startup etc.
Wasmer WASI is created with the aim to be fully sandboxed.
We are able to achieve that thanks to our Virtual Filesystem implementation (wasmer-vfs)
and by only allowing secure systemcalls back to the host.
Note: If you encounter any sandboxing issue please open an issue in the wasmer repo https://github.com/wasmerio/wasmer.
This crate provides the necessary API to create the imports to use
WASI easily from the Wasmer runtime, through our ImportObject API.
Supported WASI versions
| WASI version | Support |
|---|---|
wasi_unstable |
✅ |
wasi_snapshot_preview1 |
✅ |
The special Latest version points to wasi_snapshot_preview1.
Learn more about the WASI version
process
(ephemeral, snapshot, old).
Usage
Let's consider the following hello.rs Rust program:
fn main() {
println!("Hello, {:?}", std::env::args().nth(1));
}Then, let's compile it to a WebAssembly module with WASI support:
$ rustc --target wasm32-wasip1 hello.rsFinally, let's execute it with the wasmer CLI:
$ wasmer run hello.wasm Gordon
Hello, Some("Gordon")… and programmatically with the wasmer and the wasmer-wasi libraries:
use std::io::Read;
use wasmer::{Module, Store};
use wasmer_wasix::{Pipe, WasiEnv};
let wasm_path = "hello.wasm";
// Let's declare the Wasm module with the text representation.
let wasm_bytes = std::fs::read(wasm_path)?;
// Create a Store.
let mut store = Store::default();
println!("Compiling module...");
// Let's compile the Wasm module.
let module = Module::new(&store, wasm_bytes)?;
let (stdout_tx, mut stdout_rx) = Pipe::channel();
// Run the module.
WasiEnv::builder("hello")
.args(&["Gordon"])
// .env("KEY", "Value")
.stdout(Box::new(stdout_tx))
.run_with_store(module, &mut store)?;
eprintln!("Run complete - reading output");
let mut buf = String::new();
stdout_rx.read_to_string(&mut buf).unwrap();
eprintln!("Output: {buf}");Check the fully working example using
WASI.
More resources
This library is about the WASI implementation inside the Wasmer
runtime. It contains documentation about the implementation
itself. However, if you wish to learn more about WASI, here is a list
of links that may help you:
wasi-libc, WASI libc
implementation for WebAssembly programs built on top of WASI system
calls. It provides a wide array of POSIX-compatible C APIs,
including support for standard I/O, file I/O, filesystem
manipulation, memory management, time, string, environment
variables, program startup, and many other APIs,wasi-sdk, WASI-enabled
WebAssembly C/C++ toolchain, based onwasi-libc,- WASI API
documentation, - WASI C API header
file, - WASI Application Binary Interface
(ABI),
where we learn about_startand_initialize(for reactors) for example.
Overview (`tests/deprecated/README.md`)
Tests: Deprecated
In this folder we will test deprecated APIs to verify that they
still work the way it should, so users of Wasmer are happy while
transitioning to newer APIs.
As time passes and adoption of new APIs rises, tests on this folder
should start tending towards 0.
Therefore, deprecated tests are intended to be deleted on the long
term.
Overview (`tests/integration/README.md`)
Wasmer Integration tests
All Wasmer end to end integration tests live here.
We have different kind of integration tests:
CLI Integration tests
This tests check that the wasmer CLI works as it should when running it
as a Command in a shell, for each of the supported compilers.
Snapshot Tests
A snapshot test suite is located at ./cli/tests/snapshot.rs.
The file contains tests that run various Webassembly files through wasmer run.
The output is stored as snapshots in the repository.
The insta crate is used for snapshots.
Working With Snapshots
- Install the cargo-insta CLI
cargo install cargo-insta - Update snapshots:text
cd ./cli/ cargo insta test --review -- snapshot
C Integration tests
This tests verify that Wasmer wasm-c-api tests are passing for each of the
supported compilers.
Rust Integration tests
This tests verify that the wasmer API fulfill the required API that
external users use.
Overview (`tests/lib/README.md`)
Wasmer Test libraries
Here is the place where the test libraries will live.
Overview (`tests/wasmer-argus/README.md`)
wasmer-argus
Automatically test packages from the registry.
Building
If you want to use the local wasmer crate, you shall
build the project with cargo build --package wasmer-argus --features wasmer_lib.
Usage
This binary fetches packages from the graphql endpoint of a registry. By
default, it uses http://registry.wasmer.io/graphql; and the needed
authorization token is retrieved from the environment using the WASMER_TOKEN.
Users can specify the token via CLI with the appropriate flag.
This testsuite is parallelised, and the degree of parallelism available can be
specified both by CLI flag or automatically usingstd::thread::available_parallelism.
Fetch and test packages from a WebContainer registry
Usage: wasmer-argus [OPTIONS]
Options:
-r, --registry-url <REGISTRY_URL>
The GraphQL endpoint of the registry to test [default: http://registry.wasmer.io/graphql]
-b, --backend <COMPILER_BACKEND>
The backend to test the compilation against [default: singlepass] [possible values: llvm, singlepass, cranelift]
--run
Whether or not to run packages during tests
-o, --outdir <OUTDIR>
The output directory [default: /home/ecmm/sw/wasmer/wasmer/target/debug/out]
--auth-token <AUTH_TOKEN>
The authorization token needed to see packages [default: <env::WASMER_TOKEN>]
--jobs <JOBS>
The number of concurrent tests (jobs) to perform [default: 12]
-h, --help Print help
-V, --version Print versionOverview (`tests/wast/README.md`)
WebAssembly testsuite
Here is where all the .wast tests live.
Overview (`lib/wasix/tests/README.md`)
WASIX integration tests
default file system tree
We should see these four directories by default
cd ../../cli
cargo run --features compiler,cranelift -- ../wasix/tests/coreutils.wasm lsExpected:
bin
dev
etc
tmpusing /dev/stderr
This test ensures that the dev character devices are working properly, there should be two lines with blah as tee will
send it both to the console and to the file
cd ../../cli
echo blah | cargo run --features compiler,cranelift -- ../wasix/tests/coreutils.wasm tee /dev/stderrExpected:
blah
blahatomic_wait and atomic_wake syscalls
When we convert this from syscalls to native language constructs in WASM this test
needs to continue to pass.
cd ../../cli
cargo run --features compiler,cranelift,debug -- ../wasix/tests/example-condvar.wasmExpected:
condvar1 thread spawn
condvar1 thread started
condvar1 thread sleep(1sec) start
condvar loop
condvar wait
condvar1 thread sleep(1sec) end
condvar1 thread set condition
condvar1 thread notify
condvar woken
condvar parent done
condvar1 thread exit
all donecowsay
Piping to cowsay should, well.... display a cow that says something
cd ../../cli
echo blah | cargo run --features compiler,cranelift,debug -- ../wasix/tests/cowsay.wasmExpected:
______
< blah >
------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||polling and event notifications
This test makes sure the event notifications works correctly fd_event - this construct is used
in tokio in order to wake up the main IO thread that is blocked on an poll_oneoff.
cd ../../cli
cargo run --features compiler,cranelift,debug -- ../wasix/tests/example-epoll.wasmExpected:
EFD_NONBLOCK:4
success write to efd, write 8 bytes(4) at 1669077621s 935291us
success read from efd, read 8 bytes(4) at 1669077621s 937666us
success write to efd, write 8 bytes(4) at 1669077622s 937881us
success read from efd, read 8 bytes(4) at 1669077622s 938309us
success write to efd, write 8 bytes(4) at 1669077623s 939714us
success read from efd, read 8 bytes(4) at 1669077623s 940002us
success write to efd, write 8 bytes(4) at 1669077624s 941033us
success read from efd, read 8 bytes(4) at 1669077624s 941205us
success write to efd, write 8 bytes(4) at 1669077625s 943658us
success read from efd, read 8 bytes(4) at 1669077625s 943956usfork and execve
The ability to fork the current process and run a different image but retain the existing open
file handles (which is needed for stdin and stdout redirection)
cd ../../cli
cargo run --features compiler,cranelift,debug -- --use wasmer/coreutils --enable-threads ../wasix/tests/example
-execve.wasmExpected:
Main program started
execve: echo hi-from-child
hi-from-child
Child(1) exited with 0
execve: echo hi-from-parent
hi-from-parentlongjmp
longjmp is used by C programs that save and restore the stack at specific points - this functionality
is often used for exception handling
cd ../../cli
cargo run --features compiler,cranelift,debug -- --enable-threads ../wasix/tests/example-longjmp.wasmExpected:
(A1)
(B1)
(A2) r=10001
(B2) r=20001
(A3) r=10002
(B3) r=20002
(A4) r=10003Yet another longjmp implementation
This one is initiated from rust code and thus has the risk of leaking memory but uses different interfaces
cd ../../cli
cargo run --features compiler,cranelift,debug -- --enable-threads ../wasix/tests/example-stack.wasmExpected:
before long jump
after long jump [val=10]
before long jump
after long jump [val=20]fork
Simple fork example that is a crude multi-threading implementation - used by dash
cd ../../cli
cargo run --features compiler,cranelift,debug -- --enable-threads ../wasix/tests/example-fork.wasmExpected:
Parent has x = 0
Child has x = 2
Child(1) exited with 0fork and longjmp
Performs a longjmp of a stack that was recorded before the fork - this test ensures that the stacks that have
been recorded are preserved after a fork. The behavior is needed for dash
cd ../../cli
cargo run --features compiler,cranelift,debug -- --enable-threads ../wasix/tests/example-fork-longjmp.wasmExpected:
Parent has x = 0
Child has x = 2
Child(1) exited with 5multi threading
full multi-threading with shared memory and shared compiled modules
cd ../../cli
cargo run --features compiler,cranelift,debug -- --enable-threads ../wasix/tests/example-multi-threading.wasmExpected:
thread 1 started
thread 2 started
thread 3 started
thread 4 started
thread 5 started
thread 6 started
thread 7 started
thread 8 started
thread 9 started
waiting for threads
thread 1 finished
thread 2 finished
thread 3 finished
thread 4 finished
thread 5 finished
thread 6 finished
thread 7 finished
thread 8 finished
thread 9 finished
all donepipes
Uses the fd_pipe syscall to create a bidirection pipe with two file descriptors then forks
the process to write and read to this pipe.
cd ../../cli
cargo run --features compiler,cranelift,debug -- --enable-threads ../wasix/tests/example-pipe.wasmExpected:
this text should be printed by the child
this text should be printed by the parentsignals
Tests that signals can be received and processed by WASM applications
cargo run --features compiler,cranelift,debug -- --enable-threads ../wasix/tests/example-signal.wasmNote: This test requires that a signal is sent to the process asynchronously
kill -s SIGINT 16967Expected:
received SIGHUPsleep
Puts the process to sleep for 50ms
cd ../../cli
cargo run --features compiler,cranelift,debug -- --enable-threads ../wasix/tests/example-sleep.wasmExpected:
Spawning sub-processes
Uses posix_spawn to launch a sub-process and wait on it to exit
cd ../../cli
cargo run --features compiler,cranelift,debug -- --enable-threads --use wasmer/coreutils ../wasix/tests/example
-spawn.wasmExpected:
Child pid: 1
hi
Child status 0TCP client
Connects to 8.8.8.8:53 over TCP to verify TCP clients work
cd ../../cli
cargo run --features compiler,cranelift,debug -- --enable-threads ../wasix/tests/example-tcp-client.wasmExpected:
Successfully connected to server in port 53
Finished.TCP listener
Waits for a connection after listening on 127.0.0.1:7878
cd ../../cli
cargo run --features compiler,cranelift,debug -- --enable-threads ../wasix/tests/example-tcp-listener.wasmIn order to test this a curl command is needed below asynchronously and then it needs to be killed
curl 127.0.0.1:7878Expected:
Listening on 127.0.0.1:7878
Connection established!Thread local variables
Tests that thread local variables work correctly
cd ../../cli
cargo run --features compiler,cranelift,debug -- --enable-threads ../wasix/tests/example-thread-local.wasmExpected:
/* Detailed source-code truncated for AI context efficiency. */vforking
Tests that lightweight forking that does not copy the memory but retains the
open file descriptors works correctly.
cd ../../cli
cargo run --features compiler,cranelift,debug -- --enable-threads ../wasix/tests/example-vfork.wasmExpected:
Parent waiting on Child(1)
Child(1) exited with 10web server
Advanced test case that uses tokio, TCP listeners, asynchronous IO, event notifications, multi-threading
and mapped directories to serve HTTP content.
cd ../../cli
cargo run --features compiler,cranelift,debug -- --enable-threads --volume /prog/deploy/wasmer-web/public:/public ../wasix/tests/web-server.wasm -- --port 8080 --log-level traceNote: This requires that a curl command be made to the HTTP server asynchronously
john@AlienWorld:/prog/wasix-libc/examples$ curl 127.0.0.1:8080
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<meta name="Description" content="The Wasmer Shell is an browser based operating system powered by wasmer.io that integrates that allows the WebAssembly community to assembly and build browser hosted applications.">
<meta property="og:url" content="https://wasmer.sh" />
<meta property="og:title" content="wasmer.sh" />
<meta property="og:description" content="An browser based operating system powered by wasmer.io that integrates that allows the WebAssembly community to assembly and build browser hosted applications" />
<meta property="og:image" content="https://wasmer.sh/favicon.png" />
<meta property="og:type" content="website" />
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-capable" content="yes">
<link rel="stylesheet" href="xterm.css" />
<link rel="stylesheet" href="wasmer.css" />
<link rel="icon" href="/favicon.png">
<title>wasmer.sh</title>
<meta name="viewport" content="width=device-width,initial-scale=1" />
<script type="module" defer="defer" src="main.js"></script>
</head>
<body>
<canvas id="frontBuffer"></canvas>
<div id="terminal"></div>
</body>
</html>Expected:
/* Detailed source-code truncated for AI context efficiency. */Overview (`tests/lib/wast/README.md`)
This is the wasmer-wast crate, which contains an implementation of WebAssembly's
"wast" test scripting language, which is used in the
WebAssembly spec testsuite, using wasmer for execution.
Note: this project started as a fork of this crate.
Overview (`tests/wast/wasmer/README.md`)
Custom wast tests
In this directory we have created wast tests for different cases
where we want to test other scenarios than the ones offered
by the standard WebAssembly spectests.
NaN canonicalization: `nan-canonicalization.wast`
This is an extra set of tests that assure that operations with NaNs
are deterministic regardless of the environment/chipset where it executes in.
Call Indirect Spilled Stack: `call-indirect-spilledd-stack.wast`
We had an issue occurring that was making singlepass not working properly
on the WebAssembly benchmark: https://00f.net/2019/10/22/updated-webassembly-benchmark/.
This is a test case to ensure it doesn't reproduce again in the future.
Multiple Traps: `multiple-traps.wast`
This is a test assuring functions that trap can be called multiple times.
Fac: `fac.wast`
This is a simple factorial program.
Check that struct-return on the stack doesn't overflow: `stack-overflow-sret.wast`
Stack space for a structure returning function call should be allocated once up
front, not once in each call.
Divide by Zero: `divide.wast`
This is a simple test to check that a divide by zero is correctly trapped
Atomic Load: `atomic_load.wast`
This is a simple test to check that load an atomic "to far" in memory trigger a OutOfBound trap
Nested Unreachable Blocks: `nested_unreachable_blocks.wast`
This was broken at one point in our LLVM backend. Otherwise, it's nothing specific.
Overview (`lib/c-api/tests/wasm-c-api/README.md`)
WebAssembly C and C++ API
Work in progress! No docs yet.
Design Goals
Provide a "black box" API for embedding a Wasm engine in other C/C++ applications.
Be completely agnostic to VM specifics.
Non-goal: "white box" interoperability with embedder (such as combined GC instead of mere finalisation) -- much more difficult to achieve.
Allow creation of bindings for other languages through typical C foreign function interfaces.
Support a plain C API.
Stick to mostly manual memory management of interface objects.
Avoid language features that raise barrier to use.
E.g., no exceptions or post-C++11 features in C++ API.
E.g., no passing of structs by-value or post-C99 features in C API.
Achieve link-time compatibility between different implementations.
- All implementation-dependent API classes are abstract and can be instantiated through factory methods only.
Interfaces
C++ API:
See
include/wasm.hhfor interface.See
example/*.ccfor example usages.
C API:
See
include/wasm.hfor interface.See
example/*.cfor example usages.
Some random explanations:
The VM must be initialised by creating an instance of an engine (
wasm::Engine/wasm_engine_t) and is shut down by deleting it. Such an instance may only be created once per process.All runtime objects are tied to a specific store (
wasm::Store/wasm_store_t). Multiple stores can be created, but their objects cannot interact. Every store and its objects must only be accessed in a single thread.To exchange module objects between threads, create a shared module (
wasm::Shared<Module>/wasm_shared_module_t). Other objects cannot be shared in current Wasm.Vector structures (
wasm::vec<X>/wasm_x_vec_t) are lightweight abstractions of a pair of a plain array and its length. The C++ API does not usestd::vectorbecause that does not support adopting pre-existing arrays.References point to runtime objects, but may involve internal indirections, which may or may not be cached. Thus, pointer equality on
Ref*or subclasses cannot be used to compare identity of the underlying objects (Ref::eqmay be added later). However,nullptr/NULLuniquely represents null references.The API already encompasses current proposals like multiple return values and reference types, but not yet threads.
Prototype Implementation
This repo contains a prototype implementation based on V8 is in
src.- Note that this requires adding a module to V8, so it patches V8's build file.
The C API is implemented on top of the C++ API.
See
Makefilefor build recipe. Canonical steps to run examples:make v8-checkoutmake v8make all
Limitations
V8 implementation:
Currently requires patching V8 by adding a module.
Host functions (
Func::make) create a JavaScript function internally, since V8 cannot handle raw C imports yet.As a consequence, does not support multiple results in external calls or host functions.
Host functions and host globals are created through auxiliary modules constructed on the fly, to work around limitations in JS API.
Shared<Module>is currently implemented via serialisation, since V8 does not currently have direct support for cross-isolate sharing.
Other Implementations
Currently, known implementations of this API are included in
- V8 natively (both C and C++)
- Wabt (only C?)
- Wasmtime (only C?)
- Wasmer (only C, C++ coming soon)
TODO
Possible API tweaks:
Add
Ref::eq(or better, a subclassEqRef::eq) for reference equality?Add a way to return error messages from
Module::makeandModule::validate.Use
restrictin C API?Find a way to perform C callbacks through C++ without extra wrapper?
Add iterators to
vecclass?
Overview (`lib/wasix/tests/wasm_tests/README.md`)
WASIX wasm tests
This directory contains integration tests that build small WASM programs and run them directly through wasmer-wasix from Rust. Most fixtures are C or C++ programs compiled with wasixcc / wasix++.
A working installation of wasixcc is required for this suite to work. The harness expects wasixcc and wasix++ to be available on PATH.
How the suite is structured
The wasix-wasm integration test target discovers tests automatically from this
directory. Any subdirectory that contains one of these primary files is treated
as a test fixture:
build.shor other*.shprimary sourcesCargo.tomlmain.cmain.cpp*.rs
Discovery precedence within a fixture directory is:
*.shshell primary sourcesCargo.toml(full Cargo project)main.c/main.cpp*.rs(each Rust source is an independent test)
The harness builds each discovered fixture, runs the resulting main module through the WASIX runner,
and registers one test per configuration each of the enabled engines.
Primary source files can contain inline directives that define the runnable configurations,
arguments, runtime environment, stdin, expected output, expected exit status, mapped directories, prefilled files, and file checks.
The supported directives are documented in ../wasm_tests.rs.
If a fixture has more than one .sh file, each shell file is treated as a
primary source, where build.sh is the default shell source name.
Fixtures with an explicit Cargo.toml are built as full Cargo projects. Directives
can be placed in ##Directive: Args comments in the manifest.
The former tests/wasi-fyi shell suite now lives in wasi_fyi/
as Rust primary sources with inline directives.
How building works
Source fixtures are copied into a per-test build directory under wasm_tests/build/.
The harness then builds them as follows:
main.cis compiled withCC, orwasixccifCCis unset.main.cppis compiled withCXX, orwasix++ifCXXis unset.*.rsis built withcargo wasix buildusing an ephemeralCargo.tomlgenerated
in the build directory.Cargo.tomlfixtures are built withcargo wasix buildand the single binary
artifact is copied tomain.build.shand other shell primary sources are executed withbash; the
harness setsCC=wasixcc,CXX=wasix++, andWASIXCC_DISCARD_UNSUPPORTED_FLAGS=yes.
Every build must produce an executable WebAssembly output named main.
If a fixture needs compiler environment overrides, add BuildEnv directives to
the primary source, for example //#BuildEnv: WASIXCC_PIC=1 in C/C++ sources or##BuildEnv: WASIXCC_PIC=1 in shell sources.
Running the tests
These tests run through the normal wasix integration test target, so standard
Cargo and nextest filtering both work. Before running the suite, make surewasixcc is installed and available in your shell environment.
Rust fixtures also require cargo-wasix on PATH (cargo install cargo-wasix).
Single-file Rust fixtures build with two Rust toolchains by default (see theToolchains directive): wasix (cargo-wasix), which runs on every engine
except Singlepass — the WASIX toolchain emits exception-handling opcodes
Singlepass does not support — and wasip1 (rustc --target wasm32-wasip1,
nightly when the source uses #![feature(...)]), which runs on every engine.
The wasip1 variants need rustup target add wasm32-wasip1 (plus the same
target on nightly).
We do not publish the WASIX Rust toolchain for every platform yet, so thewasix variants are only collected on hosts that have one: gnu Linux on x86_64
and aarch64, and macOS on aarch64. They are skipped on musl, which has no
toolchain, and on Windows, which wasixcc does not cover either. The wasip1
variants build everywhere, so single-file Rust fixtures keep running on those
hosts.
On macOS, this suite collects and runs the LLVM variants only because Cranelift
exception-handling support is still incomplete there:
Overview (`lib/wasix/tests/wasm_tests/wasi_fyi/README.md`)
wasi-fyi fixtures
These fixtures were ported from the legacy tests/wasi-fyi shell test suite into the wasmer-wasix Rust integration harness.
Each *.rs file is a primary source discovered by the shared wasm_tests
harness. The source-level directives define per-test inputs and expectations:
Argssupplies command-line arguments.Envsupplies runtime environment variables.StdinFilesupplies stdin bytes from a fixture file.ExpectedStdoutFileandExpectedStderrFileassert exact output.ExpectedExitCodeasserts the expected process exit code.
Common runner setup lives in wasi-fyi.config and is included explicitly withAbstractConfigFile.
The original fixture license is preserved in LICENSE.
Overview (`lib/wasix/tests/wasm_tests/wasi_fyi/test_fs/README.md`)
Test FS
This is a test "file system" used in some of the WASI integration tests.
It's just a bunch of files in a tree.
If you make changes here, please regenerate the tests with make wasitests!
The contents of temp are deleted before each run. If you want to test making or mutating files, do it in that sub directory.
Overview (`lib/wasix/tests/wasm_tests/wasi_wast/test_fs/README.md`)
Test FS
This is a test "file system" used in some of the WASI integration tests.
It's just a bunch of files in a tree.
If you make changes here, update the expected output fixtures in the parentwasi_wast directory.
The contents of temp are deleted before each run. If you want to test making or mutating files, do it in that sub directory.
Overview (`tests/integration/cli/tests/packages/js/README.md`)
This is a simple Javascript Service Worker server template running with WinterJS.
This starter's full tutorial is available here.
Usage
Modify the logic of your the Javascript worker in the src/index.js file.
You can run the JS Service Worker locally with (check out the Wasmer install guide):
wasmer run . --netOpen http://localhost:8080 with your browser to see the worker working!
Deploy on Wasmer Edge
The easiest way to deploy your Javascript Worker is to use the Wasmer Edge.
Live example: https://wasmer-js-worker-starter.wasmer.app/
wasmer deployOverview (`lib/wasix/tests/wasm_tests/wasi_fyi/test_fs/hamlet/README.md`)
Hamlet split in to acts and scenes
From: http://shakespeare.mit.edu/hamlet/full.html
Overview (`lib/wasix/tests/wasm_tests/wasi_wast/test_fs/hamlet/README.md`)
Hamlet split in to acts and scenes
From: http://shakespeare.mit.edu/hamlet/full.html
ARCHITECTURE (`docs/ARCHITECTURE.md`)
Repository Architecture
This document maps the workspace, one crate per concern. The workspace
holds tens of crates; the full listing is the members section of the
root Cargo.toml. The table below covers the paths you
will touch most:
| Path | Content |
|---|---|
lib/api |
Public wasmer crate. Flavors: sys (native, default), v8, js. |
lib/cli |
CLI crate wasmer-cli. Binaries: wasmer, wasmer-headless. |
lib/compiler |
Compiler framework and traits. |
lib/compiler-{singlepass,cranelift,llvm} |
The three compiler backends. |
lib/vm |
Low-level VM runtime. |
lib/wasix |
The WASIX implementation (syscalls, processes, threads). |
lib/journal |
Snapshot and restore support. See journal.md. |
lib/virtual-fs, lib/virtual-net, lib/virtual-io |
Host abstraction layers. |
lib/c-api |
C API (cdylib named wasmer). |
lib/backend-api |
GraphQL client for the Wasmer registry. |
lib/config, lib/package |
wasmer.toml parsing and webc packaging. |
tests/compilers |
Integration tests (wast.rs, traps.rs, issues.rs, more). |
tests/wast/{spec,wasmer} |
WAST test files. spec is a submodule. |
The root crate is a meta-crate.
Submodules
Three submodules: tests/wast/spec, lib/napi, wasmer-test-files.
For initialization and working with the different crates + submodules, see BUILD.md
ATTRIBUTIONS (`docs/ATTRIBUTIONS.md`)
Wasmer Attributions
Wasmer is a community effort and makes use of code from various other
projects ❤️.
Listed below are notable sections of code that are licensed
from other projects and the relevant license of those projects.
These are the projects that were used as inspiration and/or that we are using code from.
Each of the subcrates we have an Acknowledgements section with more details.
Projects:
- Emscripten: for emtests test sources to ensure compatibility - LICENSE
- Nebulet: as the base for creating a great Rust WebAssembly runtime - LICENSE
- WAVM: for their great integration and testing framework - LICENSE
- wasmtime: for their API and internal documentation, as well as some internal implementations - LICENSE
- WebAssembly spec: for the spectests implementation
🙏 Please let us know if you believe there is an error or omission in
this list and we will correct.
Licenses
Nebulet
MIT License
Copyright (c) 2018
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.WAVM
/* Detailed source-code truncated for AI context efficiency. */Greenwasm
/* Detailed source-code truncated for AI context efficiency. */Wasmtime
/* Detailed source-code truncated for AI context efficiency. */Emscripten
/* Detailed source-code truncated for AI context efficiency. */Zlib
version 1.3.1, January 22nd, 2024
Copyright (C) 1995-2024 Jean-loup Gailly and Mark Adler
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
Jean-loup Gailly Mark Adler
[email protected] [email protected]bzip2-1.0.6
/* Detailed source-code truncated for AI context efficiency. */BUILD (`docs/BUILD.md`)
Building Wasmer from Source
Installing Rustup
Wasmer supports building to the latest 3 stable releases, but pins
to one specific one at the time. rustup selects it automatically. See
rust-toolchain.toml for the current pin.
The easiest way to install Rust on your system is via Rustup. To get Rustup on Linux and macOS, you can run the following:
curl https://sh.rustup.rs -sSf | sh[!NOTE]
To install Rust on Windows, download and run rustup-init.exe, then follow the on-screen instructions.
Installing Additional Dependencies
Linux
Linux is fully supported by Wasmer. WASI(x) is also fully supported. Users
building from source can enable the LLVM backend following the instruction in
the dedicated section below and installing LLVM version 22. To install it,
refer to LLVM's download
page or
check your distro's package manager.
macOS
macOS is fully supported by Wasmer. WASI(x) is also fully supported. Users
building from source can enable the LLVM backend following the instruction in
the dedicated section below and installing LLVM version 22. To install it on
macOS, you can use homebrew: brew install llvm@22.
Windows
Windows is fully supported by Wasmer. WASI(x) is also fully supported.
- Install Visual Studio
- Install Rust for Windows
- Install Git for Windows. Allow it to add
git.exeto your PATH (default settings for the installer are fine). - (optional) Install LLVM 22.1
Building the Wasmer Runtime
Wasmer is built with Cargo, the Rust package manager.
For reproducible builds, set WASMER_REPRODUCIBLE_BUILD=1 in the build
environment. This removes the build timestamp from wasmer --version -v
by omitting the verbose commit-date: line.
First, let's clone Wasmer along with its submodules:
git clone --recursive https://github.com/wasmerio/wasmer.git
cd wasmerIn an existing clone, initialize the submodules withgit submodule update --init --recursive.
Wasmer supports different backends at the moment: singlepass, cranelift, LLVM and V8.
Singlepass Compiler
The Singlepass compiler works on Linux, Darwin and Windows systems on amd64
platforms and on Linux and Darwin systems on aarch64 platforms. Currently, it
doesn't work on RISC-V or loongarch64. On system in which it can be used it
is enabled by default.
You can build Wasmer by running this command in the root of the repo:
make build-wasmerNote: you should see singlepass appear in the Enabled Compilers: ... message in the console.
You may disable the Singlepass backend with the ENABLE_SINGLEPASS=0 environment
variable, and force its enabling with ENABLE_SINGLEPASS=1.
Cranelift Compiler
The Cranelift compiler will work if you are on a X86 or ARM machine. On system
in which it can be used it is enabled by default.
You can build Wasmer by running this command in the root of the repo:
make build-wasmerNote: you should see cranelift appear in the Enabled Compilers: ... message in the console.
You may disable the Cranelift backend with the ENABLE_CRANELIFT=0 environment
variable, and force its enabling with ENABLE_CRANELIFT=1.
LLVM Compiler
If you want support for the Wasmer LLVM compiler, then you will also need to:
- Ensure that LLVM 22 (>=22.1.x) is installed on your system. The backend
needs LLVM 22 exactly; any other version silently disables it — read theEnabled Compilers:banner. The errorDidn't find usable system-wide LLVMmeans LLVM 22 is missing.- You can refer to LLVM install instructions
- You can also download and use a prebuilt LLVM binary
- In case
llvm-config-22is not on PATH, set the correct environment variable
for LLVM to access: For example, the environment variable for LLVM 22.1.x
would be:LLVM_SYS_221_PREFIX=/path/to/unpacked/llvm-22.1
And create a Wasmer release
make build-wasmerNote: you should see this in the console:Enabled Compilers: llvm
You may disable the LLVM compiler with export ENABLE_LLVM=0.
V8
To enable the backend, you can set the according ENABLE_=1
flag at build time. The build script itself will download the necessary
libraries at build time.
Note, however, that these backends are not supported on all the platforms that
Wasmer can run on.
ENABLE_V8=1 make build-wasmerAll Compilers
Once you have LLVM and Rust, you can just run:
make build-wasmerNote: you should see this in the console:Enabled Compilers: singlepass cranelift llvm
Iterating During Development
For fast iteration, run make check, or build one crate:
cargo build -p wasmer-cli --features craneliftmake build-wasmer-debug builds a debug binary with tokio-console support.
Read the Enabled Compilers: banner that each make target prints. The
Makefile silently omits backends it cannot detect. V8 is never
autodetected.
The wasix-libc sysroot and Rust toolchain pins for CI live in.github/ci-constants.env.
[!CAUTION]
Do not build withcargo build --workspace --features.
Workspace-level features do not reach subcrates. The result is a headless
binary that cannot compile Wasm. Use-p wasmer-clior the Makefile.
Running Your Wasmer Binary
Once you run the make build-wasmer command, you will have a new binary ready to be used!
./target/release/wasmer quickjs.wasmBuilding Wasmer C-API from Source
Wasmer provides a pre-compiled version for the C-API on its release page.
However, you can also compile the shared library from source:
make build-capiThis will generate the shared library (depending on your system):
- Windows:
target/release/libwasmer_c_api.dll - macOS:
target/release/libwasmer_c_api.dylib - Linux:
target/release/libwasmer_c_api.so
If you want to generate the library and headers for using them easily, you can execute:
make package-capiThis command will generate a package directory, that you can then use easily in the Wasmer C API examples.
package/
lib/
libwasmer.so
include/
wasm.h
wasmer.h[!IMPORTANT]
By default, the Wasmer C API shared library will include all the backends available in the system where is built.
Defaulting tocraneliftif available.You can generate the C-API for a specific compiler and engine with:
make build-capi-{ENGINE}
CONTRIBUTING (`docs/CONTRIBUTING.md`)
How to Contribute to Wasmer
Thank you for your interest in contributing to Wasmer. This document
outlines the expectations for issues and pull requests.
Issues & Feature Requests
Please use the issue template and provide a failing example if possible to
help us recreate the issue.
[!WARNING]
Do not fix a security vulnerability in a public PR. Embargoed work goes
through the private process in SECURITY.md. A public fix
before disclosure exposes users.
Code Style
Sparse "why" comments. Short single-responsibility functions.
Lint and Format
CI rejects lint and format failures. Run before you push:
make lintThe lint target in the Makefile defines exactly what
runs. To apply clippy fixes in bulk:
cargo clippy --all --exclude wasmer-swift --locked --fix --allow-dirty -- -D clippy::allcargo fmt does not cover lib/wasix/tests/wasm_tests. CI formats those
files with rustfmt --edition 2024 directly.
Pull Requests
For large changes, open a GitHub issue first to ensure we can accept the
change once it is ready.
- Title format is conventional-commit style with crate or area scopes:
fix(Singlepass): ...,feat(wasix): ...,feat!: ...for breaking
changes,chore: ...,deps: .... - PRs are squash-merged to
main. The PR template has one# Description
section. - Before you submit:
make lint, thencargo testin the crates you
touched, then a build of the CLI. - Do not hand-edit
CHANGELOG.mdor crate versions. Releases generate
both (see dev/release.md). - macOS and musl CI jobs run on a PR only when the PR has the
macosormusllabel. If your change touches platform code, add the label. - Do not commit a submodule pointer bump in an unrelated PR.
Common Build Issues
LLVM Dependency
Didn't find usable system-wide LLVM means LLVM 22 is missing. Either
install it or build with ENABLE_LLVM=0. See
Building Wasmer from Source for installation
instructions.
PACKAGING (`docs/PACKAGING.md`)
Wasmer OS distro packaging notes
Wasmer is written in Rust. To build Wasmer, where possible, do not
directly invokecargo, but use the suppliedMakefileFor packaging purposes, use the provided
wasmer-full-source.tar.gz,
which includes all required submodules.Wasmer provides several compilers and the
Makefileautodetects
when compilers can be compiled and/or installed. Set the environment
variablesENABLE_{CRANELIFT,LLVM,SINGLEPASS}=1to force compiler
to be build or to fail trying, e.g:sh$ ENABLE_LLVM=1 make build-wasmermake installrespectsDESTDIR, butprefixmust be configured
withWASMER_INSTALL_PREFIX. Note thatDESTDIRmust includeWASMER_INSTALL_PREFIX, e.g.:shexport WASMER_INSTALL_PREFIX=/usr make DESTDIR=/tmp/staging/usr make installIn case you must build/install directly with
cargo, make sure to
enable at least one compiler feature, like e.g.--features cranelift,- Beware that compiling with
cargo build --workspace --features …
will not enable features on the subcrates in the workspace and
result in a headless Wasmer binary that can not compile Wasm files
directly.
- Beware that compiling with
For reproducible builds, set
WASMER_REPRODUCIBLE_BUILD=1in the
build environment. This strips the build timestamp fromwasmer --version -vby omitting the verbosecommit-date:line,
which is useful for distribution packaging.If you split the package into several subpackages:
The
wasmer-headlessCLI contains a subset of thewasmer's functionalities
and should only be packaged when splitting — it must be built
explicitly with:sh$ make build-wasmer-headless-minimal install-wasmer-headless-minimallibwasmer, containinglibwasmer.so*,libwasmer-dev, containing the header files and a.pcfile,libwasmer-static, containinglibwasmer.a.
The Wasmer distro packaging story is still in its infancy, so feedback is very welcome.
Miscellaneous: binfmt_misc
Wasmer can be registered as a binfmt interpreter for wasm binaries.
An example systemd .service is included here.
Please consider statically linking the wasmer binary so that this capability is also available in mount namespaces.
RISCV (`docs/RISCV.md`)
Current state of the RISCV support
Only Cranelift and LLVM compiler are supported.
Singlepass can be done, but no resources are allocated on this task for now.
Both LLVM and Cranelift support are quite new, and so it is expected to have a few things not working well.
LLVM code needs a hack to force the ABI to "lp64d", and some tested with function & float/double values are still not working correctly and have be disable for now.
On Cranelift, SIMD is not supported as the CPU doesn't have official SIMD/Vector extension for now, and no Workaround is in place.
Test have be conducted on actual hardware, with a Vision Five 2 board running Debian. Some previous tests have also be done on a Vison Five 1 running Fedora (with LLVM only).
SECURITY (`docs/SECURITY.md`)
Security Policy
Supported Versions
The table below summarizes which versions are still supported, and which aren't.
| Version | Supported |
|---|---|
| 0.x | ❌ |
| 1.x | ❌ |
| 2.x | ❌ |
| 3.x | ❌ |
| 4.x | ❌ |
| 5.x | ❌ |
| 6.x | ✅ |
| 7.x | ✅ |
Reporting a Vulnerability
The Wasmer team and community take security bugs in Wasmer seriously.
We appreciate your efforts to responsibly disclose your findings, and will make every effort to acknowledge your contributions.
To report a security issue, email [email protected] or
[email protected] and include the word "SECURITY" in the subject line.
The Wasmer team will send a response indicating the next steps in handling your report.
After the initial reply to your report, the security team will keep you informed of the progress towards a fix and full announcement, and may ask for additional information or guidance.
TEST (`docs/TEST.md`)
Testing
Thanks to the WebAssembly spec tests
we can ensure 100% compatibility with the WebAssembly spec test suite.
Run the full local suite with make test (needs cargo-nextest;make require-nextest installs it). It automatically detects the
compilers available on your system. Follow the
Building from Source guide to prepare your system with the
requirements for each backend.
The Makefile lists the individual test targets and their
purpose: the WAST spec tests per backend, the CLI, the examples, the
C API, and more.
It is also possible to test specific parts. One crate:
cargo test -p wasmer-wasix --features sysOne test by name filter:
cargo test --release --tests --features cranelift -- cranelift::spec::simdSkipping Tests
If a test fails only on one backend or platform, add a line totests/ignores.txt with a reason (<compiler> <test> # reason). Do not
chase Singlepass failures for SIMD, relaxed SIMD, exception handling, or
wide arithmetic. Singlepass does not support these proposals.
To debug a failing WAST test, see
AGENTS.md.
WASIX Guest-Side Tests
WASIX guest-side tests live in lib/wasix/tests/wasm_tests/. They needwasixcc and cargo-wasix on PATH. Fixture directives are documented inlib/wasix/tests/wasm_tests.rs.
CI Coverage Gaps
macOS and musl CI jobs run on a PR only when the PR carries the macos ormusl label (see CONTRIBUTING.md). A PR can pass CI
and still break main on those platforms.
Journal (`docs/journal.md`)
WASM Journal Functionality
Wasmer now supports journals for the state of a WASM process. This gives the ability
to persist changes made to the temporary file system and to save and store snapshots
of the running process.
The journal file is a linear history of events that occurred when the process was
running that if replayed will bring the process made to a discrete and deterministic
state.
Journal files can be concatenated, compacted and filtered to change the discrete state.
These journals are maintained in a consistent and durable way thus ensuring that
failures of the system while the process is running does not corrupt the journal.
Snapshot Triggers
The journal will record state changes to the sandbox built around the WASM process as
it runs however it may be important to certain use-cases to take explicit snapshot
restoration points in the journal at key points that make sense.
When a snapshot is triggered all the running threads of the process are paused and
the state of the WASM memory and thread stacks are recorded into the journal so that
they can be restored.
In order to use the snapshot functionality the WASM process must be compiled with
the asyncify modifications, this can be done using the wasm-opt tool.
Note: If a process does not have the asyncify modifications you can still use
the journal functionality for recording the file system and WASM memory state
however the stacks of the threads will be omitted meaning a restoration will
restart the main thread.
Various triggers are possible that will cause a snapshot to be taken at a specific
point in time, these are as follows:
On Idle
Triggered when all the threads in the process go into an idle state. This trigger
is useful to take snapshots at convenient moments without causing unnecessary overhead.
For processes that have TTY/STDIN input this is particularly useful.
On FirstListen
Triggered when a listen syscall is invoked on a socket. This can be an important
milestone to take a snapshot when one wants to speed up the boot time of a WASM process
up to the moment where it is ready to accept requests.
On FirstStdin
Triggered when the process reads stdin for the first time. This can be useful to
speed up the boot time of a WASM process.
On FirstEnviron
Triggered when the process reads an environment variable for the first time. This can
be useful to speed up the boot time of a CGI WASM process which reads the environment
variables to parse the request that it must execute.
On Timer Interval
Triggered periodically based on a timer (default 10 seconds) which can be specified
using the journal-interval option. This can be useful for asynchronous replication
of a WASM process from one machine to another with a particular lag latency.
On Sigint (Ctrl+C)
Issued if the user sends an interrupt signal (Ctrl + C).
On Sigalrm
Alarm clock signal (used for timers)
(see man alarm)
On Sigtstp
The SIGTSTP signal is sent to a process by its controlling terminal to request it to stop
temporarily. It is commonly initiated by the user pressing Ctrl-Z.
On Sigstop
The SIGSTOP signal instructs the operating system to stop a process for later resumption
On Non Deterministic Call
When a non-deterministic call is made from WASM process to the outside world (i.e. it reaches
out of the sandbox)
Limitations
- The WASM process that wish to record the state of the threads must have had the
asyncify
post processing step applied to the binary (seewasm-opt). - Taking a snapshot can consume large amounts of memory while its processing.
- Snapshots are not instant and have overhead when generating.
- The layout of the memory must be known by the runtime in order to take snapshots.
Design
On startup if the restore journal file is specified then the runtime will restore the
state of the WASM process by reading and processing the log entries in the snapshot
journal. This restoration will bring the memory and the thread stacks back to a previous
point in time and then resume all the threads.
When a trigger occurs a new journal will be taken of the WASM process which will
take the following steps:
- Pause all threads
- Capture the stack of each thread
- Write the thread state to the journal
- Write the memory (excluding stacks) to the journal
- Resume execution.
The implementation is currently able to save and restore the following:
- WASM Memory
- Stack memory
- Call stack
- Open sockets
- Open files
- Terminal text
Journal Capturer Implementations
Log File Journal
Writes the log events to a linear log file on the local file system
as they are received by the trait. Log files can be concatenated
together to make larger log files.
Unsupported Journal
The default implementation does not support snapshots and will error
out if an attempt is made to send it events. Using the unsupported
capturer as a restoration point will restore nothing but will not
error out.
Compacting Journal
Deduplicates memory and stacks to reduce the number of volume of
log events sent to its inner capturer. Compacting the events occurs
in line as the events are generated
Filtered Journal
Filters out a specific set of log events and drops the rest, this
capturer can be useful for restoring to a previous call point but
retaining the memory changes (e.g. WCGI runner).
Improvements
Migration To 1.0.0 (`docs/migration_to_1.0.0.md`)
Migrating from Wasmer 0.x to Wasmer 1.0.0
Wasmer 1.0.0 is getting ready for a full release and is our primary focus. This document will
describe the differences between Wasmer 0.x and Wasmer 1.0.0 and provide examples
to make migrating to the new API as simple as possible.
Table of Contents
Rationale for changes in 1.0.0
Wasmer 0.x was great but as the Wasm community and standards evolve we felt the need to make Wasmer also follow these
changes.
Wasmer 1.x is what we think a necessary rewrite of a big part of the project to make it more future-proof.
This version introduces many new features and makes using Wasmer more natural. We did a hard work making it as close
to the standard API as possible while always providing good performances, flexibility and stability.
The rewrite of the Wasmer Runtime also comes with a rewrite of the languages integrations to achieve the same goals:
providing a clearer API and improving the feature set.
In this document you will discover the major changes between Wasmer 0.x and Wasmer 1.x by highlighting how to use the
new Rust API.
How to use Wasmer 1.0.0
Installing Wasmer CLI
See wasmer.io for installation instructions.
If you already have wasmer installed, run wasmer self-update.
Install the latest versions of Wasmer with wasmer-nightly or by following the steps described in the
documentation: Getting Started.
Using Wasmer 1.0.0
The CLI interface for Wasmer 1.0.0 is mostly the same as it was in Wasmer 0.x.
One difference is that rather than specifying the compiler with --backend=cranelift,
in Wasmer 1.0.0 we prefer using the name of the backend as a flag directly,
for example: --cranelift.
The top-level crates that users will usually interface with are:
- wasmer - Wasmer's core runtime API
- wasmer-wasi - Wasmer's WASI implementation
- wasmer-emscripten - Wasmer's Emscripten implementation
- TODO:
See the examples to find out how to do specific things in Wasmer 1.0.0.
Project Structure
The figure above shows the core Wasmer crates and their dependencies with transitive dependencies deduplicated.
Wasmer 1.0.0 has two core architectural abstractions: engines and compilers.
An engine is a system that processes Wasm with a compiler and prepares it to be executed.
A compiler is a system that translates Wasm into a format that can be understood
more directly by a real computer: machine code.
For example, in the examples you'll see that we are using the JIT engine and the Cranelift compiler. The JIT engine
will generate machine code at runtime, using Cranelift, and then execute it.
For most uses, users will primarily use the wasmer crate directly, perhaps with one of our
provided ABIs such as wasmer-wasi. However, for users that need finer grained control over
the behavior of wasmer, other crates such as wasmer-compiler and wasmer-engine may be used
to implement custom compilers and engines respectively.
Differences
Instantiating modules
With Wasmer 0.x, instantiating a module was a matter of calling wasmer::compiler::compile and then callinginstantiate on the compiled module.
While simple, this did not give you full-control over Wasmer's configuration. For example, choosing another compiler
was not straightforward.
With Wasmer 1.x, we changed this part and made the API look more like how Wasmer works internally to give you more
control:
- let module = compile(&wasm_bytes[..])?;
+ let engine = JIT::new(Cranelift::default()).engine();
+ let store = Store::new(&engine);
+ let module = Module::new(&store, wasm_bytes)?;
- let instance = module.instantiate(&imports)?;
+ let instance = Instance::new(&module, &import_object)?;Note that we did not cover how to create the import object here. This is because this part works the same as it used to
with Wasmer 0.x.
To get more information on how instantiation now works, have a look at the dedicated example
Passing host functions
With Wasmer 0.x passing host functions to the guest was primarily done using the func! macro or by directly usingFunc::new or DynamicFunc::new.
In Wasmer 1.0 the equivalent of Func::new is Function::new_native /Function::new_native_with_env and the equivalent of DynamicFunc::new
is Function::new / Function::new_with_env.
Given we have a function like:
fn sum(a: i32, b: i32) -> i32 {
a + b
}We want to import this function in the guest module, let's have a look at how it differs between Wasmer 0.x and
Wasmer 1.x:
let import_object = imports! {
"env" => {
- "sum" => func!(sum),
+ "sum" => Function::new_native(&store, sum),
}
}The above example illustrates how to import what we call "native functions". There were already available in Wasmer
0.x through the func! macro or with Func::new.
There is a second flavor for imported functions: dynamic functions. With Wasmer 0.x you would have created such a
function using DynamicFunc::new, here is how it's done with Wasmer 1.x:
let sum_signature = FunctionType::new(vec![Type::I32, Type::I32], vec![Type::I32]);
let sum = Function::new(&store, &sum_signature, |args| {
let result = args[0].unwrap_I32() + args[1].unwrap_i32();
Ok(vec![Value::I32(result)])
});Both examples address different needs and have their own pros and cons. We encourage you to have a look at the
dedicated example: Exposing host functions.
Note that having this API for functions now looks more like the other entities APIs: globals, memories, tables. Here is
a quick example introducing each of them: Imports & Exports
Accessing the environment as a host function
With Wasmer 0.x each function had its own vm::Ctx. This was your entrypoint to the module internals and allowed
access to the context of the currently running instance.
With Wasmer 1.0.0 this was changed to provide a simpler yet powerful API.
Let's see an example where we want to have access to the module memory. Here is how that changed from 0.x to 1.0.0:
+ #[derive(WasmerEnv, Clone, Default)]
+ struct MyEnv {
+ #[wasmer(export)]
+ memory: LazyInit<Memory>,
+ }
+ let env = MyEnv::default();
+
- let get_at = |ctx: &mut vm::Ctx, ptr: WasmPtr<u8, Array>, len: u32| {
+ let get_at = |env: &MyEnv, ptr: WasmPtr<u8, Array>, len: u32| {
- let mem_desc = ctx.memory(0);
- let mem = mem_desc.deref();
+ let mem = env.memory_ref().unwrap();
println!("Memory: {:?}", mem);
let string = ptr.get_utf8_string(mem, len).unwrap();
println!("string: {}", string);
};
let import_object = imports! {
"env" => {
- "get_at" => func!(get_at),
+ "get_at" => Function::new_native_with_env(&store, env.clone(), get_at),
}
};
- let instance = instantiate(wasm_bytes, &import_object)?;
+ let instance = Instance::new(&wasm_bytes, &import_object)?;Here we have a module which provides one exported function: get. Each time we call this function it will in turn
call our imported function get_at.
The get_at function is responsible for reading the guest module-s memory through the vm::Ctx.
With Wasmer 1.0.0 (where the vm::Ctx does not exist anymore) we can achieve the same result with something more
natural: we only use imports and exports to read from the memory and write to it.
However in order to provide an easy to use interface, we now have a trait
that can be implemented with a derive macro: WasmerEnv. We must make our
env types implement WasmerEnv and Clone. We mark an internal field
wrapped with LazyInit with #[wasmer(export)] to indicate that the type
should be found in the Wasm exports with the name of the field
("memory"). The derive macro then generates helper functions such asmemory_ref on the type for easy access to these fields.
See the WasmerEnv
docs for more information.
Take a look at the following examples to get more details:
The other thing where vm::Ctx was useful was to pass data from and to host functions. This has also been made simpler
with Wasmer 1.x:
let shared_counter: Arc<RefCell<i32>> = Arc::new(RefCell::new(0));
#[derive(WasmerEnv, Clone)]
struct Env {
counter: Arc<RefCell<i32>>,
}
fn get_counter(env: &Env) -> i32 {
*env.counter.borrow()
}
let get_counter_func = Function::new_native_with_env(
&store,
Env { counter: shared_counter.clone() },
get_counter
);A dedicated example describes how to use this feature: Exposing host functions.
Error handling
Handling errors with Wasmer 0.x was a bit hard, especially, the wasmer_runtime::error::RuntimeError. It was rather
complex: it had many variants that you had to handle when pattern matching results. This has been made way simpler with
Wasmer 1.0.0:
// Retrieve the `get` function from module's exports and then call it
let result = get.call(0, 13);
match result {
- Err(RuntimeError::InvokeError(InvokeError::TrapCode { .. })) => {
- // ...
- }
- Err(RuntimeError::InvokeError(InvokeError::FailedWithNoError)) => {
- // ...
- }
- Err(RuntimeError::InvokeError(InvokeError::UnknownTrap { .. })) => {
- // ...
- }
- Err(RuntimeError::InvokeError(InvokeError::UnknownTrapCode { .. })) => {
- // ...
- }
- Err(RuntimeError::InvokeError(InvokeError::EarlyTrap(_))) => {
- // ...
- }
- Err(RuntimeError::InvokeError(InvokeError::Breakpoint(_))) => {
- // ...
- }
- Err(RuntimeError::Metering(_)) => {
- // ...
- }
- Err(RuntimeError::InstanceImage(_)) => {
- // ...
- }
- Err(RuntimeError::User(_)) => {
- // ...
- }
+ Error(e) => {
+ println!("Error caught from `div_by_zero`: {}", e.message());
+
+ let frames = e.trace();
+ let frames_len = frames.len();
+
+ // ...
+ }
Ok(_) => {
// ...
},
}As you can see here, handling errors is really easy now! You may find the following examples useful to get more familiar
with this topic:
Note that with Wasmer 1.0.0, each function that is part of the API has its own kind of error. For example:
- Instantiating a module may return
InstantiationErrors; - Getting exports from the guest module may return
ExportErrors; - Calling an exported function may return
RuntimeErrors; - ...
Caching modules
You may be aware Wasmer, since 0.x, allows you to cache compiled module so that further executions of your program
will be faster.
Because caching may bring a significant boost when running Wasm modules we wanted to make it easier to use with
Wasmer 1.0.0.
With Wasmer 0.x you had to handle the whole caching process inside your program's code. With Wasmer 1.0.0
you'll be able to delegate most of the work to Wasmer:
- let artifact = module.cache().unwrap();
- let bytes = artifact.serialize().unwrap();
-
- let path = "module_cached.so";
- fs::write(path, bytes).unwrap();
+ module.serialize_to_file(path)?;
- let mut file = File::open(path).unwrap();
- let cached_bytes = &mut vec![];
- file.read_to_end(cached_bytes);
- drop(file);
-
- let cached_artifact = Artifact::deserialize(&cached_bytes).unwrap();
- let cached_module = unsafe { load_cache_with(cached_artifact, &default_compiler()) }.unwrap();
+ let cached_module = unsafe { Module::deserialize_from_file(&store, path) }?;Migration To 3.0.0 (`docs/migration_to_3.0.0.md`)
Migrating from Wasmer 2.x to Wasmer 3.0.0
This document will describe the differences between Wasmer 2.x and Wasmer 3.0.0
and provide examples to make migrating to the new API as simple as possible.
Table of Contents
Rationale for changes in 3.0.0
This version introduces the following changes to make the Wasmer API more ergonomic and safe:
ImportsObjectand the traitsResolver,NamedResolver, etc have been removed and replaced with a single simple typeImports. This reduces the complexity of setting up anInstance. The helper macroimports!can still be used.- The
Storewill keep track of all memory and functions used, removing old tracking and Weak/Strong pointer usage. Every function and memory that can be defined is associated to a specificStore, and cannot be mixed with anotherStore NativeFunchas been renamed toTypedFunction, accordingly the following functions have been renamed:Function::native(…)→Function::typed(…)Function::new_native(…)→Function::new_typed(…)Function::new_native_with_env(…)→Function::new_typed_with_env(…)
The previous variants still exist in order to support the migration, but they have been deprecated.
WasmerEnvand associated traits and macro have been removed. To use a function environment, you will need to create aFunctionEnvobject and pass it along when you construct the function. For convenience, these functions also exist in a variant without the environment for simpler use cases that don't need it. For the variants with the environment, it can be retrieved from the first argument of the function. Because theWasmerEnvand all helpers don't exists anymore, you have to import memory yourself, there isn't any per instance initialisation automatically done anymore. It's especially important in wasi use withWasiEnv.Envcan be accessed from aFunctionEnvMut<'_, WasiEnv>usingFunctionEnvMut::data()orFunctionEnvMut::data_mut().- The
Engines API has been simplified, Instead of the user choosing and setting up an engine explicitly, everything now uses a single engine. All functionalities of theuniversal,staticlibanddylibengines should be available in this new engine unless explicitly stated as unsupported. - Loupe has been removed. Memory inspection should be done manually
How to use Wasmer 3.0.0
Installing Wasmer CLI
See wasmer.io for installation instructions.
If you already have wasmer installed, run wasmer self-update.
Install the latest versions of Wasmer with wasmer-nightly or by following the
steps described in the documentation: Getting Started.
Using Wasmer 3.0.0
One of the main changes in 3.0.0 is that Store now owns all WebAssembly objects; thus exports like a Memory are merely handles to the actual memory object inside the store. To read/write any such value you will always need a Store reference.
If you define your own function, when the function is called it will hence need a reference to the store in order to access WebAssembly objects. This is achieved by the StoreRef<'_> and StoreMut<'_> types, which borrow from the store and provide access to its data. Furthermore, to prevent borrowing issues you can create new StoreRef and StoreMuts whenever you need to pass one at another function. This is done with the AsStoreRef, AsStoreMut traits.
See the examples to find out how to do specific things in Wasmer 3.0.0.
Project Structure
A lot of types were moved to wasmer-types crate. There are no engine crates anymore; all the logic is included in wasmer-compiler.
Differences
`WasmerEnv` is removed in favor of `FunctionEnv`
WasmerEnv has been removed in Wasmer 3.0 in favor of FunctionEnv, which is now shareable automatically between functions without requiring the environment to be cloneable.
let my_counter = 0_i32;
let env = FunctionEnv::new(&mut store, my_counter);Note: Any type can be passed as the environment: (Nota bene the passed type T must implement the Any trait, that is, any type which contains a non-'static reference.)
struct Env {
counter: i32,
}
let env = FunctionEnv::new(&mut store, Env {counter: 0});Here's how the code depending on WasmerEnv should evolve:
Before
#[derive(wasmer::WasmerEnv, Clone)]
pub struct MyEnv {
#[wasmer(export)]
pub memory: wasmer::LazyInit<Memory>,
#[wasmer(export(name = "__alloc"))]
pub alloc_guest_memory: LazyInit<NativeFunc<u32, i32>>,
pub multiply_by: u32,
}
let my_env = MyEnv {
memory: Default::default(),
alloc_guest_memory: Default::default(),
multiply_by: 10,
};
let instance = Instance::new(&module, &imports);After
pub struct MyEnv {
pub memory: Option<Memory>,
pub alloc_guest_memory: Option<TypedFunction<i32, i32>>,
pub multiply_by: u32,
}
let env = FunctionEnv::new(&mut store, MyEnv {
memory: None,
alloc_guest_memory: None,
multiply_by: 10,
});
let instance = Instance::new(&mut store, &module, &imports)?;
let mut env_mut = env.into_mut(&mut store); // change to a FunctionEnvMut
let (mut data_mut, mut store_mut) = env_mut.data_and_store_mut(); // grab data and a new store_mut
data_mut.memory = Some(instance.exports.get_memory("memory")?.clone());
data_mut.alloc_guest_memory = Some(instance.exports.get_typed_function(&mut store_mut, "__alloc")?);New `MemoryView` API (preparation for shared memory)
Reading from memory has slightly changed compared to 2.x:
// 2.x
let memory = instance.exports.get_memory("mem")?;
println!("Memory size (pages) {:?}", memory.size());
println!("Memory size (bytes) {:?}", memory.data_size());
let load = instance
.exports
.get_native_function::<(), (WasmPtr<u8, Array>, i32)>("load")?;
let (ptr, length) = load.call(&mut store)?;
let str = ptr.get_utf8_string(memory, length as u32).unwrap();
println!("Memory contents: {:?}", str);// 3.x
let memory = instance.exports.get_memory("mem")?;
let memory_view = memory.view(&store);
println!("Memory size (pages) {:?}", memory_view.size());
println!("Memory size (bytes) {:?}", memory_view.data_size());
let load: TypedFunction<(), (WasmPtr<u8>, i32)> =
instance.exports.get_typed_function(&mut store, "load")?;
let (ptr, length) = load.call(&mut store)?;
let memory_view = memory.view(&store);
let str = ptr.read_utf8_string(&memory_view, length as u32).unwrap();
println!("Memory contents: {:?}", str);The reason for this change is that in the future this will enable
safely sharing memory across threads. The same thing goes for reading slices:
// 2.x
let new_str = b"Hello, Wasmer!";
let values = ptr.deref(memory, 0, new_str.len() as u32).unwrap();
for i in 0..new_str.len() {
values[i].set(new_str[i]);
}// 3.x
let memory_view = memory.view(&store); // (can be reused)
let new_str = b"Hello, Wasmer!";
let values = ptr.slice(&memory_view, new_str.len() as u32).unwrap();
for i in 0..new_str.len() {
values.index(i as u64).write(new_str[i]).unwrap();
}Managing imports
Instantiating a Wasm module is similar to 2.x;
let import_object: Imports = imports! {
"env" => {
"host_function" => host_function,
},
};
let instance = Instance::new(&mut store, &module, &import_object).expect("Could not instantiate module.");You can also build the Imports object manually:
let mut import_object: Imports = Imports::new();
import_object.define("env", "host_function", host_function);
let instance = Instance::new(&mut store, &module, &import_object).expect("Could not instantiate module.");For WASI, don't forget to initialize the WasiEnv (it will import the memory)
let mut wasi_env = WasiState::builder("hello").finalize()?;
let import_object = wasi_env.import_object(&mut store, &module)?;
let instance = Instance::new(&mut store, &module, &import_object).expect("Could not instantiate module.");
wasi_env.initialize(&mut store, &instance).unwrap();`ChainableNamedResolver` is removed
Chaining imports with a trait has been deemed too complex for what it does; it's possible to chain (i.e. override) an Imports' contents by using its implementation of std::iter::Extend from the Rust standard library:
let imports1: Imports = todo!();
let mut imports2: Imports = todo!();
imports2.extend(&imports);
// This is equivalent to the following:
// for ((ns, name), ext) in imports1.into_iter() {
// imports2.define(&ns &name, ext);
// }Engines
Before
In Wasmer 2.0, you had to explicitly define the Engine you want to use:
let wasm_bytes = wat2wasm(
"..".as_bytes(),
)?;
let compiler_config = Cranelift::default();
let engine = Universal::new(compiler_config).engine();
let mut store = Store::new(&engine);
let module = Module::new(&store, wasm_bytes)?;
let instance = Instance::new(&module, &imports! {})?;After
In Wasmer 3.0, there's only one engine. The user can ignore the engine details when using the API:
let wasm_bytes = wat2wasm(
"..".as_bytes(),
)?;
let compiler = Cranelift::default();
let mut store = Store::new(compiler);
let module = Module::new(&store, wasm_bytes)?;
let instance = Instance::new(&mut store, &module, &imports! {})?;Advanced configuration
The previous ability to define target and features remains in a new EngineBuilder interface:
let compiler = Cranelift::default();
let mut features = Features::new();
// Enable the multi-value feature.
features.multi_value(true);
let engine = EngineBuilder::new(compiler).set_features(Some(features));
let store = Store::new(engine);C-API
The WASM C-API hasn't changed. Some wasmer-specific functions have changed, that relate to setting up WASI environments.
wasi_env_newfunction changed input parameters to accommodate the new Store API, it now is:cstruct wasi_env_t *wasi_env_new(wasm_store_t *store, struct wasi_config_t *config);wasi_get_importsfunction changed input parameters to accommodate the new Store API, it now is:cbool wasi_get_imports(const wasm_store_t *_store, struct wasi_env_t *wasi_env, const wasm_module_t *module, wasm_extern_vec_t *imports);wasi_env_set_memorywas added. It's necessary to set theWasiEnvmemory by getting it fromInstances memory exports after its initialization. This must be performed in a specific order:- Create WasiEnv
- Create Instance
- Get Instance Exports
- Find Memory from Instance Exports and store it to WasiEnv
The function's signature is:
cvoid wasi_env_set_memory(struct wasi_env_t *env, const wasm_memory_t *memory);
Dev Release (`docs/dev/release.md`)
Release Process
The release process of wasmer is mostly automated, including generating the CHANGELOG,
tagging the release and starting the build.yaml action
In the /scripts folder, you will see three files:
update-version.py: iterates through allCargo.tomlfiles and bumps the version number
according toPREVIOUS_VERSIONandNEXT_VERSIONpublish.py: resolves the dependency order and publishes all crates to crates.iomake-release.py: creates a new pull request from the current master branch, generates the
CHANGELOG, waits until all checks have passed and the release PR is merged, then starts the
GitHub action to trigger the actual release on GitHub.
In theory, all you need to do to create a new release is to look that master is green, then
run python3 scripts/make-release.py 3.2.0 - in practice the script can sometimes lock up or
break due to unexpected delays for example it takes a couple of seconds between a pull request
being merged and master being updated. Therefore it's best to run each step individually and
make sure that every step finishes properly.
# required before starting
gh login
# Script will create a release PR (release-3.2.0) and loop until the
# release PR is merged into master (after checks are green)
python3 scripts/make-release.py 3.2.0
# After the release PR is merged, the build.yml workflow should be
# triggered automatically - if it isn't, trigger it manually
git checkout master
git tag v3.2.0 && git push origin v3.2.0
gh workflow run build.yml --ref v3.2.0 --field release=v3.2.0
# After the release is done on GitHub, run the script again
# to update the release notes
python3 scripts/make-release.py 3.2.0
# Once the release on GitHub is properly done and verified that all
# artifacts exist, checkout the tag and run the publishing to crates.io
git checkout v3.2.0
python3 scripts/publish.py publishAfter the GitHub release (first command), the crates need to be
published to crates.io - the order is important because if anything
goes wrong in the first command or a release needs to be amended
because of last-minute fixes, we can still revert the GitHub release,
but publishing on crates.io is final because we can't yank crates
(this has caused a lot of version-renumbering issues in the past).
Issues to watch out for
There are a couple of problems with the scripts that you should watch out for:
- On the release pull request, the CHANGELOG might be generated incorrectly or with wrong line endings
- If the script fails, there should be an audible message (implemented using the
saycommand), so that you
can leave the script running in the background and get notified if anything goes wrong. - The script might not trigger the
build.ymlaction, in some cases it has to be run manually - Publishing to crates.io might fail because of new crates that have to be published manually.
- It is important to adjust the
SETTINGSin thepublish.pyscript if some crates need default-features
to be enabled when publishing - crates that were never published before need to usually be published for the first time
bycd lib/crate && cargo publish
- It is important to adjust the
- After publishing new crates, check that the crate ownership is set to
github:wasmerio:wasmer-core. - The CHANGELOG is generated from the pull request titles since the last release. Sometimes these titles need
to be fixed up to make any sense for a reader - The release notes should just highlight the most important changes for a release, not dump everything.
- The following files should be released (TODO: more consistent naming schema):
- wasmer-darwin-arm64.tar.gz
- wasmer-linux-aarch64.tar.gz
- wasmer-linux-amd64.tar.gz
- wasmer-linux-musl-amd64.tar.gz
- wasmer-windows-amd64.tar.gz
- wasmer-windows-gnu64.tar.gz
- wasmer-windows.exe
Videos
- Creating the release pull request
- Triggering the build.yml action manually
- Note that the version should always be tagged with a "v" tag
- The commit to tag for the version should be the merge commit of the release PR
- Publishing to crates.io
En Examples Coredump (`docs/en/examples-coredump.md`)
Using Wasm coredump
The following steps describe how to debug using Wasm coredump in Wasmer:
Compile your WebAssembly with debug info enabled; for example:
sh$ rustc foo.rs --target=wasm32-wasi -C debuginfo=2foo.rs
fn c(v: usize) {
a(v - 3);
}fn b(v: usize) {
c(v - 3);
}fn a(v: usize) {
b(v - 3);
}pub fn main() {
a(10);
}Run with Wasmer and Wasm coredump enabled:
sh$ wasmer --coredump-on-trap=/tmp/coredump foo.wasm thread 'main' panicked at 'attempt to subtract with overflow', foo.rs:10:7 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace Error: failed to run main module `foo.wasm` Caused by: 0: Core dumped at /tmp/coredump 1: failed to invoke command default 2: error while executing at wasm backtrace: ...Use wasmgdb to debug:
sh$ wasmgdb foo.wasm /tmp/coredump wasmgdb> bt ... #13 000175 as panic () at library/core/src/panicking.rs #12 000010 as a (v=???) at /path/to/foo.rs #11 000009 as c (v=???) at /path/to/foo.rs #10 000011 as b (v=???) at /path/to/foo.rs #9 000010 as a (v=???) at /path/to/foo.rs #8 000012 as main () at /path/to/foo.rs ...
Schema Generated Jsonschema Types AppConfigV1.Schema.Json (`docs/schema/generated/jsonschema/types/AppConfigV1.schema.json`)
{
"$schema": "https://json-schema.org/draft/2019-09/schema",
"title": "AppConfigV1",
"description": "User-facing app.yaml config file for apps.\n\nNOTE: only used by the backend; Edge itself does not use this format and\nrelies on the internal AppVersionV1Spec representation instead.",
"type": "object",
"properties": {
"app_id": {
"description": "App id assigned by the backend.\n\nThis will get populated once the app has been deployed.\n\nThis id is also used to map to the existing app during deployments.",
"type": [
"string",
"null"
]
},
"capabilities": {
"anyOf": [
{
"$ref": "#/$defs/AppConfigCapabilityMapV1"
},
{
"type": "null"
}
]
},
"cli_args": {
"description": "Only applicable for runners that accept CLI arguments.",
"type": [
"array",
"null"
],
"items": {
"type": "string"
}
},
"debug": {
"description": "Enable debug mode, which will show detailed error pages in the web gateway.",
"type": [
"boolean",
"null"
]
},
"domains": {
"description": "Domains for the app.\n\nThis can include both provider-supplied\nalias domains and custom domains.",
"type": [
"array",
"null"
],
"items": {
"type": "string"
}
},
"env": {
"description": "Environment variables.",
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"health_checks": {
"type": [
"array",
"null"
],
"items": {
"$ref": "#/$defs/HealthCheckV1"
}
},
"jobs": {
"type": [
"array",
"null"
],
"items": {
"$ref": "#/$defs/Job"
}
},
"locality": {
"description": "Location-related configuration for the app.",
"anyOf": [
{
"$ref": "#/$defs/Locality"
},
{
"type": "null"
}
]
},
"name": {
"description": "Name of the app.",
"type": [
"string",
"null"
]
},
"owner": {
"description": "Owner of the app.\n\nThis is either a username or a namespace.",
"type": [
"string",
"null"
]
},
"package": {
"description": "The package to execute.",
"$ref": "#/$defs/PackageSource"
},
"redirect": {
"anyOf": [
{
"$ref": "#/$defs/Redirect"
},
{
"type": "null"
}
]
},
"scaling": {
"anyOf": [
{
"$ref": "#/$defs/AppScalingConfigV1"
},
{
"type": "null"
}
]
},
"scheduled_tasks": {
"type": [
"array",
"null"
],
"items": {
"$ref": "#/$defs/AppScheduledTask"
}
},
"volumes": {
"type": [
"array",
"null"
],
"items": {
"$ref": "#/$defs/AppVolume"
}
}
},
"additionalProperties": true,
"required": [
"package"
],
"$defs": {
"AppConfigCapabilityCdnCacheV1": {
"description": "CDN cache capability settings.",
"type": "object",
"properties": {
"enabled": {
"description": "Enable CDN caching for the app.",
"type": [
"boolean",
"null"
]
}
},
"additionalProperties": true
},
"AppConfigCapabilityInstaBootV1": {
"description": "Enables accelerated instance boot times with startup snapshots.\n\nHow it works:\nThe Edge runtime will create a pre-initialized snapshot of apps that is\nready to serve requests\nYour app will then restore from the generated snapshot, which has the\npotential to significantly speed up cold starts.\n\nTo drive the initialization, multiple http requests can be specified.\nAll the specified requests will be sent to the app before the snapshot is\ncreated, allowing the app to pre-load files, pre initialize caches, ...",
"type": "object",
"properties": {
"max_age": {
"description": "Maximum age of snapshots.\n\nFormat: 5m, 1h, 2d, ...\n\nAfter the specified time new snapshots will be created, and the old\nones discarded.",
"anyOf": [
{
"$ref": "#/$defs/PrettyDuration"
},
{
"type": "null"
}
]
},
"mode": {
"description": "The method to use to generate the instaboot snapshot for the instance.",
"anyOf": [
{
"$ref": "#/$defs/InstabootSnapshotModeV1"
},
{
"type": "null"
}
],
"default": null
},
"requests": {
"description": "HTTP requests to perform during startup snapshot creation.\nApps can perform all the appropriate warmup logic in these requests.\n\nNOTE: if no requests are configured, then a single HTTP\nrequest to '/' will be performed instead.",
"type": "array",
"items": {
"$ref": "#/$defs/HttpRequest"
}
}
}
},
"AppConfigCapabilityMapV1": {
"description": "Restricted version of the internal CapabilityMapV1, with only a select\nsubset of settings.",
"type": "object",
"properties": {
"cdn_cache": {
"description": "CDN cache settings.",
"anyOf": [
{
"$ref": "#/$defs/AppConfigCapabilityCdnCacheV1"
},
{
"type": "null"
}
]
},
"instaboot": {
"description": "Enables app bootstrapping with startup snapshots.",
"anyOf": [
{
"$ref": "#/$defs/AppConfigCapabilityInstaBootV1"
},
{
"type": "null"
}
]
},
"memory": {
"description": "Instance memory settings.",
"anyOf": [
{
"$ref": "#/$defs/AppConfigCapabilityMemoryV1"
},
{
"type": "null"
}
]
},
"runtime": {
"description": "Runtime settings.",
"anyOf": [
{
"$ref": "#/$defs/AppConfigCapabilityRuntimeV1"
},
{
"type": "null"
}
]
},
"ssh": {
"anyOf": [
{
"$ref": "#/$defs/CapabilitySshServerV1"
},
{
"type": "null"
}
]
}
},
"additionalProperties": true
},
"AppConfigCapabilityMemoryV1": {
"description": "Memory capability settings.\n\nNOTE: this is kept separate from the internal CapabilityMemoryV1 struct\nto keep the high-level app.yaml distinct from the internal App entity.",
"type": "object",
"properties": {
"limit": {
"description": "Memory limit for an instance.\n\nFormat: [digit][unit], where unit is Mb/Gb/MiB/GiB,...",
"type": [
"string",
"null"
]
}
}
},
"AppConfigCapabilityRuntimeV1": {
"description": "Runtime capability settings.",
"type": "object",
"properties": {
"async_threads": {
"description": "Whether to enable asynchronous threads/deep sleeping.",
"type": [
"boolean",
"null"
]
},
"engine": {
"description": "Engine to use for an instance, e.g. wasmer_cranelift, wasmer_llvm, etc.",
"type": [
"string",
"null"
]
}
}
},
"AppScalingConfigV1": {
"type": "object",
"properties": {
"mode": {
"anyOf": [
{
"$ref": "#/$defs/AppScalingModeV1"
},
{
"type": "null"
}
]
}
}
},
"AppScalingModeV1": {
"type": "string",
"enum": [
"single_concurrency"
]
},
"AppScheduledTask": {
"type": "object",
"properties": {
"name": {
"type": "string"
}
},
"required": [
"name"
]
},
"AppVolume": {
"type": "object",
"properties": {
"mount": {
"type": "string"
},
"name": {
"type": "string"
}
},
"required": [
"name",
"mount"
]
},
"CapabilitySshServerV1": {
"description": "Configure SSH server credentials and settings.",
"type": "object",
"properties": {
"enabled": {
"description": "Enable an SSH server.",
"type": [
"boolean",
"null"
]
},
"users": {
"type": [
"array",
"null"
],
"items": {
"$ref": "#/$defs/SshUserV1"
}
}
},
"additionalProperties": true
},
"ExecutableJob": {
"type": "object",
"properties": {
"capabilities": {
"anyOf": [
{
"$ref": "#/$defs/ExecutableJobCompatibilityMapV1"
},
{
"type": "null"
}
]
},
"cli_args": {
"description": "CLI arguments passed to the runner.\nOnly applicable for runners that accept CLI arguments.",
"type": [
"array",
"null"
],
"items": {
"type": "string"
}
},
"command": {
"description": "The command to run. Defaults to the package's entrypoint.",
"type": [
"string",
"null"
]
},
"env": {
"description": "Environment variables.",
"type": [
"object",
"null"
],
"additionalProperties": {
"type": "string"
}
},
"package": {
"description": "The package that contains the command to run. Defaults to the app config's package.",
"anyOf": [
{
"$ref": "#/$defs/PackageSource"
},
{
"type": "null"
}
]
},
"volumes": {
"type": [
"array",
"null"
],
"items": {
"$ref": "#/$defs/AppVolume"
}
}
}
},
"ExecutableJobCompatibilityMapV1": {
"type": "object",
"properties": {
"memory": {
"description": "Instance memory settings.",
"anyOf": [
{
"$ref": "#/$defs/AppConfigCapabilityMemoryV1"
},
{
"type": "null"
}
]
}
},
"additionalProperties": true
},
"HealthCheckHttpV1": {
"description": "Health check configuration for http endpoints.",
"type": "object",
"properties": {
"body": {
"description": "Request body as a string.",
"type": [
"string",
"null"
]
},
"expect": {
"anyOf": [
{
"$ref": "#/$defs/HttpRequestExpect"
},
{
"type": "null"
}
]
},
"headers": {
"description": "HTTP headers added to the request.",
"type": [
"array",
"null"
],
"items": {
"$ref": "#/$defs/HttpHeader"
}
},
"healthy_threshold": {
"description": "Number of retries before the health check is considered healthy again.\n\nDefaults to 1.",
"type": [
"integer",
"null"
],
"format": "uint32",
"minimum": 0
},
"interval": {
"description": "Interval for the health check.\n\nFormat: 1s, 5m, 11h, ...\n\nDefaults to 60s.",
"type": [
"string",
"null"
]
},
"method": {
"description": "HTTP method.\n\nDefaults to GET.",
"type": [
"string",
"null"
]
},
"path": {
"description": "Request path.",
"type": "string"
},
"timeout": {
"description": "Request timeout.\n\nFormat: 1s, 5m, 11h, ...",
"anyOf": [
{
"$ref": "#/$defs/PrettyDuration"
},
{
"type": "null"
}
]
},
"unhealthy_threshold": {
"description": "Number of retries before the health check is considered unhealthy.\n\nDefaults to 1.",
"type": [
"integer",
"null"
],
"format": "uint32",
"minimum": 0
}
},
"required": [
"path"
]
},
"HealthCheckV1": {
"oneOf": [
{
"type": "object",
"properties": {
"http": {
"$ref": "#/$defs/HealthCheckHttpV1"
}
},
"additionalProperties": false,
"required": [
"http"
]
}
]
},
"HttpHeader": {
"description": "Definition for an HTTP header.",
"type": "object",
"properties": {
"name": {
"type": "string"
},
"value": {
"type": "string"
}
},
"required": [
"name",
"value"
]
},
"HttpRequest": {
"description": "Defines an HTTP request.",
"type": "object",
"properties": {
"body": {
"description": "Request body as a string.",
"type": [
"string",
"null"
]
},
"expect": {
"anyOf": [
{
"$ref": "#/$defs/HttpRequestExpect"
},
{
"type": "null"
}
]
},
"headers": {
"description": "HTTP headers added to the request.",
"type": [
"array",
"null"
],
"items": {
"$ref": "#/$defs/HttpHeader"
}
},
"method": {
"description": "HTTP method.\n\nDefaults to GET.",
"type": [
"string",
"null"
]
},
"path": {
"description": "Request path.",
"type": "string"
},
"timeout": {
"description": "Request timeout.\n\nFormat: 1s, 5m, 11h, ...",
"anyOf": [
{
"$ref": "#/$defs/PrettyDuration"
},
{
"type": "null"
}
]
}
},
"required": [
"path"
]
},
"HttpRequestExpect": {
"description": "Validation checks for an [HttpRequest].",
"type": "object",
"properties": {
"body_includes": {
"description": "Text that must be present in the response body.",
"type": [
"string",
"null"
]
},
"body_regex": {
"description": "Regular expression that must match against the response body.",
"type": [
"string",
"null"
]
},
"status_codes": {
"description": "Expected HTTP status codes.",
"type": [
"array",
"null"
],
"items": {
"type": "integer",
"format": "uint16",
"maximum": 65535,
"minimum": 0
}
}
}
},
"InstabootSnapshotModeV1": {
"description": "How will an instance be bootstrapped?",
"oneOf": [
{
"description": "Start the instance without any snapshot triggers. Once the requests are done,\nuse wasmer_wasix::WasiProcess::snapshot_and_stop to capture a snapshot\nand shut the instance down.",
"type": "string",
"const": "bootstrap"
},
{
"description": "Explicitly enable the given snapshot triggers before starting the instance.\nThe instance's process will have its stop_running_after_checkpoint flag set,\nso the first snapshot will cause the instance to shut down.",
"type": "object",
"properties": {
"triggers": {
"type": "array",
"items": {
"$ref": "#/$defs/SnapshotTrigger"
}
}
},
"additionalProperties": false,
"required": [
"triggers"
]
}
]
},
"Job": {
"description": "Job configuration.",
"type": "object",
"properties": {
"action": {
"$ref": "#/$defs/JobAction"
},
"jitter_percent_max": {
"description": "Maximum percent of "jitter" to introduce between invocations.\n\nValue range: 0-100\n\nJitter is used to spread out jobs over time.\nThe calculation works by multiplying the time between invocations\nby a random amount, and taking the percentage of that random amount.\n\nSee also [Self::jitter_percent_min] to set a minimum jitter.",
"type": [
"integer",
"null"
],
"format": "uint8",
"maximum": 255,
"minimum": 0
},
"jitter_percent_min": {
"description": "Minimum "jitter" to introduce between invocations.\n\nValue range: 0-100\n\nJitter is used to spread out jobs over time.\nThe calculation works by multiplying the time between invocations\nby a random amount, and taking the percentage of that random amount.\n\nIf not specified while jitter_percent_max is, it will default to 10%.\n\nSee also [Self::jitter_percent_max] to set a maximum jitter.",
"type": [
"integer",
"null"
],
"format": "uint8",
"maximum": 255,
"minimum": 0
},
"max_schedule_drift": {
"description": "Don't start job if past the due time by this amount,\ninstead opting to wait for the next instance of it\nto be triggered.",
"anyOf": [
{
"$ref": "#/$defs/PrettyDuration"
},
{
"type": "null"
}
]
},
"name": {
"type": "string"
},
"retries": {
"type": [
"integer",
"null"
],
"format": "uint32",
"minimum": 0
},
"timeout": {
"anyOf": [
{
"$ref": "#/$defs/PrettyDuration"
},
{
"type": "null"
}
]
},
"trigger": {
"$ref": "#/$defs/JobTrigger"
}
},
"additionalProperties": true,
"required": [
"name",
"trigger",
"action"
]
},
"JobAction": {
"type": "object",
"oneOf": [
{
"type": "object",
"properties": {
"fetch": {
"$ref": "#/$defs/HttpRequest"
}
},
"required": [
"fetch"
]
},
{
"type": "object",
"properties": {
"execute": {
"$ref": "#/$defs/ExecutableJob"
}
},
"required": [
"execute"
]
}
]
},
"JobTrigger": {
"type": "string"
},
"Locality": {
"type": "object",
"properties": {
"regions": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": [
"regions"
]
},
"PackageSource": {
"type": "string"
},
"PasswordV1": {
"oneOf": [
{
"description": "Plain text password.",
"type": "object",
"properties": {
"password": {
"type": "string"
},
"type": {
"type": "string",
"const": "plain"
}
},
"required": [
"type",
"password"
]
},
{
"description": "Bcrypt password hash.",
"type": "object",
"properties": {
"hash": {
"type": "string"
},
"type": {
"type": "string",
"const": "bcrypt"
}
},
"required": [
"type",
"hash"
]
}
]
},
"PrettyDuration": {
"type": "string"
},
"Redirect": {
"description": "App redirect configuration.",
"type": "object",
"properties": {
"force_https": {
"description": "Force https by redirecting http requests to https automatically.",
"type": [
"boolean",
"null"
]
}
}
},
"SnapshotTrigger": {
"type": "string"
},
"SshUserV1": {
"type": "object",
"properties": {
"authorized_keys": {
"description": "SSH public keys for this user.",
"type": [
"array",
"null"
],
"items": {
"type": "string"
}
},
"passwords": {
"description": "Passwords for this user.",
"type": [
"array",
"null"
],
"items": {
"$ref": "#/$defs/PasswordV1"
}
},
"username": {
"description": "The username used for SSH login.",
"type": "string"
}
},
"additionalProperties": true,
"required": [
"username"
]
}
}
}
--- METRICS ---
- Files Extracted: 60
- Estimated Token Budget: ~55943 tokens
- Canonical Reference: https://codewiki.google/github.com/wasmerio/wasmer