kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

commit af5ecc87b77eaf69a9795b2fcc497459f5f024f1
parent e5087df9d440f55ba3e9e8d0b7165593a6c99041
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Tue,  9 Jun 2026 16:17:04 -0700

plan: SYSROOTS

Diffstat:
Adoc/plan/SYSROOTS.md | 243+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 243 insertions(+), 0 deletions(-)

diff --git a/doc/plan/SYSROOTS.md b/doc/plan/SYSROOTS.md @@ -0,0 +1,243 @@ +# Cross-compilation sysroots + +This document is the design and implementation plan for packaging and +distributing minimal sysroots that let kit users cross-compile for every +platform in the release support set from any host. + +## Goals + +- One `kit sysroot install <triple>` installs everything needed to + cross-compile for that target. +- Sysroots are minimal: stubs and headers only, no full framework trees or + large dynamic libraries. +- Every sysroot ships as a signed `.kpkg`, distributed through kit's existing + CAS + package infrastructure. +- Macros and library versions are versioned and reproducible; the kpkg hash is + the identity of a sysroot release. +- macOS SDK headers are legally redistributable only by the user; the macOS + kpkg references them by CAS blob hash but does not embed them. Users + populate the blobs from a local SDK once; thereafter the kpkg installs + normally. + +## Support set + +| Triple pattern | libc variant | Notes | +|---|---|---| +| `{x86_64,aarch64,riscv64}-linux-musl` | musl static + stub `.so` | Compiled from musl source | +| `{x86_64,aarch64,riscv64}-linux-gnu` | glibc stub `.so` | Stubs generated from reference glibc | +| `{x86_64,aarch64}-windows-gnu` | mingw-w64 UCRT | Import stubs + headers, open source | +| `aarch64-apple-macos{14,15}` | libSystem stub | `.tbd` stubs; headers by hash | +| `{x86_64,aarch64,riscv64}-freebsd` | FreeBSD libc stub | Stubs + headers, BSD license | +| `{x86_64,aarch64,riscv64,riscv32}-none` | freestanding | kit `rt/` only; no sysroot kpkg | + +Freestanding targets require no sysroot kpkg; `libkit_rt.a` and +`rt/include/` serve that role and are already in-tree. + +## Sysroot kpkg layout + +Each installed sysroot unpacks into `~/.kit/sysroots/<triple>/`: + +``` +<triple>/ + include/ system headers + lib/ + crt1.o C runtime entry (where applicable) + crti.o + crtn.o + libc.a static libc (musl only; absent on stub-only platforms) + libc.so stub or real shared library + libm.so + libpthread.so + ... other platform libs + tbd/ macOS .tbd stubs (macOS targets only) +``` + +The `cc` driver's `-target` flag resolves the sysroot by triple lookup under +`~/.kit/sysroots/`. Explicit `--sysroot=<path>` overrides this. + +## Library stubs + +### ELF stub `.so` (Linux glibc, FreeBSD) + +A stub `.so` contains only what the linker needs: SONAME, exported symbol +table, and GNU version info (`.gnu.version`, `.gnu.version_r`). No PT_LOAD +segment, no `.text`, no `.data`. The file is ~10–50 KB instead of hundreds of +KB for the real library. + +Kit will include a **stub generator** (`src/obj/elf_stub.c`, exposed as +`kit sysroot gen-elf-stub`) that: + +1. Reads a real `.so` (dynsym + versioning sections). +2. Emits a minimal ELF with the same SONAME, all exported symbols as + `STT_NOTYPE`/`STB_GLOBAL`/`SHN_ABS`, and the original `.gnu.version_r` + chain. +3. Records the source library's build-id in a `.note.kit.stub` section for + traceability. + +Stubs are generated offline from a reference installation (a glibc or FreeBSD +system) and committed into the sysroot kpkg. They must be regenerated when the +upstream ABI version changes. + +### macOS `.tbd` stubs + +Apple's Text-Based Stub Library (`.tbd`, YAML) is the native macOS stub format +used inside Xcode SDKs. Kit's Mach-O linker already knows how to read `.tbd` +files (required for linking against system frameworks). The macOS sysroot kpkg +contains `.tbd` files for `libSystem`, `libm`, `libpthread`, `libc++`, and the +core framework stubs. + +The `.tbd` files are open/YAML; they can be extracted from any macOS SDK +installation and are small. + +### Windows import stubs (`.dll.a`) + +mingw-w64 provides import stub archives for the Windows SDK DLLs (kernel32, +ucrtbase, etc.) under a MIT-compatible license. The Windows sysroot kpkg +bundles these directly alongside the mingw-w64 UCRT headers. No generation +step is needed; the mingw-w64 tree is the upstream source. + +## musl: compiled from source + +For `*-linux-musl` targets kit compiles musl directly rather than shipping +pre-built archives. Advantages: reproducible, architecture-correct, no +redistribution complexity, and a good exercise of kit's self-compilation +pipeline. + +The musl source tree (a pinned release tarball, verified by BLAKE2b hash) is +bundled in the kpkg for each architecture. `kit sysroot install +aarch64-linux-musl` fetches the kpkg, extracts the musl source, and compiles +it with `kit cc -target aarch64-linux-musl` into: + +- `libc.a` — static archive +- `libc.so` (stub only; the real `.so` for dynamic musl is the runtime-provided + `ld-musl-<arch>.so.1`) +- CRT objects: `crt1.o`, `rcrt1.o` (PIE), `Scrt1.o`, `crti.o`, `crtn.o` + +The compile is cached by the musl source hash, so reinstalling the same kpkg +version is a no-op. + +## macOS SDK headers: CAS-referenced blobs + +Apple's SDK headers may not be redistributed by third parties. The macOS +sysroot kpkg solves this by **referencing** the header blobs by CAS hash +without embedding them: + +```yaml +# excerpt from the macOS sysroot kpkg manifest +headers: + required_blobs: + - hash: "sha256:abc123..." # usr/include/stdio.h + install_path: include/stdio.h + - hash: "sha256:def456..." # usr/include/sys/types.h + install_path: include/sys/types.h + ... +``` + +When `kit sysroot install aarch64-apple-macos14` runs: + +1. Kit resolves each required blob from the local CAS. +2. If any blobs are missing, it prints the missing hashes and instructs the + user to run `kit sysroot extract-macos-headers`. +3. Once all blobs are present, the sysroot is materialized normally. + +The blobs themselves are ordinary CAS objects — the user may host them on any +CAS-compatible store (private server, S3, local NAS) and point kit at it via +`KIT_CAS_REMOTE` or `kit cas remote add`. + +### `kit sysroot extract-macos-headers` + +``` +kit sysroot extract-macos-headers [--sdk-path=<path>] [--target=<triple>] +``` + +Walks the SDK's `usr/include/` (and selected framework headers), ingests each +file as a CAS blob, and prints a manifest fragment with the resulting hashes. +This is run once per SDK version by the user on their Mac. It does not upload +anything; it just populates the local CAS. The user may then push those blobs +to their preferred remote. + +The manifest fragment output is what kit's sysroot release process uses to +build the macOS kpkg. For users who just want things to work locally, the +extract step followed by `kit sysroot install` is sufficient. + +## `kit sysroot` command surface + +``` +kit sysroot list # show installed sysroots +kit sysroot available # show sysroots available in configured remotes +kit sysroot install <triple> # fetch + install sysroot kpkg +kit sysroot install <triple> --from=<path> # install from a local kpkg file +kit sysroot remove <triple> # uninstall +kit sysroot update [<triple>] # reinstall latest version +kit sysroot path <triple> # print install path (for --sysroot= use) + +kit sysroot extract-macos-headers [--sdk-path=<path>] [--target=<triple>] +kit sysroot gen-elf-stub <input.so> -o <stub.so> +kit sysroot gen-kpkg <triple> --config=<sysroot.toml> -o <output.kpkg> +``` + +`gen-kpkg` is the sysroot *builder* used offline by kit's release pipeline. It +reads a `sysroot.toml` that declares the source for each component (musl source +hash, upstream `.so` paths to stub-ify, mingw tree path, `.tbd` directory, +macOS header manifest), runs the appropriate generators, and emits a signed +kpkg. + +## Implementation work items + +### Infrastructure + +- [ ] `src/obj/elf_stub.c` — ELF stub `.so` generator; reads dynsym + + `.gnu.version_r`, emits a no-PT_LOAD ELF. Exposed via `kit sysroot + gen-elf-stub`. +- [ ] `driver/cmd/sysroot.c` — the `kit sysroot` subcommand (list / available / + install / remove / update / path / extract-macos-headers / gen-elf-stub / + gen-kpkg). +- [ ] `include/kit/sysroot.h` + `src/api/sysroot.c` — public API for sysroot + resolution, used by the `cc` driver's `-target` lookup. +- [ ] `sysroot.toml` schema — declarative input format for `gen-kpkg`; one file + per `(triple, libc-variant, libc-version)`. +- [ ] macOS blob-reference manifest support in kpkg reader — when a kpkg + declares `required_blobs`, validate presence before materializing, and + emit a helpful error with the `extract-macos-headers` hint if missing. + +### Sysroot sources and generation + +- [ ] **musl** — pin a musl release (tarball + BLAKE2b), write a `sysroot.toml` + per `{x86_64,aarch64,riscv64}-linux-musl`, implement the in-install + compile step. +- [ ] **Linux glibc** — generate ELF stubs from a reference glibc + `{x86_64,aarch64,riscv64}` installation (targeting glibc 2.35 as a + reasonable minimum). Package headers + stubs + CRT objects into kpkgs. +- [ ] **Windows** — package mingw-w64 headers + import stubs for + `{x86_64,aarch64}-windows-gnu`. Validate against the VM test suite + (`test-hosted`). +- [ ] **macOS** — generate `.tbd` stubs, write header manifest, validate the + blob-reference install flow on a local macOS SDK. Target macOS 14 and 15. +- [ ] **FreeBSD** — generate ELF stubs + package headers from a FreeBSD 14 + `{x86_64,aarch64,riscv64}` installation. + +### CI and distribution + +- [ ] Release pipeline script (`scripts/gen_sysroots.sh`) — runs `gen-kpkg` + for each sysroot, signs the resulting kpkgs, and pushes to the release + CAS remote. +- [ ] `kit sysroot available` fetches the index from the configured release + remote and shows version + size for each triple. +- [ ] Add sysroot install smoke tests to `test/hosted` for each supported + triple: install sysroot, compile `hello.c`, run on target (or VM). + +## Open questions + +- **glibc version targeting**: ship stubs for a single baseline version + (e.g. 2.35) or per-version kpkgs? Per-version is more correct but multiplies + the release surface. Start with a single baseline and version the kpkg + (users who need an older ABI can pin the kpkg version). +- **FreeBSD version**: FreeBSD 14 as the baseline. FreeBSD moves slowly; + one kpkg version per major release is likely sufficient. +- **macOS SDK scraping automation**: the `extract-macos-headers` step is manual. + A CI job running on a macOS runner could automate it, but requires a macOS + SDK license. For now the manifest is generated manually when an SDK version + changes and the blob hashes are committed to the release pipeline config. +- **CAS remote hosting**: where are the kpkgs and blobs hosted? Options: GitHub + Releases (artifacts, size-limited), S3/R2, or a self-hosted kit CAS instance. + This is a release infrastructure question, not a kit code question.