Packages

Wasmtime bindings for Erlang: run WebAssembly natively, call Erlang from the guest

Current section

Files

Jump to
Raw

README.md

# erlang-wasmtime
Wasmtime bindings for Erlang (also findable as wasmtime-erlang). WebAssembly
modules run natively through Wasmtime's Cranelift compiler, and a module can
call Erlang functions when it needs to, the way `erlang-python` lets Python
call Erlang.
```erlang
{ok, Mod} = wasmtime:compile({wat, ~"""
(module
(import "env" "log" (func $log (param i32) (result i32)))
(func (export "run") (param i32) (result i32)
local.get 0 call $log))
"""}),
{ok, Inst} = wasmtime:instantiate(Mod, #{
imports => #{{~"env", ~"log"} => fun(_Ctx, [N]) -> logger:info("got ~p", [N]), {ok, [N * 2]} end}}),
{ok, [84]} = wasmtime:call(Inst, ~"run", [42]).
```
Nothing raises for guest failures. Compile, link, trap, WASI and host errors
all come back as `{error, #{class => ..., kind => ..., message => ...}}`.
## What you get
- Native execution: Wasmtime 48, statically linked into one NIF.
- Host functions: an import backed by an Erlang fun, run in the calling process.
- Isolation by default: no WASI, no filesystem, no host functions and a 256 MB
memory cap unless you grant more. Each instance has its own store, memory and
OS thread.
- Interruption: `timeout` on a call, or `wasmtime:interrupt/1` from any process,
stops a running guest within 10 ms.
- WASI preview 1 with explicit capabilities: `args`, `env`, preopened `dirs`,
and stdio redirected to files or inherited.
- Linear memory access from Erlang while the guest is idle or inside a host call.
- References as terms: `funcref`, `externref` (wrapping any Erlang term) and
GC structs and arrays cross calls, host functions, globals and tables.
- Precompiled modules: compile once, `deserialize/1` in milliseconds.
- Runtime-only builds: `WASMTIME_RUNTIME_ONLY=1` gives a 4 MB NIF without the
compiler for nodes that only load precompiled modules.
- Host functions served by the caller or by a dedicated process.
- Streams: a long-running guest reads what `send/2` queues and its writes
arrive as messages, through stdin/stdout for stock WASI programs or the
`erlang` imports for modules you build.
## Install
```erlang
{deps, [{erlang_wasmtime, "0.1.1"}]}.
```
The first `rebar3 compile` downloads the pinned Wasmtime C API release for your
platform (about 15 MB, checksum verified) and builds the NIF. You need a C
compiler and `curl`; a platform without a prebuilt archive builds Wasmtime
from source with `git`, `cmake` and Rust. See [docs/building.md](docs/building.md)
for offline builds, runtime-only builds and supported platforms.
Requires OTP 27 or later.
## Documentation
- [Run JavaScript](docs/javascript.md): QuickJS in the sandbox, the shortest path to a demo
- [Run Python](docs/python.md): CPython's WASI build, with the standard library
- [Getting started](docs/getting-started.md)
- [Host functions](docs/host-functions.md)
- [WASI](docs/wasi.md)
- [Streams](docs/streams.md): talk to a guest while it runs
- [References](docs/references.md): funcref, externref and GC values as terms
- [Precompiled modules](docs/precompiled.md): compile once, load in milliseconds
- [Building and shipping](docs/building.md)
- [Troubleshooting](docs/troubleshooting.md)
- [Design](docs/design.md): how the NIF is put together, for contributors; see also [CONTRIBUTING.md](CONTRIBUTING.md)
- [Features](docs/features.md): what is implemented, what is refused, what is deferred
- [Examples](examples/README.md): user-defined event transforms in JavaScript, a guest that reads ETS, logs and notifies processes
## Related
- [erlang_wasm](https://github.com/benoitc/erlang_wasm): a WebAssembly runtime
written in Erlang, no native code. Same API style; pick it when you cannot
ship a NIF.
- [erlang-python](https://github.com/benoitc/erlang-python): the embedding
pattern this project copies, for Python.
## License
Apache-2.0