npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@horang-corp/avr-gcc-wasm

v0.2.0

Published

Compile Arduino AVR firmware (atmega328p / Uno) to Intel HEX entirely in the browser with AVR GCC + binutils built for WebAssembly.

Readme

AVR GCC WASM

Browser proof of concept for compiling Arduino AVR firmware to Intel HEX with AVR GCC and GNU binutils components built for WebAssembly.

Use as an npm package

Published as @horang-corp/avr-gcc-wasm.

npm install @horang-corp/avr-gcc-wasm
import { compile, SENSOR } from "@horang-corp/avr-gcc-wasm";

const source = await fetch("/source.ino").then((r) => r.text());

const result = await compile({
  source,                       // your firmware source (.ino / .cpp text)
  sensors: [SENSOR.TOF],        // toggles -DUSE_OLED / -DUSE_TOF
  // assetsBase: "/avr/",       // optional: where tools/ and assets/ are served from
});

console.log(result.hex);        // Intel HEX text, ready to flash
console.log(result.fitsTarget); // false if it overflows the Uno flash budget

compile() runs the build in a dedicated module Worker and terminates it afterward. buildFirmware() (same options) runs in the current thread if you are already inside a worker.

Shipping the binaries (tools/ and assets/)

The package ships ~16 MB of WebAssembly compilers in tools/ and ~38 MB of prebuilt Arduino objects/headers in assets/. These are fetched at runtime into the compiler's in-memory filesystem — they are deliberately not inlined into JS (a 14 MB cc1plus.wasm base64-inlined would block streaming compile and bloat the bundle, and assets/ are loaded conditionally per sensor selection).

Bundlers can bundle the JS glue, but cannot statically discover the manifest-driven asset URLs. So copy the package's tools/ and assets/ directories to a static path your app serves and point assetsBase at it:

// e.g. after copying node_modules/@horang-corp/avr-gcc-wasm/{tools,assets}
//      into your public dir under /avr/
await compile({ source, sensors, assetsBase: new URL("/avr/", location.origin) });

The default assetsBase is the package's own location, which works when the files are served alongside the module (e.g. plain static hosting or npm run serve in this repo).

Prepare Assets

Third-party Arduino core, Arduino libraries, Adafruit libraries, avr-libc objects, and generated AVR object files are not committed to this repository.

Generate them from pinned upstream Arduino package/library archives:

npm run prepare-assets

This creates assets/ locally. The script downloads exact versions from Arduino package indexes, verifies SHA-256 checksums, extracts headers/libraries, and compiles the fixed Arduino/library object files with the downloaded native AVR GCC toolchain. It currently expects Linux, Node.js 18+, tar, and unzip.

Run

Put your firmware source in src/HorangFirmware.cpp first. That file is intentionally ignored by git.

npm run serve

Open http://127.0.0.1:4173/.

The browser API is exposed on the page:

const result = await buildFirmware([SENSOR.OLED, SENSOR.TOF]);
console.log(result.hex);

The UI creates a fresh Worker for each build and terminates it after completion. This makes memory reclamation more predictable on low-end devices.

Current Result

The build runs fully in the browser through a module Worker:

  1. cc1plus.wasm compiles src/HorangFirmware.cpp with -DUSE_OLED and -DUSE_TOF.
  2. avr-as.wasm assembles the generated AVR assembly.
  3. avr-ld.wasm links the firmware object with precompiled Arduino core and library objects.
  4. avr-objcopy.wasm emits Intel HEX.

Generated Arduino core and library objects live in assets/objects. They are selected by sensor group at link time, so unused sensor libraries are not linked into the output.

The product firmware source used during local validation is not included in this repository.

Measured In Chrome

Measured on this machine through agent-browser against http://127.0.0.1:4173/.

| Sensors | Flash bytes | HEX text bytes | Linked objects | Wall time | | --- | ---: | ---: | ---: | ---: | | base | 23,914 | 67,276 | 30 | 1.09s | | TOF | 28,024 | 78,837 | 31 | 0.66s | | OLED | 33,768 | 95,005 | 32 | 0.62s | | OLED + TOF | 37,878 | 106,553 | 33 | 0.63s |

For arduino:avr:uno, the sketch upload budget is treated as 32,256 bytes. That means TOF fits, while OLED and OLED + TOF do not fit on the Uno-class target.

Bundle And Memory

Generated uncompressed local asset size after npm run prepare-assets:

  • tools: 17 MB
  • assets: about 38 MB
  • total generated runtime bundle inputs: about 55 MB

The original unstripped WASM tools were about 106 MB. After removing DWARF/custom debug sections, tools/cc1plus.wasm is about 14 MB and the binutils tools are about 0.7-1.1 MB each.

Initial WebAssembly linear memory was also reduced:

| Tool | Original initial memory | Current initial memory | | --- | ---: | ---: | | cc1plus.wasm | 256 MB | 4 MB | | avr-as.wasm | 128 MB | 4 MB | | avr-ld.wasm | 128 MB | 4 MB | | avr-objcopy.wasm | 128 MB | 4 MB |

ALLOW_MEMORY_GROWTH is still enabled, so each tool can grow when needed. A 2 MB initial memory also passed the current OLED + TOF build, but 1 MB fails during instantiation because static data no longer fits. The checked-in value is kept at 4 MB for margin.

Measured linear-memory peaks in Chrome after growth:

| Sensors | cc1plus peak | avr-ld peak | Sequential tool total | | --- | ---: | ---: | ---: | | base | 40.8 MB | 7.0 MB | 55.8 MB | | TOF | 40.8 MB | 7.0 MB | 55.8 MB | | OLED | 40.8 MB | 7.0 MB | 55.8 MB | | OLED + TOF | 40.8 MB | 7.0 MB | 55.8 MB |

The real tab/worker footprint is higher than these linear-memory numbers because the browser also holds fetched assets, MEMFS file contents, JS objects, compiled WebAssembly code, and output buffers.

Production should still add HTTP compression, long-lived cache headers, and possibly Cache Storage/IndexedDB preloading.

Notes

  • This does not run QEMU. The actual AVR compiler pieces are WebAssembly modules.
  • The GCC driver is not used in-browser because it depends on process behavior such as vfork. The browser path drives cc1plus, assembler, linker, and objcopy directly.
  • The firmware source should allow USE_OLED and USE_TOF to be overridden from the compiler command line.
  • assets/ldscripts/avr5.xn and assets/objects/core_abi.o are generated because avr-ld and Adafruit_GFX need them when running/linking in the browser bundle.
  • See THIRD_PARTY_NOTICES.md before using these artifacts in a public or commercial distribution.