wa_embedder
A WebAssembly-to-BEAM compiler for the Erlang ecosystem, written in Erlang. It
parses a .wasm binary (via wa_parser),
translates each function to Erlang abstract format, and compiles and loads the
result as a native BEAM module that you can call directly.
This is the Erlang package. Elixir projects can depend on it directly, or use
the companion wa_embedder_ex package
for an idiomatic Elixir API (WaEmbedder.compile/1..4 + WaEmbedder.ImportError).
Repository layout (monorepo)
Two hex packages live in this repository:
| Path | Package | Tool | Role |
|---|---|---|---|
| repo root | wa_embedder | rebar3 | The compiler core (pure Erlang) |
wa_embedder_ex/ | wa_embedder_ex | mix | Thin Elixir wrapper + the test suite |
test_data/ | — | cmake | Shared WAT/C .wasm fixtures |
The dependency direction is one-way: wa_embedder_ex (Elixir) → wa_embedder
(Erlang) → wa_parser (Erlang). The core has no Elixir dependency.
Installation (rebar3)
%% rebar.config
{deps, [{wa_embedder, "~> 0.1"}]}.
Usage
{module, Mod} = wa_embedder:compile("module.wasm"),
Result = Mod:some_exported_fun(Arg).
compile/1,2,3,4 compiles and loads the module and returns the
code:load_binary/3 result ({module, ModuleName} on success). Modules with
imports take an imports map resolving each WASM import to an Erlang target
(MFA tuple, external fun, or closure); unsatisfiable imports raise
erlang:error({import_error, Map}).
Development
A nix develop shell provides erlang, elixir, rebar3, and the fixture
toolchain (cmake, ninja, wabt, binaryen). Dependencies default to their
published hex releases:
- Core → parser (side repo): the core depends on the published
{wa_parser, "~> 0.1"}hex package;rebar3fetches it from hex. To develop against a sibling../wa_parsercheckout instead, opt in manually with a rebar3 checkout (mkdir -p _checkouts && ln -sfn ../../wa_parser _checkouts/wa_parser); a checkout takes precedence over the hex dep. Nothing wires it for you (remove it before packaging). - Wrapper → core (in-repo): the wrapper depends on the published
{:wa_embedder, "~> 0.1"}hex package by default. To build against the Erlang core at the repo root instead, opt in manually by exportingWA_EMBEDDER_PATH=..beforemix(e.g.WA_EMBEDDER_PATH=.. mix test).
Build and test
# Erlang core (repo root) — uses the published wa_parser hex dep
rebar3 compile
# Elixir wrapper + full fixture suite (in wa_embedder_ex/).
# The core is not on hex yet, so build the wrapper against the in-repo core:
cd wa_embedder_ex && WA_EMBEDDER_PATH=.. mix test
The test suite lives in wa_embedder_ex/test/ and compiles the WAT/C fixtures
under the repo-root test_data/ (built by CMake/Ninja before the suite runs).
Once wa_embedder is published, mix test works without WA_EMBEDDER_PATH.
Building the fixtures manually
cd test_data
cmake -B build -G Ninja
ninja -C build # WAT fixtures (default); `ninja -C build c_fixtures` for the C chain
Packaging
# Core: uses the published {wa_parser, "~> 0.1"} dep. (If you added a manual
# _checkouts override for parser dev, remove it first: rm -rf _checkouts.)
rebar3 hex build # or: make package
# Wrapper: unset WA_EMBEDDER_PATH so the {:wa_embedder, "~> 0.1"} hex dep is used
cd wa_embedder_ex && env -u WA_EMBEDDER_PATH mix hex.build # or: make package
Publish order: publish wa_embedder (core) first, then wa_embedder_ex (the
wrapper’s hex dep on the core cannot resolve until the core is on hex).
License
Released into the public domain under the Unlicense.