Platform Guide
Overview
The engine core is platform-agnostic; everything OS-specific lives behind the Platform* seam. This guide covers the seam, the shared POSIX core that both production targets build on, the two targets themselves, and the checklist for a new port.
The platform seam
Every platform implements the contract in platform/include/platform.h. A conforming port must provide a working body for all of it — there are no optional symbols:
| Area | Symbols |
|---|---|
| Wapp lifecycle | PlatformWappLoad / Unload / Start / Stop / Loop / GetState |
| Registry backend | PlatformRegistryRead / Write / Remove / WappLoad |
| Filesystem | PlatformOpenStateDir, PlatformFsRename, PlatformFsMkdir |
| Network | PlatformNetOpen / Connect / Recv / Send / Accept / Shutdown / Close / Free |
| Clock | PlatformClockGetRes / GetTime / NanoSleep |
| Memory | PlatformMemoryStats |
| Concurrency | PlatformMutexNew / Lock / Unlock / Free |
| Power / process | PlatformSetProcessArgs, PlatformRequestShutdown, PlatformRequestReboot |
The invariants every platform must honour: a wapp runs on its own thread; PlatformWappStop must interrupt a wapp that is blocked in a host syscall (not merely set a flag and wait); PlatformWappLoop blocks until an explicit shutdown/reboot request and respawns a supervisor that exits on its own; memory stats report heap usage; the registry resolves a wapp image by name.
All targets build inside the standardized container — the host only needs a container runtime. make help lists the targets; append RUNNER=docker to use Docker.
Shared POSIX core
Linux and the NuttX simulator are both POSIX environments, so most of the seam has one implementation they both compile in: platform/posix/. It carries the generic, syscall-backed bodies:
| Source | Provides |
|---|---|
posix/socket.c |
PlatformNet* — the BSD socket calls (open, connect, recv, send, accept, shutdown, close) |
posix/mutex.c |
PlatformMutex* |
posix/clock.c |
PlatformClockGetRes / GetTime |
posix/fs.c |
PlatformOpenStateDir, PlatformFsRename, PlatformFsMkdir |
posix/registry-store.c |
the filesystem registry store behind PlatformRegistry* |
posix/wapps-image.c |
image load/unload behind PlatformWappLoad / Unload |
A target layer (platform/linux/, platform/nuttx/) links those sources and implements only what genuinely differs between the two:
| Concern | Linux | NuttX |
|---|---|---|
| Threads + stop | pthreads; async pthread_cancel |
tasks; cooperative SIGUSR2 + WAMR terminate flag |
Sleep (PlatformNanoSleep) |
api/clock-sleep.c |
api/clock-sleep.c (signal-EINTR quirk) |
| Secure sockets | OpenSSL (api/ssocket.c) |
none yet |
| Memory stats | mallinfo2 |
NuttX heap walk |
| Registry backend glue | host directory (api/registry.c) |
hostfs (api/registry.c) |
| Entry point | wanted-cli main |
wanted_sim_main (NuttX init task) |
platform/dummy/ is the exception: a unit-test stub that implements the whole seam in memory and shares none of the POSIX sources — the model for a target that is not POSIX at all.
Linux
The primary target.
1make build # engine + CLI with the production sheriff supervisor
2make wsh # engine with the wsh debug supervisor
- Threads — pthreads.
- Stop mechanism —
pthread_cancel(ASYNCHRONOUS)interrupts a blocked syscall immediately, so a wapp stuck in a host call is reaped promptly. - Registry — a host-filesystem directory (
./registry/) scanned for<name>:<version>.wappimages. - TLS — OpenSSL-backed secure sockets (
T/Usocket options). - Memory stats —
mallinfo2.
CMake options of note: WANTED_PLATFORM (the platform layer), WANTED_SUPERVISOR_IMAGE_PATH (compile-time supervisor image), SECURE_SOCKETS (TLS).
NuttX simulator
A first-class, CI-gated target: the full engine running as a NuttX application on the host-stack simulator. The platform/nuttx/ layer is complete — every Platform* symbol has a working body, with no remaining stubs.
1make nuttx-deps # init the nuttx + nuttx-apps submodules, link the app package
2make nuttx-build # configure + build the sim from a clean tree
3make nuttx-selftest # run the in-WASM selftest suite on the sim
4make nuttx-shell # boot the sim to an interactive wsh prompt
- Board config —
sim:wanted, a native defconfig in the NuttX fork. The engine runs as the NuttX init task viawanted_sim_main, whichchdirs to/data(so./registryresolves against the sim's hostfs) and powers the board off cleanly whenwanted_mainreturns. - Console — raw
write(1/2)for output. - Stop mechanism — cooperative:
PlatformWappStopsets the WAMR terminate flag and sendsSIGUSR2to the worker so a wapp blocked in a host call is interrupted and checks the flag on return. A per-workerinterruptedflag bridgesclock_nanosleep's success-on-signal quirk. - Submodules —
third_party/nuttxandthird_party/nuttx-appsare shallow submodules pinned to thewantedbranch of the mekops forks;make nuttx-depsinitialises them (idempotent) and must run once beforenuttx-build.
Differences from Linux. No TLS yet. The sim:wanted board is built without a network stack (CONFIG_NET off), so socket() fails and /net sockets are unavailable on the sim — socket paths are exercised on Linux only, and the selftest skips its /net socket check on the sim. The cooperative stop cannot pre-empt a bare native call that never checks EINTR, where Linux's async cancel can.
NuttX on real HW (upcoming)
The planned architecture: wapp images loaded from XIP flash, a LittleFS-backed registry slot table, and mbedTLS for secure sockets. The simulator port is the staging ground — hardware reuses the shared POSIX core and most of the NuttX target layer; the flash registry backend and mbedTLS are the remaining hardware-specific pieces.
Porting to a new platform
- Create
platform/<name>/. If the target is POSIX-like, linkplatform/posix/and implement only the deltas (thread/stop model, memory stats, secure sockets if any, registry-backend glue, entry point); otherwise implement everyPlatform*symbol fromplatform.hyourself, withplatform/dummy/as the model for a from-scratch port. Either way, no stubs. - Provide a stop mechanism that interrupts a blocked host syscall, not just a cooperative flag.
- Implement a registry backend (filesystem, flash blob, or in-memory) behind
PlatformRegistry*. - Wire the build (
WANTED_PLATFORM=<name>) and a board/app entry point.
The NuttX port is the reference for a constrained target. Its findings carry over: keep wamrData_t opaque and reach it through the WantedWappTerminate accessor; avoid VLAs; avoid scandir and GNU extensions (use opendir/readdir/qsort); confirm CONFIG_INTERPRETERS_WAMR_THREAD_MGR so wasm_runtime_terminate takes effect, and that thread cleanup does not rely on pthread_cleanup_push.
See also
- Architecture — where the platform seam sits in the system.
- Testing Guide — the same suites run on Linux and the NuttX sim.