Open-source project
WAVM/WAVM avatar
WAVM/WAVM

WAVM: a WebAssembly virtual machine for non-browser workloads

WebAssembly Virtual Machine

2,780 stars234 forksC++BSD-3-Clause

At a glance

What is it?
WAVM compiles WebAssembly to machine code with LLVM and runs it outside the browser. It is aimed at embedders who need near-native speed and can build a C++ toolchain from source.
Who is it for?
Adopt WAVM if you are embedding WebAssembly in a native C++ application, need LLVM-compiled machine code, and can run a 64-bit host with a source build. Do not adopt it if you need a 32-bit target, a stable tagged release, or isolation from side-channel attacks, since the README says WAVM is vulnerable to attacks such as Spectre variant 2 and recommends an OS process boundary.
Can I use it commercially?
Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 177 days ago.
What is it written in?
Mainly C++, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 24, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What WAVM solves and who it is for

WAVM is a WebAssembly virtual machine designed for use in non-browser applications. That single sentence from the README defines the audience: developers who already have a native program and want to execute untrusted or pluggable WebAssembly modules inside it, rather than ship a browser engine or a JavaScript runtime. The project is written in portable C and C++, with a small amount of architecture-specific assembly and LLVM IR generation code, and it is licensed under BSD-3-Clause.

The problem it addresses is the cost of running sandboxed code. Interpreters and JITs that compile quickly pay at execution time. WAVM takes the opposite position: it uses LLVM to compile WebAssembly code to machine code, and the README claims this reaches close to native performance, with the possibility of beating native performance when the generated code is tuned for the exact CPU running it. Memory safety is handled with virtual memory and signal handlers so that WebAssembly's bounds-checked accesses cost the same as a native unchecked access, according to the README.

This is not a tool for running WebAssembly in a page. It is for server-side execution, plugin hosts, and language runtimes that want a WebAssembly backend. If you are looking for a drop-in CLI to run a .wasm file once and move on, the build cost described below will feel disproportionate.

How WAVM turns a WASM module into running machine code

The mechanism visible in the repository is a compile step, not an interpretation step. WebAssembly input is translated through LLVM IR and then compiled to machine code for the host. The repository layout reflects this split: Include/ holds public headers, Lib/ holds the implementation, Programs/ holds the executables, and ThirdParty/ holds vendored dependencies. The README points to Doc/CodeOrganization.md for readers who want to follow the source.

Two design choices follow from that. First, the runtime requires a 64-bit virtual address space, so it does not run on 32-bit hosts. The assembler and disassembler are the exception: the README states those work on 32-bit hosts. Second, the safety boundary is the virtual machine plus explicit linking. WAVM prevents WebAssembly code from accessing state outside the virtual machine or calling native code you did not explicitly link with the module. That is a linking model, not a capability system: what a module can reach is decided when you build the host program.

The feature list is broader than WebAssembly 1.0. The README lists WASI, 128-bit SIMD, threads, reference types, multiple results and block parameters, bulk memory operations, non-trapping float-to-int conversions, sign-extension instructions, exception handling, an extended name section, and multiple memories. Those are proposed extensions, and the README presents them as supported rather than experimental, which is a strong claim for a project whose release history is mostly nightly builds.

Building WAVM from source with the repository Dockerfile

WAVM does not present a package installation path in the README. The linked documentation is Doc/Building.md, and the repository ships a Dockerfile that pins the whole toolchain to Ubuntu 18.04. That file is the most concrete build recipe available, and it is worth reading before you start, because it fixes the LLVM version at 6.0.

The Dockerfile installs autoconf, automake, build-essential, cmake, libtool, llvm-6.0, make, ninja-build, sudo, unzip and zlib1g-dev, copies the source to /code, and builds in /build with CMake and Ninja:

dockerfile
RUN cmake -G Ninja /code -DCMAKE_BUILD_TYPE=RelWithDebInfo
RUN ninja

A RelWithDebInfo build of an LLVM-based compiler is not a quick operation, and the image starts from Ubuntu 18.04, which is old enough that you may prefer to reproduce the dependency list on a current base image rather than use the file as-is. If you build outside Docker, the same two commands apply once the dependencies are present. The Programs/ directory is where the resulting executables live; the repository also contains Examples/ with echo.wast, helloworld.wast, tee.wast and trap.wast, plus an Examples/embedder/ directory with its own CMakeLists.txt for embedding WAVM in a host program.

A first real use is to build the tree, then run one of the example modules through the resulting program to confirm the toolchain produced working code. The examples are small on purpose: helloworld.wast and echo.wast exercise the basic path, and trap.wast is there to show what a trap looks like. The README does not document a command-line invocation for these examples, so read Doc/GettingStarted.md before assuming a flag or subcommand name.

Where WAVM is the wrong tool

The README is unusually direct about the security boundary. WAVM is vulnerable to some side-channel attacks, such as Spectre variant 2. The text says WAVM may add further mitigations for specific side-channel attacks, but that it is impractical to guard against all of them, and it recommends another form of isolation such as OS processes to protect sensitive data from untrusted WebAssembly code. If your threat model includes speculative execution attacks from hostile modules, the virtual machine alone is not the answer, and the project says so.

The second limitation is portability. The runtime needs a 64-bit virtual address space. The README says WAVM is tested on and fully supports x86-64 and AArch64 on Windows, macOS and Linux, all six combinations in CI, and that it is designed to run on any POSIX-compatible system but is not routinely tested on others. A 32-bit embedded target is out of scope for the runtime, even though the assembler and disassembler still work there.

The third is release cadence. The recent releases are nightly builds, with a long gap between the 2022 nightlies and the 2026-04-05 nightly. The last push to the repository was on 2026-04-05. There is no tagged stable release in the published release list, so a team that needs versioned upgrade paths has to decide how to pin a nightly or a commit. The README does not document rollback or a support policy.

WAVM against a browser-oriented WebAssembly runtime

The natural comparison is a WebAssembly engine that lives inside a JavaScript host, such as the one shipped with a browser or a Node.js runtime. The difference is in what the engine is optimised for. A browser engine must start fast, because a page load cannot wait for an LLVM compile, and it must integrate with the DOM, JavaScript objects and the browser's own sandbox. WAVM gives up fast startup in exchange for LLVM-generated machine code and a native linking model where the host decides which functions a module may call.

That trade-off shows up in the embedding story. With a browser-oriented runtime you get a JavaScript API and a garbage-collected host; with WAVM you write a C++ host program, link the module's imports explicitly, and take responsibility for the process boundary yourself. The README's own advice about using OS processes for isolation is a reminder that WAVM expects the embedder to own that layer.

A second alternative is to keep the untrusted code in a separate process running a different runtime and communicate over a socket. That costs latency and message-passing complexity, but it buys the isolation WAVM explicitly does not provide against side channels. For a plugin host that runs trusted or semi-trusted modules, in-process WAVM is the simpler design. For a multi-tenant service executing arbitrary user code, the process boundary is doing the real work either way.

Maintenance, licence and upgrade cost

The repository is not archived, and its last push was on 2026-04-05. The releases listed are nightlies, with a three-year gap between the 2022-05-14 nightly and the 2026-04-05 nightly. That gap matters more than the current activity: it means the project has had long quiet periods, and anyone depending on it should be prepared to build from a specific commit rather than wait for a version number.

The licence is BSD-3-Clause, which is permissive and does not impose copyleft obligations on your host program. The repository also contains a THIRD-PARTY.md file, which is where the licences of vendored dependencies such as LLVM and the code in ThirdParty/ are recorded. LLVM's licence is not the same as WAVM's, and if you redistribute a binary that links it, that file is the place to start reading. This is not legal advice; the point is that the permissive licence on WAVM itself does not settle the obligations attached to its dependencies.

The upgrade cost is dominated by the build, not by API churn you can measure from the published documentation. The Dockerfile pins llvm-6.0 and Ubuntu 18.04, so moving to a newer LLVM or a newer base image is work the project has not done for you in that file. Budget for a rebuild and a re-run of the Test/ suite whenever you move commits, and treat the nightly label as a signal that no compatibility promise is being made.

Editorial conclusion

Adopt WAVM if you are embedding WebAssembly in a native C++ application, need LLVM-compiled machine code, and can run a 64-bit host with a source build. Do not adopt it if you need a 32-bit target, a stable tagged release, or isolation from side-channel attacks, since the README says WAVM is vulnerable to attacks such as Spectre variant 2 and recommends an OS process boundary. Before committing, clone the repository and run the Dockerfile build to confirm that CMake and Ninja produce the Programs binaries on your platform, and check the Portability Matrix for your architecture.

Frequently asked questions

What is WAVM?

WAVM is a WebAssembly virtual machine designed for use in non-browser applications. It uses LLVM to compile WebAssembly code to machine code and supports WebAssembly 1.0 plus extensions such as WASI, SIMD, threads and exception handling.

How do I build WAVM from source?

The repository Dockerfile installs the dependencies on Ubuntu 18.04, copies the source to /code, and builds with cmake -G Ninja /code -DCMAKE_BUILD_TYPE=RelWithDebInfo followed by ninja. The README links Doc/Building.md for building outside that image.

Which platforms does WAVM support?

The README states that WAVM is tested on and fully supports x86-64 and AArch64 on Windows, macOS and Linux, with all six combinations in CI. The runtime requires a 64-bit virtual address space, so it is not portable to 32-bit hosts, though the assembler and disassembler work there.

Is WAVM safe for running untrusted WebAssembly?

WAVM prevents WebAssembly code from accessing state outside the virtual machine or calling native code you did not explicitly link. However, the README states that WAVM is vulnerable to some side-channel attacks such as Spectre variant 2 and recommends another form of isolation, such as OS processes, for sensitive data.

Is WAVM actively maintained?

The repository is not archived, and the last push was on 2026-04-05. The listed releases are nightly builds, with a gap between the 2022-05-14 nightly and the 2026-04-05 nightly, and no tagged stable release appears in the release list.

Official sources

  1. License: BSD-3-Clause
  2. Project website
  3. README
  4. Releases
  5. WAVM/WAVM on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/wavm-wavm.svg)](https://hysenlabs.com/projects/wavm-wavm)