erlang-wasmtime

View Source

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.

{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

{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 for offline builds, runtime-only builds and supported platforms.

Requires OTP 27 or later.

Documentation

  • erlang_wasm: a WebAssembly runtime written in Erlang, no native code. Same API style; pick it when you cannot ship a NIF.
  • erlang-python: the embedding pattern this project copies, for Python.

License

Apache-2.0