Embedding libkit
Kit ships as both the kit multi-call executable and lib/libkit.a. The driver
is the reference host for the library: it uses the public headers under
include/kit/ and supplies the OS-facing callbacks that freestanding libkit
does not provide itself.
This document is the entry point for an application embedding compilation, objects, linking, JIT, debugging, packages, or builds. Exact signatures and ownership annotations live in the public headers; the architectural boundary inventory is in INTERFACES.md.
Link against the distribution
For an extracted native distribution:
ROOT=/path/to/kit
K="$ROOT/bin/kit"
"$K" cc -I "$ROOT/include" embed.c "$ROOT/lib/libkit.a" -o embed
./embed
Native support and SDK discovery follow the same rules as kit cc. An explicit
--support-dir, --sysroot, or -isysroot overrides discovery. The static
library has no extra user-selected dependency when linked through the native
hosted profile.
Include the narrow headers for the APIs in use; there is intentionally no
whole-library kit.h umbrella. Common entry points are:
| Task | Header |
|---|---|
| Context, compiler, writers, diagnostics | <kit/core.h> |
| Target profiles and triples | <kit/target.h> |
| High-level source compilation | <kit/compile.h> |
| Language/frontend code generation | <kit/frontend.h>, <kit/cg.h> |
| Objects and archives | <kit/object.h>, <kit/archive.h> |
| Linking and JIT publication | <kit/link.h>, <kit/jit.h> |
| Debug information and debugger sessions | <kit/dwarf.h>, <kit/dbg.h> |
| Content store and packages | <kit/cas.h>, <kit/package.h> |
| Content-addressed builds | <kit/build_coord.h> |
Host contract
Libkit is freestanding and owns no process-global host adapter. The embedder
constructs a KitContext and keeps its referenced callbacks alive for every
object that uses them.
The common context may provide:
KitHeapfor aligned allocation, reallocation, and release;KitDiagSinkfor diagnostics and maintained error/warning counters;KitFileIOwhen an API should resolve files through the host;- optional metrics and clock callbacks.
The heap callbacks must honor the requested alignment. Input slices are usually borrowed for the duration stated by the API; a context callback's user data must outlive every operation that can call it.
JIT and debugger operations require additional, deliberately separate host interfaces:
KitJitHostsupplies executable-memory reservation, protection, release, and instruction-cache flushing throughKitExecMem;KitDbgHostsupplies the thread, event, signal/trap, guarded-memory, and code-patching operations required by a debug session.
Keeping these interfaces separate means an embedder that only compiles or links does not need to provide executable-memory or signal machinery.
Common lifecycle
- Initialize the embedder-owned
KitHeap,KitDiagSink, optionalKitFileIO, andKitContext. - Parse a target with
kit_target_from_triple, or select a public target profile from<kit/target.h>. - Create a
KitTargetwithkit_target_new. - Create a
KitCompilerwithkit_compiler_neworkit_compiler_new_ex. - Create short-lived compile, object, link, JIT, debug, package, or build sessions under that compiler/context.
- Free sessions and builders before freeing the compiler; free the target after the compiler.
No mutable process-global compiler exists. Independent contexts and compiler handles may coexist, subject to the thread-safety rules documented by each specific public API.
Compile and link lifecycle
The high-level source path is defined by <kit/compile.h>:
- Fill
KitCompileSessionOptions, including the registered language and frontend input kind. - Create a
KitCompileSessionwithkit_compile_session_new. - Stage a caller-owned
KitSourceInputwithkit_compile_session_stage. Source names and bytes must remain valid for the duration documented by the header. - Consume the returned
KitObjBuilder: emit it, inspect it, or add it to a link session. - Publish the final output through a caller-owned
KitWriter. - Call
kit_compile_session_commitonly after publication succeeds. On every abandoned or failed staged path, callkit_compile_session_abort.
For a file image, create a KitLinkSession from <kit/link.h>, add object
builders or borrowed object/archive/DSO bytes in command-line order, resolve,
and emit through a KitWriter. The linker owns resolution and layout policy;
the caller owns its input buffers and output sink unless a specific API says
otherwise.
Cleanup is the reverse of construction:
writer -> link session -> object builder -> compile session
-> compiler -> target -> embedder-owned context services
Language frontends
A language can bypass the high-level compile session and emit directly through
KitCg from <kit/cg.h>. Frontends should include <kit/frontend.h>, the
tier-scoped front door that re-exports the code-generation, compile, source, and
arena facilities intended for frontend authors.
The frontend provides a KitFrontendVTable, registers it with the compiler,
and emits semantic operations into a KitObjBuilder. It does not own target
object formats, ABI layout policy, or linking. Those remain behind the public
codegen/object/link boundaries.
The C, cpp, and internal Toy frontends are built without access to src/
headers and are useful boundary examples. The Wasm frontend has one documented
internal-module exception; external frontends should not copy that exception.
See FRONTENDS.md and CODEGEN.md.
Object, JIT, and distribution paths
The public API is intentionally composable:
<kit/object.h>builds, reads, inspects, and rewrites format-neutral objects.<kit/archive.h>reads and writes POSIX archives.<kit/link.h>emits files or a JIT link image from the same object inputs.<kit/jit.h>publishes a resolved image through embedder-supplied executable memory.<kit/disasm.h>and<kit/dwarf.h>inspect code and debug information.<kit/cas.h>and<kit/package.h>expose content-addressed trees and signed packages without imposing network transport.<kit/build_coord.h>exposes the content-addressed build coordinator through a host scheduler/filesystem/process adapter.
The command-line tools are thin hosted examples of these compositions. They are not additional privileged entry points into libkit internals.
Error handling and ownership checklist
- Check every
KitStatus; diagnostics provide detail but do not replace status handling. - Keep borrowed source/object/archive buffers alive for the documented call or session lifetime.
- Close every writer and check its status before committing staged work.
- Abort an uncommitted compile session on every failure path.
- Free child sessions/builders before their compiler and target.
- Keep context services and their user pointers alive until all kit handles are gone.
- Supply executable-memory, TLS, signal, and thread hooks only to the JIT/debug operations that require them.