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.

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.
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.
npm install maiac
yarn add maiac
pnpm add maiac

Compile a C89 source string to WebAssembly using MaiaC with WAT output. Demonstrates ESM import and basic usage.

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]);