Repository messaging and storage

ctrl+alt+d · repository channels, users, messages and the product origin object pool

L2 object pool

Developer guide

Build locally, run on brintOS

The end-to-end loop: build the toolchain once, compile your program, upload the binary through the file browser, then launch the machine in your browser and run it on brintos.io.

A brintOS package is not a generic .wasm file. It must be produced by the brintOS toolchain (hwjs-cc), which emits a small versioned header in a custom wasm section so the kernel can execve it. A binary built with Emscripten or wasi-libc will not run on a brintOS machine.

Prerequisites

You need the brintOS toolchain installed: the pinned LLVM, the HwjsCoroutinize pass and the wasmcc/wasmld drivers on your PATH, and our musl built into a sysroot. If you haven't done that yet, work through Install the toolchain first (all three steps — packages need the musl sysroot), then come back here.

1. Compile your package

wasmcc is a drop-in replacement for cc: it targets wasm32, links the musl from your sysroot, runs the HwjsCoroutinize pass, and attaches the binfmt_wasm header. Start with a hello-world:

cat > hello.c <<'EOF'
#include <stdio.h>
int main(void) {
    printf("hello from a brintOS package\n");
    return 0;
}
EOF

# Compile to a wasm-native Linux executable.
# WASMLD_HWJS=1 selects the coroutinizing arm — required for real builds
# (your toolchain env from the setup guide should already export it).
export WASMLD_HWJS=1
wasmcc hello.c -o hello

The result is a standard wasm module with one extra custom section. You can inspect it with stock wasm tooling — the custom section is ignored by tools that don't understand it:

wasm-objdump -h hello     # the custom binfmt_wasm section is present
file hello                # WebAssembly (wasm) binary module

Make sure the libc actually linked. A correctly linked package imports the kernel's shared memory and the syscall entry point our musl wrappers call. Confirm both are present:

wasm-objdump -x hello | grep -E 'kernel_memory|wasm_syscall'
# (env) kernel_memory   memory   ...
# (env) wasm_syscall    func     ...

If those imports are missing, your program didn't link against the brintOS musl — re-check the driver environment from the toolchain setup (WASMLD_HWJS=1, HWJS_TOOLS_DIR / WASMLD_HWJS_LIBC_BC) and rebuild. Builds are static by default, so hello bundles musl and is self-contained. Any build system that respects CC/LD works — point it at wasmcc/wasmld (e.g. make CC=wasmcc, with the sysroot env set) to build larger packages.

2. Get a machine and upload your package

Fork a shell image from Explore into your account. Upload hello through its file browser, for example to /usr/local/bin/hello. For a complete filesystem built locally, use ext4 image import.

3. Make the package executable

Launch your writable live machine and run:

chmod +x /usr/local/bin/hello

4. Run it in the browser

Open your machine on brintos.io and press Power on. The machine boots its configured kernel and init (a shell, for a bash/coreutils image) entirely in the tab — its root filesystem is served from the same cloud storage you just wrote to. When the serial console shows a prompt, run your program:

$ hello
hello from a brintOS package

The kernel's binfmt_wasm loader recognizes the header you compiled in, swaps the image in on execve, and your process runs as a real Linux task — it can fork, take signals, and block on syscalls like any other binary.

Want your package to be the machine — run automatically instead of from a shell? Set the machine's init to your binary's path (e.g. /usr/local/bin/hello) in its machine spec, and the kernel will exec it as PID 1 on boot. See Machines. Building your own kernel image instead of using a stock one? See Build the Linux kernel.