Skip to content

Repository files navigation

browsercc

Compile C/C++ programs in your browser to WebAssembly.

This repository contains build scripts for compiling a Clang/LLVM toolchain to WebAssembly, which can be used to compile C/C++ programs right in the browser. The compiler creates WebAssembly binaries that use the standard WASI system interface and can be executed by a simple runtime like @bjorn3/browser_wasi_shim.

While WASI lacks some features like C++ exceptions and threading support, it requires much less build infrastructure (no Python, shell scripts, etc.) and JavaScript glue code than Emscripten. If you need Emscripten's more advanced features, check out emception.

Usage

The NPM release of browsercc contains a precompiled toolchain, but you can also build it yourself with npm run build. This uses Docker to create a Linux container with the necessary dependencies, and then calls build.sh to compile the toolchain.

browsercc provides a JavaScript function for compiling source code given as a string to a WebAssembly module:

type CompilationJob = {
  source: string;
  fileName: string;
  flags: string[];
  extraFiles?: {
    [fileName: string]: string | ArrayBuffer;
  };
};

type CompilationResult = {
  compileOutput: string;
  module: WebAssembly.Module | null;
};

async function compile(_: CompilationJob): Promise<CompilationResult>;

Package contents

We try to optimize the artifact size as much as possible (except LTO, blocked on llvm/llvm-project#136197), but LLVM is a huge project regardless. The following files are included in the NPM package (uncompressed sizes):

  • index.js (~5 kB unminified): The main JavaScript file that contains the compile function.
  • clang.js, lld.js (70 kB unminified each): The Emscripten glue code for the Clang and LLD binaries.
  • clang.wasm (43 MB): The main compiler binary.
  • lld.wasm (23 MB): The linker binary (includes the LLVM backend because of LTO support, could be made smaller).
  • sysroot.tar (29 MB): C and C++ standard libraries and their headers.
  • stdc++.h.pch (19 MB): Precompiled header for speeding up C++ STL usage. Only downloaded if getPrecompiledHeader() is used.

Example

The index.html file contains a simple Compiler Explorer-like interface for compiling C/C++ programs. To run it, execute npm run demo and open the link printed in the console. If you open the localhost link, it will use your local build, otherwise it will load the pre-built NPM package from a CDN.

The bare minimum to compile and run a C++ program is:

import { compile } from "browsercc";
import { WASI, File, OpenFile, ConsoleStdout } from "@bjorn3/browser_wasi_shim";

const { module, compileOutput } = await compile({
  source: `
#include <iostream>
#include <string>

int main() {
  std::string name;
  std::cin >> name;
  std::cout << "Hello, " << name << "!" << std::endl;
  return 0;
}
`,
  fileName: "main.cpp",
  flags: ["-std=c++20"],
});

// Set up stdin to contain the string "browsercc\n" and capture stdout/stderr in the `output` variable.
const stdin = new TextEncoder().encode("browsercc\n");
let output = "";
const fds = [
  new OpenFile(new File(stdin)),
  new ConsoleStdout((data: Uint8Array) => {
    output += new TextDecoder().decode(data);
  }),
  new ConsoleStdout((data: Uint8Array) => {
    output += new TextDecoder().decode(data);
  }),
];

const wasi = new WASI([], [], fds);
const instance = await WebAssembly.instantiate(module, {
  wasi_snapshot_preview1: wasi.wasiImport,
});
wasi.start(instance);
console.log(output); // "Hello, browsercc!"

About

Compile C/C++ programs in your browser to WebAssembly

Topics

Resources

Stars

6 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages