Kindler IR specification
This page is a draft by Raion.
Version: 1.0
Date: 2025-12-02
Status: Draft — targeted for Kindler 1.0 release
Purpose
This document defines the Kindler Intermediate Representation (IR) 1.0: a stable, deterministic, and minimal model used by Kindler and its tooling to describe projects, targets, and build artifacts for C and C++ (initial release). The IR is the canonical in-memory model used by Kindler’s parsers, validators, toolchain modules, and exporters.
Philosophy and goals
- Deterministic: .kindler files and the resulting IR do not perform globbing or implicit filesystem discovery. Tools may expand globs before writing .kindler, but Kindler itself requires explicit file lists.
- Declarative: the IR describes intent (what to build), not imperative compiler flags.
- Extensible: the IR is intentionally minimal but provides well-defined extension points for languages, toolchains, and exporters.
- Warnings-first: validation prefers prominent, actionable warnings over hard failures. Only structural corruption stops execution.
- Stable: schema changes should be backwards-compatible; versioning applied to caches and export formats.
Terminology
- Project: Top-level container for one or more Targets.
- Target: A build unit (executable, staticlib, sharedlib, header-only, object_group).
- Artifact: The produced file(s) from a Target (e.g.,
libfoo.a,app). - Toolchain: Compiler/Linker/Archiver set and their capabilities (provided by
compiler.hints). - OS hint: Operating system metadata (provided by
os.hints). - Exporter: Module that converts IR into a concrete build system (Makefile, Ninja, Meson, etc).
- Validator: Module that checks IR structural and semantic correctness and emits warnings/errors.
File formats and naming
- Project source format:
.kindler(UCL-like / TOML-like). Must be explicit; no globbing. - Hints:
os.hints.lua,compiler.hints.lua(human-editable Lua tables shipped with Kindler). - Cache: binary cache files written under system or per-user locations:
- System:
/etc/kindler/cache/ - User:
$HOME/.config/kindler/cache/
- System:
- IR is represented in memory as native Lua tables. Exporters may serialize the IR for debugging (JSON recommended).
Overall IR structure
Top-level IR is a table with these keys:
project(table) — top-level metadata and defaultstargets(table) — map:target_name→Targettoolchains(table) — optional, resolved toolchain info used at validation and exportmetadata(table) — free-form metadata (license, authors, etc)
Project object
Fields (all plain keys are strings unless noted):
name(string) — project name (required)version(string) — optionallanguages(array of language descriptors) — common languages used by the project; each descriptor:{ family="c"|"c++", standard="c89"|"c99"|"c11"|... }config(table) — project-level defaults applied to targets (see inheritance rules)targets(array or map) — convenience; canonical form is top-leveltargetsmap
Target object
Every Target is a map keyed by name. Required minimal target:
Common fields
name(string) — unique IDtype(enum) — one of the types abovelanguage(table) — as described in Language Modelsources(array of strings) — required for executable/library targets (empty allowed with warning)include_dirs(array of strings) — additional include pathssystem_include_dirs(array of strings) — system include paths (do not propagate in same way as project includes)definitions(map string->string or array) — preprocessor defines, equivalent to-DKEY=VALcflags(array of strings) — additional per-target C compiler flags (intent, not raw fs flags)cxxflags(array of strings) — additional C++ flagsldflags(array of strings) — additional linker flags (intentual)libs(array of strings) — external libraries (e.g.,m,pthread, or pkg-config logical names)pkg_config(array of strings) — names of required pkg-config packages (Kindler converts to include_dirs/libs/ldflags via a module)deps(array of strings) — other Kindler target names this target depends onvisibility(enum) —"public"or"private"; determines propagation of include_dirs/definitions to dependentsfeatures(map string->bool) — capability requests (e.g.,{ threads = true })generated_sources(array) — paths produced by generators (must be explicitly present)output_name(string) — override artifact name (optional)runtime_paths(array) — rpath entries for runtime linkingmetadata(table) — arbitrary key/value attachable metadata
Artifact object (computed)
artifactis derived by exporter but canonical shape:artifact.type(string)artifact.name(string)artifact.path(string)
Language model (1.0)
Minimal model for C/C++ initial release.
Language descriptor:
family—"c"or"c++"standard— C:"ansi"|"c89"|"c99"|"c11"; C++:"c++98"|"c++03"|"c++11"|"c++14"dialect— optional array of strings indicating vendor dialects, e.g.,{"gnu"}
Compiler hint mapping (in compiler.hints)
std_mapmaps canonical standard tokens to compiler flags orfalseif unsupported:- e.g.,
std_map["c11"] = "-std=c11"
- e.g.,
Toolchain selection in IR
toolchainsfield (project-level or target-level) lists preferred toolchains by name. The bootstrap must resolve an available cached toolchain or warn.
Validation rules
Summary:
- Structural validation: fatal only when IR is malformed or incomplete (missing required fields, wrong types).
- Semantic validation: non-fatal warnings by default — checks for incompatible or suspicious configurations (e.g., C++ standard not matching language family).
- Environment validation: uses cached
compiler.hintsandos.hintsto emit environment-specific warnings (e.g., requested standard unsupported by resolved compiler). - Policy: Kindler emits warnings, not hard errors (except structural fatal cases). Users may opt-in to treat warnings as errors.
Structural validation list (fatal)
project.namemust exist and be non-empty string.targetsmust be present and contain at least one target.- Each target must have
name,type, andlanguage. - Field types must match the schema (e.g.,
sourcesmust be array,namemust be string). - No duplicate target names.
Semantic validation list (warnings unless configured otherwise)
- Language family vs standard mismatch: e.g.,
family="c", standard="c++11"→ warn. - Target
typeconstraints:headerlibmay have no sources; executable must have at least one source (warning if empty). - Dependency cycles: flagged as fatal structural (cannot topologically order).
- Unused fields or deprecated keys: warn with code.
- Empty
sourcesorinclude_dirs: warn (advice).
Environment validation list (warnings)
- Requested
standardunsupported by resolved compiler (by cache): emitKIN-2xxwarning. - Required features (e.g.,
thread_local) unsupported: emitKIN-3xxwarning. pkg_configentries missing.pcfiles:KIN-4xx(warn).- Requested ABI not supported by toolchain:
KIN-5xx(warn). - Linker features (rpath) unsupported:
KIN-6xx(warn).
Warning and error codes
Kindler uses small, consistent codes to allow lookups:
- KIN-1xx — IR structural errors (fatal)
- KIN-2xx — Language/toolchain warnings (standards/flags)
- KIN-3xx — Feature compatibility warnings (thread-local, atomics)
- KIN-4xx — Dependency / package-config warnings
- KIN-5xx — ABI and OS compatibility warnings
- KIN-6xx — Linker/runtime warnings
- KIN-9xx — Advice / best-practices
Each warning includes:
- code (e.g.,
KIN-201) - severity (
warning/advice) - human-friendly message
- suggested remedy (optional)
- reference URL or local doc anchor (optional)
Examples:
Module hooks and extension points
Kindler core is small. Modules plug in at well-defined points.
Hook points:
- Parser — language modules can register syntax extensions and validators (e.g., a
cxx20module can parse extra target fields). - IR normalization — modules can provide normalizers that mutate IR in a controlled way (add defaults).
- Feature testers — runtime modules that can run checks using toolchains (optionally invoked during bootstrap).
- Exporter registration —
exportersimplementexport(ir, opts)and register by name (make,ninja,cmake). - Generators — codegen modules (protobuf, rpc, lex) can register producers of
generated_sourcesand a hook to run them.
Module API (high-level)
register_language(name, plugin_table)register_toolchain(name, resolver_fn)register_exporter(name, exporter_fn)register_validator(name, stage, validator_fn)
Cache usage and semantics
- Kindler reads toolchain and OS caches from
/etc/kindler/cache/(system) or${HOME}/.config/kindler/cache/(user). - Each hint entry is cached as a single binary blob per hint (e.g.,
os_irix65.bin,compiler_mipspro.bin). - Cache format is versioned. If cache missing or version mismatch, Kindler aborts and instructs user to rerun bootstrap.
- Cache exposes simple key→value flatten maps used by validators and exporter to map semantics to flags.
Exporters (how IR becomes a build script)
- Exporter receives resolved and normalized IR (after validation and toolchain resolution).
- Exporter responsibility:
- map IR concepts to concrete flags using toolchain hints
- respect
visibilitysemantics for include propagation - produce deterministic output (sorted lists, stable ordering)
- emit warnings if exporter-specific assumptions are met or violated
Example exporter responsibilities:
- Make exporter must avoid GNU extensions if
os.hintsindicates strict POSIX. - Ninja exporter outputs build edges and a DAG; Kindler may optionally produce dependency
.dfiles via the exporter.
Serialization for debug and CI
- Exporters should optionally be able to dump canonical IR in JSON for debugging and CI. This is a textual, read-only snapshot for humans and tools.
- DO NOT use the JSON dump as canonical cache input; caches are binary and versioned.
Example IR — Minimal (Lua)
Example .kindler snippet (UCL-like)
Validation lifecycle
- Parse
.kindlerfile → initial IR (syntactic) - Schema validation (fatal if corrupt)
- Normalization (apply defaults from project.config, expand pkg-config results if available)
- Semantic validation (warnings)
- Toolchain/OS validation with caches (warnings)
- Final IR normalization (flag ordering, include propagation)
- Export (use exporter modules)
Best practices for tool authors
- Tools that help produce
.kindlerfiles must expand globs before writing and record explicit file lists. - Default
visibilityfor include propagation should beprivateunless a library is intended to be used by dependents. - Keep
sourcesexplicit; do not rely on implicit discovery. - Always use toolchain hints to convert capability requests (e.g., PIC) to flags; exporters must not hardcode flags.
Backwards compatibility and versioning
- IR version 1.0 must be stable. Future versions must preserve old semantics or provide explicit migration guidance.
- Cache files are versioned; if Kindler’s cache version changes, users must rerun bootstrap. Kindler must detect and print actionable instructions.
Appendix A — Common warning codes (starter set)
- KIN-100: Missing required project.name (fatal)
- KIN-101: No targets defined (fatal)
- KIN-200: Language standard mismatch (warning)
- KIN-201: Selected standard unsupported by resolved compiler (warning)
- KIN-300: Feature unsupported by toolchain (warning)
- KIN-400: pkg-config package missing (warning)
- KIN-500: ABI mismatch between target and selected toolchain (warning)
- KIN-600: Linker rpath unsupported (warning)
- KIN-900: Advice messages (info)
Appendix B — Minimal IR schema (machine-friendly)
(For reference; not normative; used in unit tests and validation.)
project.name: string (required)project.version: string (optional)project.languages: array of{ family:string, standard:string, dialect?:array }targets: map<string, Target>Target.name: stringTarget.type: enumTarget.language: language descriptorTarget.sources: array<string>Target.include_dirs: array<string>Target.definitions: map<string,string> or array<string>Target.cflags,Target.cxxflags,Target.ldflags: array<string>Target.libs: array<string>Target.pkg_config: array<string>Target.deps: array<string>Target.features: map<string,bool>
Contributors and governance
Kindler IR is maintained by the Kindler core team. Changes to the IR must:
- Be proposed with rationale and migration plan.
- Include a deprecation period with warnings before hard changes.
- Be documented in release notes and online documentation.
License
Kindler IR specification and reference implementation are released under an OSI-approved license (choose project license e.g., MIT/Apache-2.0 — pick one and insert here).
Contact and further reading
- Kindler project repo:
<TBD URL> - Issue tracker:
<TBD URL> - Online manual: (document the KIN codes, examples, migration guides)