carlos / todomvc-bakeoff Public
docs(mojo): STATUS BLOCKED on single-file binaries
Builds for linux-arm64 and passes the shared suite locally (host and qemu), but every Mojo binary needs libKGENCompilerRTShared.so and Carloku's binary kind takes one file.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 file changed,
+57
−0
apps/mojo/STATUS.md+57 −0
diff --git a/apps/mojo/STATUS.md b/apps/mojo/STATUS.md| new file mode 100644 |
| index 0000000..b8cb175 |
| --- /dev/null |
| +++ b/apps/mojo/STATUS.md |
| @@ -0,0 +1,57 @@ |
| +BLOCKED platform: single-file binaries only (Mojo needs libKGENCompilerRTShared.so) |
| + |
| +## Where it got stuck |
| + |
| +The app is finished and tested; it can't be shipped as Carloku's binary |
| +kind, which takes a single file (`carlos deploy --target`: "binary kind, |
| +single file"). |
| + |
| +What works, at commit `a874c81` (2026-10-23): |
| + |
| +- `make test`: 19 unit tests plus a process-level smoke test (unix |
| + socket, keep-alive, cookie round trip, clean exit on SIGTERM) pass. |
| +- Shared behaviour suite against the host build |
| + (`dist/app --listen 127.0.0.1:39517`): **67 passed, 3 skipped**, the |
| + same as the reference fixture. |
| +- `make build-arm64` produces `dist/app-linux-arm64` inside the arm64 |
| + root (about 45 s for the app once SQLite is compiled; SQLite itself |
| + takes about 15 minutes emulated, once). |
| +- The shared suite against that arm64 binary under qemu: **67 passed, |
| + 3 skipped**. `scripts/boot-check.sh dist/app-linux-arm64`: `/healthz` |
| + 200, `/api/version` 200 `a874c81`, clean exit on SIGTERM. |
| + |
| +Why it isn't deployed: |
| + |
| +- `readelf -d dist/app-linux-arm64` shows `NEEDED |
| + libKGENCompilerRTShared.so` (besides `libc.so.6`) and `RUNPATH |
| + /root/.pixi/envs/mojo/lib`. That library in turn needs `libstdc++`, |
| + `libMSupportGlobals.so` and `libAsyncRTRuntimeGlobals.so`. Boot-check |
| + and the qemu run only pass because `qemu-aarch64-static -L <arm64 root>` |
| + finds them in the root's pixi install; a Carloku instance sees only its |
| + own build. |
| +- I looked for a supported static route and found none: Mojo 1.2.0 ships |
| + no static archive of its runtime (no `libKGEN*.a` in either the x86 or |
| + the arm64 pixi env, only the `.so`), and `mojo build` has no static or |
| + standalone option (`--emit` offers `exe`, `object`, `shared-lib` and |
| + IR formats; `--help-hidden` adds nothing for linking the runtime). The |
| + runtime also starts 16 worker threads before `main`, so even |
| + `--emit object` output depends on it. |
| +- As the brief says, I didn't bundle, embed or self-extract the |
| + libraries to get around the single-file rule, and I didn't create the |
| + Carloku app or instance, since nothing could be deployed to it. |
| + |
| +What would unblock it: either Carloku's binary kind accepting a binary |
| +plus its shared libraries (a directory or archive release), or Modular |
| +shipping a static `libKGENCompilerRTShared` (and its dependencies). With |
| +either, `make build-arm64 && make deploy` after the three first-time |
| +`carlos` commands in BRIEF.md should be all that's left. |
| + |
| +Notes for the report: |
| + |
| +- SIGTERM: the Mojo runtime installs its own SIGTERM handler, which ends |
| + the process with status 143, and its threads exist before `main`, so a |
| + signal mask or `signalfd` can't catch it. The app installs a C-ABI |
| + handler that writes to a pipe its poll loop watches (`src/libc.mojo`). |
| +- Mojo's standard library has no sockets or SQLite binding, so both go |
| + through `external_call` to libc and to SQLite compiled from the |
| + amalgamation. |