commit ed7f379593b1990849bff38040e04435222cb9b0
parent 30edea9e33151f5d7fc5ba2c19f3b7111b6ab797
Author: Ryan Sepassi <rsepassi@gmail.com>
Date: Thu, 18 Jun 2026 12:24:35 -0700
doc: plan kitc support library
Diffstat:
2 files changed, 296 insertions(+), 0 deletions(-)
diff --git a/doc/plan/KITC.md b/doc/plan/KITC.md
@@ -0,0 +1,295 @@
+# kitc support library
+
+This document sketches a future `kitc` library: a Kit-provided C utility
+library that is distributed with the toolchain, built on demand for the active
+target, and linkable from both file-output builds and JIT runs.
+
+`kitc` is deliberately **not** libc and not the compiler runtime. It is an
+ordinary opt-in support library for data structures, algorithms, encoding,
+small platform abstractions, and other reusable C utilities that are useful to
+programs compiled by Kit.
+
+## Goals
+
+- Ship reusable C utility APIs under a Kit-owned namespace.
+- Make the library available to C programs, C "scripts" run through `kit run`,
+ and cross-compiled targets.
+- Build archives on demand from source, using Kit itself, instead of shipping a
+ prebuilt archive for every target and ABI variant.
+- Use the normal linker and archive semantics once the archive exists: no
+ special symbol resolution path, no JIT-only library path.
+- Keep freestanding code usable without libc or host syscalls.
+- Distribute the source tree through the existing signed package/CAS machinery
+ once package-based support assets are user-facing.
+
+## Non-goals
+
+- `kitc` is not a C standard library implementation.
+- `kitc` must not define standard libc symbols such as `printf`, `malloc`, or
+ `memcpy`.
+- `kitc` must not be required for ordinary C code generation. Compiler helper
+ routines remain in `libkit_rt.a`.
+- `kitc` must not introduce hidden global state. Stateful APIs take explicit
+ context structs or caller-owned storage.
+- The initial implementation does not need a new public libkit API. Driver-side
+ support is enough until embeddings need the same facility.
+
+## Relationship to existing support libraries
+
+`libkit_rt.a` is part of the compiler substrate: integer/floating helpers,
+atomics, setjmp/coroutines, freestanding header support, and other pieces that
+compiled code may need even when the user did not ask for a utility library.
+The driver already resolves a target runtime variant, builds the archive on
+demand, caches it under `build/rt` or the user cache, and inserts it into the
+link at the policy point required by the target.
+
+`kitc` should reuse that shape, but with different policy:
+
+- headers are under `<kitc/...>`, not the freestanding libc header namespace;
+- symbols are prefixed with `kitc_`;
+- linking is explicit, normally via `-lkitc` or a driver sugar flag;
+- archive insertion is lazy and ordinary, just like any other static library;
+- hosted/OS-dependent helpers live in a separate component from freestanding
+ core utilities.
+
+By the time a link session sees `kitc`, it should be just another archive input.
+All special behavior belongs before linking: locating the source package,
+choosing the target variant, compiling the source set, caching the archive, and
+inserting the archive in the requested link order.
+
+## Source layout
+
+The library should live outside `rt/`:
+
+```text
+kitc/
+ include/
+ kitc/
+ base.h
+ vec.h
+ str.h
+ ...
+ src/
+ vec.c
+ str.c
+ ...
+ manifest.kitc
+ LICENSE
+```
+
+The manifest is the source of truth for the driver-side builder. It should
+record the library version, components, source files, public include roots, and
+target/feature gates. It should be canonical text so it can be hashed directly
+or stored as a CAS blob later.
+
+Possible component split:
+
+| Component | Scope |
+|-----------|-------|
+| `kitc-core` | Freestanding utilities: containers, string slices, hashing adapters, encoders, parsers, formatting into caller-provided buffers, no syscalls. |
+| `kitc-hosted` | File, environment, time, process, terminal, and other helpers that require hosted OS/libc facilities. |
+| `kitc-extra` | Optional heavier modules that should not be pulled in by the default utility library. |
+
+The default `-lkitc` spelling should start with `kitc-core`. Hosted helpers can
+be exposed as `-lkitc_hosted` or a later explicit feature flag.
+
+## Command-line surface
+
+The primary interface should be ordinary library spelling:
+
+```sh
+kit cc app.c -lkitc
+kit run script.c -lkitc
+kit cc -target aarch64-linux app.c -lkitc
+```
+
+A convenience flag such as `--kitc` can be added later, but it should lower to
+"add the kitc include root and lazy-link the selected kitc archive". The driver
+should not auto-link merely because a source included `<kitc/foo.h>`: include
+resolution and link input selection should stay separate.
+
+Header search policy can be friendlier than link policy. It is reasonable for
+the driver to add the `kitc/include` root to the system include set when Kit
+support headers are enabled, so a source can write:
+
+```c
+#include <kitc/vec.h>
+```
+
+But a reference to `kitc_vec_*` still requires an explicit library input.
+
+## On-demand build and cache identity
+
+The first implementation can mirror `driver/lib/runtime.c`:
+
+1. Resolve the active `KitTargetSpec`.
+2. Select the `kitc` variant/component from `manifest.kitc`.
+3. Build each source file with a `KitCompiler` configured for the target.
+4. Archive the resulting object builders or object bytes with `kit_ar_write`.
+5. Insert the archive path as a normal lazy archive input.
+
+The cache key should be content-based rather than only mtime-based:
+
+```text
+kitc source tree id
++ manifest version
++ component name
++ target triple / target key
++ object format and OS
++ ABI/data-model axes: pointer size, alignment, float ABI, long double, int128
++ -march / -mabi or equivalent target ISA options
++ codegen-affecting feature flags
++ debug/profile/sanitizer variant when those are supported
+```
+
+Recommended cache locations:
+
+```text
+<checkout>/build/kitc/<target-key>/<config-id>/libkitc.a
+$KIT_HOME/cache/kitc/<target-key>/<config-id>/libkitc.a
+```
+
+In a checkout or explicit support directory, prefer the in-tree cache so local
+development shares artifacts with `make` targets. In an installed distribution,
+prefer the user cache so the tool never writes into the install tree.
+
+Staleness should eventually be determined by the source tree id and config id.
+An initial mtime fallback is acceptable if the tree-id plumbing is not ready,
+but the design target is reproducible content identity.
+
+## Distribution
+
+`kitc` should be distributed as source, not as prebuilt target archives.
+
+Prebuilt archives multiply across architecture, OS, object format, ABI, ISA
+options, and feature flags. Source distribution keeps the package small and
+matches Kit's self-hosting story: any target Kit can compile can get a matching
+`kitc` archive on demand.
+
+Long-term distribution should use the existing signed package and CAS layers:
+
+1. Release packaging stores the `kitc` source tree as a CAS tree.
+2. A signed `.kpkg` claims the tree id, version, and metadata.
+3. Install or first use materializes the tree under the Kit support root, or
+ reads it from the local CAS when direct tree reads are available.
+4. The on-demand builder keys compiled archives by that source tree id plus the
+ target/config id.
+
+This gives `kitc` the same verification story as other support assets without
+requiring a new distribution format.
+
+## JIT and C scripts
+
+The JIT path should need no special linker support. For:
+
+```sh
+kit run script.c -lkitc
+```
+
+the driver should:
+
+1. Compile `script.c` to an object builder for the host-compatible target.
+2. Ensure the selected `libkitc.a` exists for that same target.
+3. Add `libkitc.a` as a lazy archive input after user objects.
+4. Add `libkit_rt.a` according to the existing runtime policy.
+5. Open a link session with `KIT_LINK_OUTPUT_JIT`.
+6. Call `kit_link_session_jit`.
+
+Because the JIT uses the same object, archive, relocation, and symbol-resolution
+machinery as file output, archive member selection should behave identically.
+If `kitc-hosted` calls host libc functions, those are resolved through the
+existing JIT extern resolver and call-stub/GOT machinery. `kitc-core` should not
+depend on that path.
+
+## Driver integration
+
+The first cut can stay driver-local:
+
+```text
+driver/lib/kitc.c
+driver/lib/kitc.h
+kitc/manifest.kitc
+kitc/include/...
+kitc/src/...
+```
+
+Proposed driver helper responsibilities:
+
+- locate the `kitc` source/support root;
+- parse or load the source manifest;
+- select a component and target variant;
+- compute or approximate the archive cache key;
+- build missing/stale archives;
+- return a `DriverArchiveInput` compatible with the existing link input set.
+
+`cc`, `ld`, and `run` should not grow independent `kitc` logic. They should call
+the shared helper when `-lkitc` or a future sugar flag requires it, then insert
+the returned archive through the same `DriverLinkInputSet` path used for other
+archives.
+
+If embeddings later need this feature, promote the concept into a public support
+library API. Until then, keeping it in the driver avoids freezing a broad API
+too early.
+
+## Link ordering
+
+For normal links, `libkitc.a` should appear where the user requested `-lkitc`.
+That preserves ordinary archive behavior and lets users control dependency
+order.
+
+For a future `--kitc` sugar flag, insert the archive after user source/object
+inputs and before the compiler runtime. This order lets user code pull needed
+`kitc` members lazily, and lets both user code and `kitc` pull compiler-runtime
+helpers as needed.
+
+Windows runtime special cases should remain owned by the runtime insertion code.
+`kitc` should not duplicate runtime archive placement rules.
+
+## Open questions
+
+- Manifest format: use a small canonical custom text format, or reuse a broader
+ package/build manifest format once that stabilizes?
+- Header availability: should `<kitc/...>` be on by default for `cc` and `run`,
+ or only enabled when `-lkitc`/`--kitc` is present?
+- Hosted split: should hosted helpers be a separate archive from day one, or a
+ component selected from one manifest?
+- Build coordinator integration: should `kitc` archive builds eventually be
+ modeled as content-addressed build targets, so remote trace reuse can avoid
+ rebuilding popular variants?
+- Version policy: is `kitc` versioned exactly with Kit releases, or can package
+ channels ship newer `kitc` source trees to older compatible Kit binaries?
+
+## Phased implementation
+
+### Phase 1: local source archive
+
+- Add the `kitc/` tree with a small freestanding `kitc-core` surface.
+- Add a driver-local builder modeled on runtime archive generation.
+- Recognize `-lkitc` and replace it with an ensured archive path.
+- Add targeted tests for `kit cc app.c -lkitc` and `kit run app.c -lkitc` on
+ the native target.
+
+### Phase 2: target matrix
+
+- Extend the variant table/manifest across the release support set.
+- Add cross-target archive build tests for a small source corpus.
+- Validate freestanding targets do not accidentally depend on hosted libc
+ symbols.
+
+### Phase 3: content identity
+
+- Compute a source tree id and config id for archive caches.
+- Stop relying on mtimes when content identity is available.
+- Share cache layout with the support/install root policy.
+
+### Phase 4: signed package distribution
+
+- Package the `kitc` source tree as a signed `.kpkg`.
+- Materialize it under the support root during install or first use.
+- Key archive builds by the package tree id.
+
+### Phase 5: broader library surface
+
+- Add hosted and optional components behind explicit link spellings.
+- Consider public support-library APIs only after the driver-local shape has
+ real users and stable requirements.
diff --git a/doc/plan/README.md b/doc/plan/README.md
@@ -18,6 +18,7 @@ shrinks to whatever remains open (and is deleted once nothing remains open).
| [ARM32.md](ARM32.md) | 32-bit ARM (`arm-none-eabi`, ARMv7-M/ARMv7E-M Thumb-2, Cortex-M3/M4/M7) freestanding backend: Phase 1 (walking skeleton) is landed; Phase 2 tracks the remaining ops, the -O1 known-frame path, 64-bit, atomics, TLS, and the `qemu-system-arm` cross-test lane. | [../ARCH.md](../ARCH.md), [../PORT.md](../PORT.md) |
| [MCU.md](MCU.md) | Microcontroller development workflow for STM32 Cortex-M (ARMv7-M/E-M) and Espressif RISC-V (ESP32-C/H/P): the last-mile gaps over the working backends — `objcopy` ihex/srec, reusable startup/vector-table + starter linker script, the rv32 soft-float-default footgun, SDK interop, and on-target debug. Assessment stage; references ARM32.md for ARM-core follow-ons. ARMv6-M/Cortex-M0 and Xtensa are out of scope. | [ARM32.md](ARM32.md), [../RUNTIME.md](../RUNTIME.md), [LINKER.md](LINKER.md) |
| [SYSROOTS.md](SYSROOTS.md) | Cross-compile sysroot packaging: minimal per-target stubs/headers/CRT objects distributed via `.kpkg` for the support set. Design complete, implementation not yet started. | — |
+| [KITC.md](KITC.md) | The planned `kitc` utility library: source distribution, on-demand target archive builds, driver integration, and JIT/script linking. | [../RUNTIME.md](../RUNTIME.md), [../LINK.md](../LINK.md), [../JIT.md](../JIT.md) |
| [TODO.md](TODO.md) | Open deferred fixes and code smells, plus terse backlog folded from retired plan docs (arch-backend parity, Wasm object backend, Windows x64 self-host, bootstrap breadth). Completed items are removed instead of checked off. A current backlog, not a roadmap. | — |
Speculative, not-committed designs (no code, parked) live in [`../ideas/`](../ideas/)