| 1 | # đŸ¤– Toolchains |
| 2 | |
| 3 | Installed on docs-t1 (x86-64, Debian 13) under `$HOME`, with no `sudo`, |
| 4 | by `scripts/toolchains.sh`. Put them on `PATH` with |
| 5 | `source scripts/env.sh`. Carloku runs **linux-arm64**, so each language |
| 6 | also needs a way to produce a static (or libc-only) arm64 binary. |
| 7 | `scripts/smoke.sh <lang>` proves that route with a hello-world: it builds |
| 8 | the binary, checks it's aarch64 and static, and runs it under qemu. |
| 9 | |
| 10 | Checked 2026-10-23. |
| 11 | |
| 12 | | Setup | Versions on docs-t1 | Route to linux-arm64 | Smoke | |
| 13 | |---|---|---|---| |
| 14 | | Go, Go + Rastrillo | Go 1.26.10 | `CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build` | ok, static | |
| 15 | | Rust | rustc 1.99.1, cargo-zigbuild 0.24 | `cargo zigbuild --target aarch64-unknown-linux-musl` (zig is the linker) | ok, static | |
| 16 | | Zig | Zig 0.17.0 | `-target aarch64-linux-musl` | ok, static | |
| 17 | | Swift | Swift 6.2 + Static Linux SDK | `swift build --swift-sdk aarch64-swift-linux-musl` | ok, static | |
| 18 | | OCaml | opam 2.6.1, OCaml 5.3.0 (switch `bakeoff`) | Build **inside the arm64 root**: OCaml 5.3.0, ocamlfind and opam 2.3 for arm64, link with `-ccopt -static` | ok, static | |
| 19 | | Haskell | GHC 9.10.3, cabal 3.16 (ghcup) | Build **inside the arm64 root**: GHC 9.6.6 and cabal 3.10 for arm64, link with `-static -optl-static -optl-pthread` | ok, static | |
| 20 | | Nim | Nim 2.2.12 | `nim c --cpu:arm64 --os:linux --cc:clang` with `--clang.exe` and `--clang.linkerexe` set to `scripts/zigcc-aarch64-musl` (zig cc, musl) and `--passL:-static` | ok, static | |
| 21 | | Spinel | spinel `abf54280` (tep's pin), tep, spinelkit, Ruby 4.0.9 + prism (pixi) | Either build Spinel **inside the arm64 root** and compile with `--cc="cc -static"`, or follow lpay's zig cross-build (`paulca/lpay` `spinel/BUILD-arm64.md`) | ok, static (arm64 root route) | |
| 22 | |
| 23 | ## The arm64 root |
| 24 | |
| 25 | `scripts/arm64.sh <command>` runs a command in a Debian 13 arm64 root |
| 26 | filesystem (`~/.local/share/bakeoff-toolchains/arm64root`) through proot |
| 27 | and qemu-user. It needs no root access and no binfmt. The repo, `$TMPDIR` |
| 28 | and the toolchains directory are visible inside at the same paths. |
| 29 | Everything in it runs emulated, so builds are several times slower than |
| 30 | native. Install extra Debian packages with |
| 31 | `scripts/arm64.sh apt-get install -y <pkg>`. |
| 32 | |
| 33 | **The root is shared.** Other builders use it at the same time. If `apt` |
| 34 | or `dpkg` reports a lock, wait a minute and retry. Install what you need, |
| 35 | but never remove or downgrade packages others may rely on, and keep your |
| 36 | build output and caches under your own app directory (for example |
| 37 | `apps/<slug>/.cache/`), not in the root's `/root` or `/tmp`. |
| 38 | |
| 39 | To run any arm64 binary on docs-t1: |
| 40 | `qemu-aarch64-static -L ~/.local/share/bakeoff-toolchains/arm64root <binary>`. |
| 41 | |
| 42 | ## Notes for builders |
| 43 | |
| 44 | - **OCaml and Haskell:** the x86 compiler versions differ from the arm64 |
| 45 | root's (OCaml 5.3.0 in both; GHC 9.10.3 on x86 but 9.6.6 in the root). |
| 46 | Choose library versions that build with the arm64 root's compiler, or |
| 47 | install a matching one inside the root (ghcup and opam both work |
| 48 | there, emulated). |
| 49 | - **Static glibc** (OCaml, Haskell, Spinel via the arm64 root) warns about |
| 50 | `getaddrinfo` and `dlopen`. That's fine for an app that doesn't resolve |
| 51 | hostnames itself. |
| 52 | - **Mojo was removed from the bakeoff** (Paul's call, 2026-10-24). Mojo |
| 53 | 1.2.0 can't make a single-file binary: every executable needs |
| 54 | `libKGENCompilerRTShared.so` (plus `libstdc++`, `libMSupportGlobals.so` |
| 55 | and `libAsyncRTRuntimeGlobals.so`), and no static runtime ships. In 2023 |
| 56 | its authors described fully standalone binaries |
| 57 | ([news.ycombinator.com/item?id=35797485](https://news.ycombinator.com/item?id=35797485)); |
| 58 | that no longer holds. The finished app is kept on the `app/mojo` branch, |
| 59 | and the platform Idea is |
| 60 | [amadan.net/carlos/platform discussion 360](https://amadan.net/carlos/platform/-/discussion/360). |
| 61 | - **Fallback:** if a route above fails for a real app, the builder writes |
| 62 | `BLOCKED needs-arm64-host`, and the orchestrator arranges a native |
| 63 | arm64 machine. |
| 64 | |