kit

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

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

Non-goals

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:

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/:

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:

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:

#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:

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:

<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:

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:

driver/lib/kitc.c
driver/lib/kitc.h
kitc/manifest.kitc
kitc/include/...
kitc/src/...

Proposed driver helper responsibilities:

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

Phased implementation

Phase 1: local source archive

Phase 2: target matrix

Phase 3: content identity

Phase 4: signed package distribution

Phase 5: broader library surface