MaiaC (WebC): C89-to-WebAssembly Compiler
raw JSON → 1.2.4 verified Fri May 01 auth: no javascript
MaiaC (WebC) is a C-to-WebAssembly compiler written in JavaScript, targeting a C89 subset. Version 1.2.4 (as of March 2025) is released via npm, with development on GitHub. It parses C source using EBNF-generated parsers, lowers to WAT, emits WAT via templates, and validates/assembles via the MaiaWASM submodule. Supports Node.js >=18 and browser execution. Differentiators: pure JavaScript implementation (no native dependencies), built-in runtime bridges for host environment (e.g., console, Math), and distribution packaging for browser + Node workflows. Release cadence appears irregular; check GitHub for latest.
Common errors
error Error: Cannot find module 'maiac' ↓
cause Running code in Node without installing the package or running from the wrong directory.
fix
Run
npm install maiac and ensure your script imports from 'maiac' not a relative path. error TypeError: webc is not a constructor ↓
cause Using `new webc()` after v1.2.0 when webc is now a plain function.
fix
Call
webc(options) directly without the new keyword. error Expected C89 declaration before statement ↓
cause C code uses C99+ features like mixed declarations and code.
fix
Move variable declarations to the beginning of blocks.
Warnings
gotcha MaiaC only supports a C89 subset; C99 or later features (e.g., // comments, mixed declarations) will cause parse errors. ↓
fix Write C89-compliant code: use /* */ comments, declare variables at block start.
breaking In v1.2.0, the default export changed from a class to a function. Using `new webc()` will throw. ↓
fix Call webc(options) directly without new.
deprecated create-dist.js CLI wrapper is deprecated; use tools/webc.js --dist instead. ↓
fix Run node tools/webc.js compiler/examples/test.c --dist instead of node tools/create-dist.js ...
gotcha C source must not use standard library includes like <stdio.h> unless you provide the stubs; external functions must be declared as extern __host__* functions. ↓
fix Declare I/O via extern __console__log(char* msg) and similar host bridges.
gotcha The --resolve-system-includes flag is experimental and may expand includes incorrectly for nested paths. ↓
fix Avoid using --resolve-system-includes for production; manually inline includes.
Install
npm install maiac yarn add maiac pnpm add maiac Imports
- webc (default) wrong
const webc = require('maiac')correctimport webc from 'maiac' - createDist wrong
import createDist from 'maiac'correctimport { createDist } from 'maiac' - hostEnvBuilder wrong
import HostEnvBuilder from 'maiac'correctimport { hostEnvBuilder } from 'maiac'
Quickstart
import webc from 'maiac';
import { readFileSync, writeFileSync } from 'fs';
const cSource = `int main() { return 42; }`;
const outDir = './out';
const name = 'test';
const result = await webc({
source: cSource,
outDir,
name,
wat: true,
run: false
});
console.log('Output files:', result.files);
// Expected: out/test.wasm, out/test.js (if wrappers generated), out/test.wat
// Or compile from file:
const sourceFile = './test.c';
const fileResult = await webc({
file: sourceFile,
outDir,
name: 'test',
wat: true
});
console.log('Compiled .wasm to:', fileResult.files[0]);