Library / SDK
WebAssembly/binaryen avatar
WebAssembly/binaryen

Binaryen: the wasm-opt optimizer and toolchain library for WebAssembly

Optimizer and compiler/toolchain library for WebAssembly

8,648 stars892 forksWebAssemblyApache-2.0

At a glance

What is it?
Binaryen is a C++ compiler and toolchain infrastructure library for WebAssembly, best known for the wasm-opt command line optimizer. It is aimed at toolchain authors and anyone who needs to shrink or speed up an existing .wasm file.
Who is it for?
Adopt Binaryen if you already have a .wasm file and want a wasm-to-wasm optimizer, or if you are building a toolchain and want a C API in a single header plus a JavaScript API. Do not adopt it expecting a general-purpose compiler front end: it does not turn C, Rust or TypeScript into wasm on its own, and its default text output is not guaranteed to be valid wasm text.
Can I use it commercially?
Yes. Apache-2.0 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 received new commits within the last day.
What is it written in?
Mainly WebAssembly, according to GitHub's language statistics.

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

Editorial analysis

What Binaryen solves, and who actually needs it

Binaryen sits between a compiler and a browser. The README describes it as a compiler and toolchain infrastructure library for WebAssembly, written in C++, with three stated goals: easy, fast and effective. The part most people meet first is not the library at all but the wasm-to-wasm optimizer. You hand it a .wasm file, it parses the module, runs optimization passes over it, and emits a new .wasm file. No source code is involved at that stage.

The second audience is toolchain authors. Binaryen exposes a C API in a single header and can also be used from JavaScript. Compilers that use it as a library include AssemblyScript, wasm2js, Asterius and Grain. Toolchains that use it as a component, typically by running wasm-opt, include Emscripten for C and C++, wasm-pack for Rust, J2CL for Java, Kotlin/Wasm, Flutter for Dart, and wasm_of_ocaml for OCaml. That list is the clearest signal of the intended user: people shipping a language to the browser, not people writing an application.

If you are writing ordinary application code and your build already runs wasm-opt for you, you are a downstream beneficiary rather than a user. You would only install Binaryen directly when you need to run the optimizer by hand, inspect a module, or embed the library.

Binaryen IR: a tree, not a stack, and what that costs you

The internal representation is where Binaryen diverges from WebAssembly itself. The wasm binary format is a stack machine. Binaryen IR is a tree with hierarchical structure, which the README says is for convenience of optimization. A separate Stack IR exists to optimize code that cannot be represented in structured form, and when stacky code has to appear in the main IR, such as with multivalue instructions and blocks, it is represented with tuple types that do not exist in the WebAssembly language.

One consequence is worth reading twice. Binaryen IR has an unreachable type and lets block, if and loop take it, which enables local transforms that do not need to know the global context. Because of that, the default text output is not necessarily valid wasm text. If you need text that a wasm parser will accept, the README points at `--generate-stack-ir --print-stack-ir`, which prints Stack IR and is guaranteed to be valid for wasm parsers. Anyone piping Binaryen's default text output into another tool should expect failures.

Control flow is narrower than in wasm. Binaryen IR has exactly one control flow structure with a variable-length list of children: the block. Loops, if arms and function bodies each have a single child, which may itself be a block. The stated motivation is that many passes need special code to iterate over instruction lists, so concentrating that list in one node simplifies them. Branch targets are resolved by name rather than nesting depth, which means unnamed blocks cannot be branch targets and names must be unique. Reading .wat files with duplicate names is supported, but the names are modified when the IR is constructed.

Installing Binaryen and running wasm-opt for the first time

Binaryen ships as a set of command line tools, of which wasm-opt is the one you will use most. The project publishes tagged releases, with version_132 dated 2026-08-12, version_131 dated 2026-07-15 and version_130 dated 2026-06-01. Because the repository is written in C++ and built with CMake, the practical route is either a prebuilt package for your platform or a build from source using the top-level `CMakeLists.txt`.

If you consume it from a JavaScript toolchain, the npm package is the usual entry point, and the README notes that Binaryen can be used from JavaScript as well as from C. The README gives one concrete command line example for getting valid wasm text out of the optimizer:

bash
wasm-opt --generate-stack-ir --print-stack-ir

That form prints Stack IR rather than the default text output, and the README states it is guaranteed to be valid for wasm parsers. This is the variant to reach for when another tool has to read the result, because the default text output is not necessarily valid wasm text.

The README does not document a rollback procedure for an optimization run, so keep the original .wasm file rather than overwriting it on the first attempt. The README also does not spell out a full install sequence for every platform; it points to the contributing instructions in Contributing.md for people who want to work on the project itself, and describes the toolchain utilities in terms of what they do rather than as a copy-paste setup guide.

Where Binaryen is the wrong tool

Binaryen does not compile C, C++, Rust or TypeScript to WebAssembly by itself. It is a backend and an optimizer. Emscripten provides the complete C and C++ to WebAssembly toolchain and integrates with Binaryen; wasm-pack plays the same role for Rust. If your problem is "I have source code and no wasm," Binaryen is downstream of your problem, not a solution to it.

The IR differences create a second class of failure. The README is explicit that the default text output is not necessarily valid wasm text, and that unnamed blocks cannot be branch targets while names must be unique. If you are generating .wat by hand and expecting Binaryen to round-trip it unchanged, the IR construction step may rename your blocks. That is a documented behavior, not a bug, but it will surprise anyone treating Binaryen as a pass-through text formatter.

There is also a stated limit on how far the design will bend. The README says experiments show that better support for multivalue could enable useful but small code size savings of 1-3%, and that this has not been worth changing the core IR structure. So if your workload depends on multivalue for meaningful gains, the project has already decided that this particular axis is not where it will invest. Treat that as a boundary rather than a roadmap item.

Binaryen compared with Emscripten and LLVM

The comparison people search for most is Binaryen versus Emscripten, and the two are not competitors. Emscripten is a complete compiler toolchain from C and C++ to WebAssembly, and it uses Binaryen as a component, typically by running wasm-opt. Choosing Emscripten means you get Binaryen inside the box. Choosing Binaryen alone means you get the optimizer and the library but no front end, no libc, and no runtime glue.

The comparison with LLVM is about role rather than overlap. LLVM is a general-purpose compiler infrastructure; Binaryen's README frames its own focus as WebAssembly-specific optimizations that general-purpose compilers might not do, describing the goal as wasm minification in the same spirit as minification for JavaScript or CSS. That framing is the honest summary of the difference: LLVM gets you to wasm, and Binaryen tries to make the wasm smaller and faster afterward. The README also notes that Binaryen can be used as a compiler backend by itself, so the boundary is not absolute, but the center of gravity is clear.

A third option worth naming is wasm2js, which compiles WebAssembly to JavaScript. It is listed in the README as a compiler using Binaryen as a library, so it is an extension of Binaryen rather than an alternative to it. If your target environment lacks native wasm support, the README notes that Binaryen can polyfill WebAssembly by running it in the interpreter compiled to JavaScript, which is described as useful for testing.

Release cadence, licence and the cost of staying current

The repository is not archived, and the last push was on 2026-09-21. Releases are frequent: version_132 on 2026-08-12, version_131 on 2026-07-15, version_130 on 2026-06-01. That is roughly a monthly tag, which means the upgrade cost is really a question of how tightly you pin. A toolchain that pins a specific tag and only moves when it needs a new optimization pass pays very little. A toolchain that tracks the default branch pays continuously, and the CHANGELOG.md at the repository root is where those changes are recorded.

The licence is Apache-2.0, which is a permissive licence with an explicit patent grant. That matters for a project that gets embedded inside other compilers, because the terms travel with the code when you redistribute a modified Binaryen inside your own toolchain. This is not legal advice; if you are shipping a modified Binaryen in a commercial product, have your own counsel read the LICENSE file rather than relying on a summary.

One cost that is easy to miss: because Emscripten, wasm-pack, Kotlin/Wasm and Flutter already bundle wasm-opt, installing Binaryen separately can leave you with two copies of the optimizer at different versions. The version that actually runs on your module may not be the one you installed.

Editorial conclusion

Adopt Binaryen if you already have a .wasm file and want a wasm-to-wasm optimizer, or if you are building a toolchain and want a C API in a single header plus a JavaScript API. Do not adopt it expecting a general-purpose compiler front end: it does not turn C, Rust or TypeScript into wasm on its own, and its default text output is not guaranteed to be valid wasm text. Before committing, verify the release tag you pin against the version_132 release notes from 2026-08-12, and check whether your downstream toolchain already bundles wasm-opt before you add a second copy.

Frequently asked questions

How do I install Binaryen?

The repository is a C++ project built with CMake, and the project publishes tagged releases such as version_132. You can build from source using the top-level CMakeLists.txt, or consume it through the npm package if you are working from a JavaScript toolchain.

What is the difference between Binaryen and LLVM?

LLVM is general-purpose compiler infrastructure, while Binaryen focuses on WebAssembly-specific optimizations that general-purpose compilers might not do. The README describes Binaryen's aim as wasm minification, similar to minification for JavaScript or CSS.

Do I need to install Binaryen if I already use Emscripten?

Emscripten is listed in the README as a toolchain that uses Binaryen as a component, typically by running wasm-opt, so Binaryen already comes with it. Installing it separately can leave you with two copies of wasm-opt at different versions.

Can Binaryen compile C or Rust to WebAssembly on its own?

No. Binaryen is a compiler and toolchain infrastructure library and an optimizer, not a front end for those languages. Emscripten provides the complete C and C++ to WebAssembly toolchain, and wasm-pack plays that role for Rust.

Why is Binaryen's text output sometimes not valid wasm text?

Binaryen IR has an unreachable type that block, if and loop can take, which the README says allows local transforms that do not need the global context. To get text guaranteed to be valid for wasm parsers, use --generate-stack-ir --print-stack-ir.

Official sources

  1. Issues
  2. License: Apache-2.0
  3. README
  4. Releases
  5. WebAssembly/binaryen 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/webassembly-binaryen.svg)](https://hysenlabs.com/projects/webassembly-binaryen)