owner @Hindurable
[dependencies] wasmbuilder = "^0.1.3"
0.1.3 · 2026-07-25 · @Hindurable · files · api0.1.2 · 2026-07-07 · @Hindurable · files · api0.1.1 · 2026-07-03 · @Hindurable · files · api0.1.0 · 2026-07-03 · @Hindurable · files · apiNone.
Compile NURL to wasm32-wasi locally — no wasi-sdk, no Docker, no build service. One install command brings everything:
curl -fsSL https://nurl-lang.org/install.sh | sh
export PATH="$HOME/.nurl/bin:$PATH"
nurlpkg install wasmbuilder
wasmbuilder program.nu # → program.wasm
Run the result with any wasm runtime — the reference wasmtime, or the pure-NURL one from this registry:
nurlpkg install wasmtime
wt run program.wasm
The installed toolchain already contains everything a wasm build needs; wasmbuilder just drives it:
nurlc compiles your program to LLVM IR (host-targeted).wasm32-unknown-wasi. This isthe production pipeline extracted from the play.nurl-lang.org build service: @main is renamed to the wasi crt entry, libc calls whose NURL FFI uses 64-bit widths where wasm32's libc expects 32 get trunc/zext shim wrappers, POSIX-only symbols wasi-libc doesn't ship (mmap, fork, pthread…) become error-sentinel stubs behind the stdlib's runtime gates, and every remaining external symbol is annotated as a potential env wasm import — so canvas/audio/GPU host imports resolve at run time instead of failing the link.
zig cc (which nurl.sh already prefersfor native builds) compiles + links the module: zig carries its own wasi-libc and wasm-ld, which is what makes wasi-sdk unnecessary.
runtime.wasm.o) is compiled from the installedstdlib's runtime.c on first use and cached under $NURL_HOME/build/wasmbuilder/, keyed by the source's content hash — upgrading the toolchain automatically rebuilds a matching runtime.
If no zig is found at all (for example a Windows install, or a Linux toolchain installed with the clang fallback), wasmbuilder downloads the pinned zig 0.13.0 release once, sha256-verified against ziglang.org's release index, into $NURL_HOME/zig — after which builds are fully offline. Set NURL_WASM_NO_DOWNLOAD=1 to forbid the download and fail instead.
wasmbuilder <file.nu> [options]
-o, --output FILE output path (default: <input>.wasm)
-O, --opt LEVEL 0..3 or z (default 2; z = size)
--emit-ll keep the rewritten wasm32 .ll next to the output
--asyncify wasm-opt asyncify wrap for canvas programs
(needs binaryen's wasm-opt on PATH)
--no-host-imports don't pass --ffi-host-imports to nurlc
-q, --quiet suppress progress output
--doctor show how nurlc / zig / runtime resolve here
--version, -h
--doctor is the first thing to run when something is off — it prints each resolution step (nurlc, stdlib C sources, wasm compiler, cache dir) and what would happen next.
Other packages depend on wasmbuilder to compile wasm in-process — no subprocess orchestration, no HTTP build API. This is how swarm-mcp compiles compute kernels and how nurl-mcp exposes a local build-wasm tool:
$ `deps/wasmbuilder/src/build.nu`
: ~ WbOpts opts ( wb_opts_default )
= . opts quiet T
: !( Vec u ) String r ( wb_build_source kernel_src `kernel.nu` opts )
?? r {
T wasm_bytes → { … ship to workers … }
F err → { … structured error, nurlc diagnostics included … }
}
wb_build_file nu_path out_wasm opts → !v String is the file-to-file variant the CLI wraps; it also handles multi-file programs (imports resolve exactly as a native nurl build would).
| Variable | Effect |
|---|---|
NURL_HOME | toolchain prefix (default ~/.nurl) |
NURLC | explicit nurlc binary |
NURL_ZIG | explicit zig binary (skips discovery) |
WASI_CLANG | use a wasi-sdk clang instead of zig |
NURL_WASM_NO_DOWNLOAD | never download zig; fail with instructions |
NURL_WASM_OPT | wasm-opt binary for --asyncify (default PATH) |
stdlib/ext/postgres.nu)can't target wasm — the link reports the missing symbols.
thread_spawn fails gracefully atrun time (pthread stubs return error), mirroring the playground.
./tests/build_test.sh
Builds the CLI, compiles a corpus of repo examples to wasm, runs each next to its native twin and diffs the output byte-for-byte, then exercises the library API. The pipeline is also validated at scale: the NURL compiler itself (65k lines) built through wasmbuilder produces byte-identical output to its native twin under both the reference wasmtime and the pure-NURL wt.