← Playground docs/PLATFORMS.md
raw

Platforms

Two distinct axes: where compiled NURL programs run (codegen targets) and where the toolchain itself builds and runs (host platforms).

Support is stated in tiers, defined by what continuous integration actually verifies — not by intent:

on every change. A failure blocks merge.

bootstrap fixed point verified in CI, but the test corpus does not run on that platform.

exercised ad hoc (playground endpoints, one-off device validation); nothing in CI gates them.

Host platforms (where the toolchain runs)

HostTierWhat is verifiedInstall
Linux x86_64 (glibc ≥ 2.28)1build.sh bootstrap fixed point + full corpus + examples gate + ASan/UBSan/LSan + peak-RSS / symbol-collision / leak gates, every push and PR; release artifact smoke-testedinstall.sh
FreeBSD x86_641build + bootstrap + full corpus on a FreeBSD 14.2 VM in CI (hard gate); the release artifact leg is best-effort (continue-on-error)install.sh
Linux ARM64 (glibc)2release workflow builds natively on an ARM64 runner (--no-tests) and smoke-tests a hello-world; not in ci.ymlinstall.sh
Windows x86_641the windows-tests workflow runs build.bat — bootstrap fixed point + the full Windows golden corpus (run_tests.ps1) — on every push to main and every PR, so a Windows-only regression cannot reach main; the release job builds with --no-tests. ci.yml additionally links the runtime with the distro mingw-w64 (tools/check_mingw_cross.sh), because both Windows-runner toolchains target UCRT and the cross one does notinstall.ps1
macOS ARM64 (Apple Silicon)1the macos-tests workflow runs ./build.sh — bootstrap fixed point + the full corpus, against the same outputs/ goldens as Linux and FreeBSD — on every push to main and every PR, plus the nurl.sh driver end to end and the examples gate. Requires Homebrew LLVM: Xcode's clang cannot parse nurlc's IR (see BUILDING.md). No release artifact yet — the installer still rejects Darwin, so the install route stays build-from-sourcebuild from source
macOS x86_64 (Intel)3no CI. GitHub's last Intel image (macos-13) never left the queue across ten attempted runs, and a required check that cannot schedule blocks every PR — so the leg was removed rather than left permanently pending. The code paths are the ARM64 ones plus a different codegen backend; unverifiedbuild from source
Alpine / musl3build from source only. The shipped Linux archives are glibc-linked and do not load under muslbuild from source

On Windows, building a program works with no Visual Studio and no LLVM: the archive bundles a zig cc, and carries a MinGW-ABI runtime object (stdlib\runtime.mingw.o) for it alongside the MSVC one that a system clang uses — the two ABIs cannot share an object. Compression is not affected either way: gzip, deflate and zstd are all pure NURL and link nothing.

There is a THIRD Windows toolchain, and for two releases nothing tested it: the distro mingw-w64 (x86_64-w64-mingw32-gcc), which the hosted playground's /build_windows cross-compiles with. It targets the older msvcrt.dll rather than UCRT, so a runtime that calls a UCRT-only CRT export links on both toolchains above and on neither of that one — and because mingw pulls in the whole runtime object, the failure is total: hello world does not link either. tools/check_mingw_cross.sh compiles stdlib/runtime.c for that target and links a trivial main against it, in about ten seconds and with no Windows involved; ci.yml runs it.

Two things are MSVC-ABI only, because the library each needs is an MSVC import lib, and the driver says so rather than leaving it to the linker: the canvas FFI (canvas.o + SDL2.lib), and real GPU compute (cuda.lib / nvrtc.lib from a CUDA Toolkit). Under the bundled zig a program using packages/gpu still builds and runs — it falls through to the driverless stubs and reports the CPU backend — so a package that merely pulls gpu in transitively (anomaly → tensor → gpukit → gpu) needs nothing installed. For GPU compute on the device, build with a system clang.

The shipped nurlc / nurlpkg binaries link libc only (optional FFI libraries are pulled in --as-needed, so a program that uses none stays libc-only), and the nurl.sh wrapper is POSIX sh — no bash, no make, no Python. Linux archives are relinked against a glibc 2.28 floor (tools/relink-toolchain-portable.sh).

Codegen targets (where compiled programs run)

The compiler emits LLVM IR and delegates native codegen to clang, so any target clang supports is reachable in principle. NURL's IR carries no target triple, so a single zig cc --target= (or clang --target=) drives every cross build. Linux x86_64 and Windows x86_64 are exercised by the local build scripts; the rest are produced through the nurlapi/ container's cross-compile endpoints (see PLAYGROUND.md).

TargetBackendTierNotes
Linux x86_64LLVM1primary target — build.sh + full corpus
Windows x86_64LLVM (mingw-w64)1separate Windows goldens (compiler/tests/outputs-windows/); corpus runs on every push and PR via the windows-tests workflow
macOS x86_64LLVM + zig cc3POST /build_macos; Mach-O links only libSystem (no Apple SDK). Runs on Apple Silicon via Rosetta 2. canvas/audio/libcurl-HTTP not supported
macOS ARM64LLVM + zig cc3POST /build_target (target=macos-arm64) — native Apple Silicon Mach-O, links only libSystem. Unsigned: clear quarantine before running
WebAssemblywasm32-wasi3via the nurlapi/ container (WASI SDK 24.0); browser execution via browser_wasi_shim. The self-hosting compiler itself also builds to wasm — see PLAYGROUND.md
Linux ARM64 / RISC-V64LLVM + zig cc3POST /build_target — fully-static musl ELFs (linux-arm64-musl, linux-riscv64-musl) or dynamic glibc (linux-arm64-gnu). Milk-V Duo (RISC-V C906) validated on-device (one-off, not CI)
Unikernel x86_64LLVM + unikernel nolibc1the program boots as its own kernel — PVH ELF for QEMU microvm, and the same image boots under Firecracker and cloud-hypervisor. The guest gate (corpus subset against hosted goldens, device demos, faults, an HTTP server answering the host, a virtio-blk disk written across three boots and validated by fsck.vfat — not the full corpus) runs in CI on every change and blocks merge. POST /build_unikernel in the playground. See unikernel/README.md
Unikernel AArch64 / RISC-V64LLVM + zig cc + unikernel nolibc1QEMU virt; AArch64 also emits a flat Image for Firecracker / cloud-hypervisor (those need an ARM64 host). Per-arch QEMU gates (same scope as x86_64's) run in CI on every change and block merge. AArch64 via POST /build_unikernel arch
Android / iOSLLVM cross—planned
Embedded (no_std)LLVM—planned

Unsigned macOS binaries: clear the Gatekeeper quarantine attribute with xattr -d com.apple.quarantine <bin> before running.

CI details: BUILDING.md.