kit
Kit is a BusyBox for compilation: one multi-call executable and one C library covering the compiler, linker, binary utilities, execution runtimes, package distribution, and builds.
A conventional toolchain is assembled from several layers. cc coordinates
preprocessing, compilation, assembly, and linking; binutils handles archives and
object inspection; JIT and WebAssembly runtimes are separate again; build and
package systems sit above and after them. Kit gives those layers a shared target
registry, object model, linker, content store, and public API.
Kit is implemented in freestanding C11. It does not require a C++ compiler to
bootstrap, has no mutable global state, and makes host services explicit through
context structs and vtables. The kit executable is the reference host for
libkit.a, not a separate implementation wrapped around it.
For a longer introduction, including representative compile-speed and code-size comparisons, see Introducing kit.
Quick start
From a source checkout:
make bin
K=build/kit
From an extracted release:
K=bin/kit
Compile, inspect, and run a native program:
printf 'int main(void) { return 0; }\n' > hello.c
"$K" cc hello.c -o hello
"$K" objdump -h -t hello
./hello
"$K" run hello.c
"$K" run --no-jit hello.c
Native distributions discover their sibling support tree automatically. Native
macOS builds also discover and apply the SDK. An explicit --support-dir,
--sysroot, or -isysroot remains an authoritative override.
Inspect the compiled target profiles before cross-compiling:
"$K" targets
"$K" targets aarch64-linux-gnu
"$K" cc -target aarch64-linux-gnu --sysroot /path/to/sysroot \
-c hello.c -o hello.aarch64.o
Hosted cross targets currently require an appropriate SDK or sysroot.
Freestanding targets use kit's shipped runtime sources and caller-supplied
startup/linker policy. Signed .kpkg SDK distribution is planned; see
the sysroot plan.
Install the multi-call binary under conventional tool names:
mkdir -p "$HOME/.local/bin"
"$K" install "$HOME/.local/bin"
Kit creates symlinks on POSIX and hard links on Windows. kit cc ... and an
installed cc ... invoke the same command implementation.
What is included
| Surface | Commands and APIs |
|---|---|
| Compilation | C11 preprocessor/compiler, assembly, cc, check, cpp, as, ld, build-exe, build-lib, build-obj |
| Binary tools | ar, ranlib, nm, size, strip, objcopy, objdump, addr2line, symbolize, strings, disas, mc, image, cpio |
| Execution | Native JIT with run, IR interpreter with run --no-jit, interactive dbg, Wasm/WAT execution with explicit host-resource policy |
| Targets | AArch64, x86-64, RISC-V, Arm freestanding, and wasm32 across ELF, Mach-O, COFF/PE, and Wasm profiles |
| Distribution | Content-addressed cas, signed .kpkg/portable packages with pkg, managed release installation and rollback with update |
| Builds | Content-addressed build targets, tests, configuration profiles, declared recipe inputs, dependency traces, external repositories, and output trees |
| Data tools | SHA-256, BLAKE2b-256, CRC-32, gzip, LZ4 frame, xxd, and cmp, including conventional command aliases |
| Generation | gram EBNF-to-C parser/lexer generation with allocation-free push runtimes |
| Library | Public C APIs for compilation, code generation, objects, linking, JIT, debugging, DWARF, archives, hashing, compression, CAS, packages, builds, and targets |
Run kit --help for the compiled tool inventory and kit help COMMAND for the
authoritative command-line reference.
Packages and trust
Kit separates content identity from trust. Blobs and canonical directory trees are addressed by BLAKE2b-256 and can come from an untrusted store. A canonical package manifest names output trees and artifact roles; a Minisign-compatible Ed25519 signature authorizes that claim.
kit pkg keygen -o release-key
kit pkg create --name app --version 1 -s release-key.key \
--root out -o app.kpkg
kit pkg verify -p release-key.pub app.kpkg
kit pkg unpack --verify -p release-key.pub app.kpkg -C installed
The native .kpkg representation may be fat, metadata-rich, or thin. A
portable .tar.gz representation carries the same signed logical package. Kit
uses this machinery for its own releases and authenticates both the release
channel and selected package before kit update changes the active toolchain.
See Code distribution and Releasing and updating kit.
Build system
kit build is a build system, not an alias for cc. A package-local
BUILD.kit maps target labels to recipe executables. Recipes receive a clean
environment, write an output directory, and declare configuration, source,
glob, fetch, and target dependencies through the recipe protocol.
kit-build 1
[target app]
recipe recipes/app.sh
kit build //:app
Outputs are canonical content-addressed trees. Deep traces handle unchanged transitive inputs; shallow traces can reuse a parent when a changed dependency rebuilds to the same output. The current contract relies on recipes declaring all cache-visible inputs; filesystem hermeticity enforcement and build-store garbage collection remain future work.
See Content-addressed build coordinator.
Optimization and scope
-O0 emits through the direct native backend. -O1 records IR and runs the
fast, non-SSA optimization and register-allocation pipeline. -O2 is currently
accepted as an alias for -O1; the distinct SSA mid-end is maintained but not
yet enabled as a public optimization level.
Kit is not intended to hide its current boundaries:
- Hosted cross-compilation needs target system files;
kit targetsreports the provisioning model separately from compiler capability. - Shared-library creation is currently an ELF feature.
- Wasm supports same-invocation source builds and partial WASI, not general separate-object/archive linking or complete WASI.
- Debugger and execution support depends on the host/profile reported by the target registry.
Embedding and bootstrapping
An embedder owns the host callbacks and the lifetime of its KitContext, target,
compiler, compile/object/link sessions, and writers. The public headers are the
API contract; the driver and most frontends are built against the same boundary
without access to internal headers.
See Embedding libkit, Design, and Interfaces.
Kit's normal self-host check starts from a host C compiler, builds kit, and then uses kit for two more stages. Stage 2 and stage 3 must be byte-identical. Because the implementation is C, replacing the initial compiler with a smaller seed does not require first constructing a C++ toolchain; a minimal/diverse seed is a separate trust project, not a claim of the current build.
Documentation
Start with the documentation map. Common routes are:
| Task | Documentation |
|---|---|
| Learn the architecture | DESIGN.md |
| Use and extend the CLI | DRIVER.md |
| Inspect targets and portability lanes | PORT.md |
| Embed the library | EMBEDDING.md, INTERFACES.md |
| Package and authenticate artifacts | DISTRIBUTE.md |
| Define builds | BUILD_COORDINATOR.md |
| Work on kit itself | BUILD.md, TESTING.md |
| Measure performance and size | BENCHMARKING.md, CODE_SIZE.md |
Durable doc/*.md files describe implemented behavior. Forward-looking work is
under doc/plan; speculative designs are under
doc/ideas.
Building and testing
make lib # libkit.a
make bin # kit
make rt # libkit_rt.a
Prefer the targeted suites listed in TESTING.md. Portability and self-host testing are separately provisioned and documented in PORT.md.