Kindler IR specification

From TechPubs Wiki

Revision as of 20:33, 2 December 2025 by Raion (talk | contribs) (Created page with "'''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 exp...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

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/
  • 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 defaults
  • targets (table) — map: target_nameTarget
  • toolchains (table) — optional, resolved toolchain info used at validation and export
  • metadata (table) — free-form metadata (license, authors, etc)

Project object

Fields (all plain keys are strings unless noted):

  • name (string) — project name (required)
  • version (string) — optional
  • languages (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-level targets map

Target object

Every Target is a map keyed by name. Required minimal target:

Common fields

  • name (string) — unique ID
  • type (enum) — one of the types above
  • language (table) — as described in Language Model
  • sources (array of strings) — required for executable/library targets (empty allowed with warning)
  • include_dirs (array of strings) — additional include paths
  • system_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=VAL
  • cflags (array of strings) — additional per-target C compiler flags (intent, not raw fs flags)
  • cxxflags (array of strings) — additional C++ flags
  • ldflags (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 on
  • visibility (enum) — "public" or "private"; determines propagation of include_dirs/definitions to dependents
  • features (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 linking
  • metadata (table) — arbitrary key/value attachable metadata

Artifact object (computed)

  • artifact is 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_map maps canonical standard tokens to compiler flags or false if unsupported:
    • e.g., std_map["c11"] = "-std=c11"

Toolchain selection in IR

  • toolchains field (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.hints and os.hints to 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.name must exist and be non-empty string.
  • targets must be present and contain at least one target.
  • Each target must have name, type, and language.
  • Field types must match the schema (e.g., sources must be array, name must 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 type constraints: headerlib may 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 sources or include_dirs: warn (advice).

Environment validation list (warnings)

  • Requested standard unsupported by resolved compiler (by cache): emit KIN-2xx warning.
  • Required features (e.g., thread_local) unsupported: emit KIN-3xx warning.
  • pkg_config entries missing .pc files: 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:

  1. Parser — language modules can register syntax extensions and validators (e.g., a cxx20 module can parse extra target fields).
  2. IR normalization — modules can provide normalizers that mutate IR in a controlled way (add defaults).
  3. Feature testers — runtime modules that can run checks using toolchains (optionally invoked during bootstrap).
  4. Exporter registrationexporters implement export(ir, opts) and register by name (make, ninja, cmake).
  5. Generators — codegen modules (protobuf, rpc, lex) can register producers of generated_sources and 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 visibility semantics 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.hints indicates strict POSIX.
  • Ninja exporter outputs build edges and a DAG; Kindler may optionally produce dependency .d files 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

  1. Parse .kindler file → initial IR (syntactic)
  2. Schema validation (fatal if corrupt)
  3. Normalization (apply defaults from project.config, expand pkg-config results if available)
  4. Semantic validation (warnings)
  5. Toolchain/OS validation with caches (warnings)
  6. Final IR normalization (flag ordering, include propagation)
  7. Export (use exporter modules)

Best practices for tool authors

  • Tools that help produce .kindler files must expand globs before writing and record explicit file lists.
  • Default visibility for include propagation should be private unless a library is intended to be used by dependents.
  • Keep sources explicit; 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: string
  • Target.type: enum
  • Target.language: language descriptor
  • Target.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:

  1. Be proposed with rationale and migration plan.
  2. Include a deprecation period with warnings before hard changes.
  3. 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)