|
|
| Line 1: |
Line 1: |
| = Kindler Build System Specification =
| | '''Kindler''' is a flexible, declarative build system that is cross-platform. In fact, it was designed by [[User:Raion|Raion]] to explicitly support both modern Unix-likes and IRIX alike. |
| '''Version:''' 0.1.0 (Draft) | |
|
| |
|
| '''Last Updated:''' January 2026
| | == Availability == |
| | Kindler is going to be included in [[Nekoware]] but it can also be used with the Nekoware SDK, which offers Lua. |
|
| |
|
| '''Status:''' Design Phase
| | == Why Use Kindler for an IRIX project == |
| | Kindler understands mipspro. So does Autotools, but CMake? No. Meson? No. |
|
| |
|
| '''AI Disclosure:''' Claude and Grok provided assistance | | Kindler understands IRIX's limitations and gives verbose diagnostic info. |
| ----
| |
|
| |
|
| == 1. Overview ==
| | Kindler can coexist with Meson or CMake in the same project. |
| '''Kindler''' is a declarative, cached, bootstrapped build system for UNIX-like platforms. It does not build software directly—instead, it generates build files (Makefiles, Ninja files) that native build tools execute.
| |
| | |
| === Core Philosophy ===
| |
| | |
| # '''Portable:''' Runs on any POSIX-compliant system with Lua 5.1+
| |
| # '''Declarative:''' Project files describe ''what'' to build, not ''how''
| |
| # '''Non-blocking:''' Warns about problems but never prevents builds
| |
| # '''Generator-based:''' Outputs to Make/Ninja, doesn't reinvent the wheel
| |
| # '''Cached:''' Bootstraps once per system, reuses platform knowledge
| |
| # '''Interoperable:''' Plays nice with other build systems
| |
| | |
| === What Kindler IS ===
| |
| | |
| * A project description parser (UCL format)
| |
| * A platform/compiler database (hint files + cache)
| |
| * A discovery tool (bootstrap scanner)
| |
| * A build file generator (POSIX Make, GNU Make, Ninja)
| |
| * A module loader (Lua hooks for complex tasks)
| |
| | |
| === What Kindler IS NOT ===
| |
| | |
| * A compiler (it doesn't compile anything)
| |
| * A package manager (it doesn't fetch dependencies)
| |
| * A scripting language (no Turing-complete logic in project files)
| |
| * A build executor (Make/Ninja do the actual building)
| |
| * A replacement for CMake/Meson for all use cases
| |
| | |
| ----
| |
| | |
| == 2. Architecture ==
| |
| | |
| === 2.1 Bootstrap Phase ===
| |
| '''Purpose:''' One-time system profiling to build a knowledge cache.
| |
| | |
| '''Steps:'''
| |
| | |
| # Detect OS via <code>uname</code> and match against OS hints
| |
| # Load OS-specific hints file (<code>hints/os/<osname>.lua</code>)
| |
| # Scan for compilers listed in OS hints
| |
| # Detect available libraries (via pkg-config/pkgconf)
| |
| # Optionally scan system headers
| |
| # Serialize all findings to cache (<code>~/.config/kindler/cache/<hostname>.lua</code>)
| |
| | |
| '''Cache Format:''' Lua source files (portable, debuggable)
| |
| | |
| '''Cache Invalidation:''' 30-day TTL or manual re-bootstrap
| |
| ----
| |
| | |
| === 2.2 Project Files (UCL Format) ===
| |
| Projects are described in UCL (Universal Configuration Language), a human-readable, non-Turing-complete format.
| |
| | |
| '''Example:'''
| |
| | |
| ucl
| |
| <code>project {
| |
| name = "myapp";
| |
| lang = "c99";
| |
| version = "1.0.0";
| |
| }
| |
|
| |
| dependencies {
| |
| requires = ["mbedtls >= 2.16", "pthread"];
| |
| prefer = "static"; # or "shared", "any"
| |
| }
| |
|
| |
| build {
| |
| sources = ["main.c", "net.c", "util.c"];
| |
| output = "myapp";
| |
| type = "executable"; # or "static", "shared"
| |
| }
| |
|
| |
| config {
| |
| debug {
| |
| cflags = ["-g", "-O0"];
| |
| defines = ["DEBUG=1"];
| |
| };
| |
| release {
| |
| cflags = ["-O2"];
| |
| defines = ["NDEBUG"];
| |
| };
| |
| }</code>
| |
| '''Key Sections:'''
| |
| | |
| * <code>project</code> — Name, language, metadata
| |
| * <code>dependencies</code> — External libraries (resolved via pkg-config + OS hints)
| |
| * <code>build</code> — Source files, output, artifact type
| |
| * <code>config</code> — Build configurations (debug, release, custom)
| |
| * <code>modules</code> — Optional Lua modules for complex tasks
| |
| | |
| ----
| |
| | |
| === 2.3 Hints System ===
| |
| Hints are Lua tables that describe platform/compiler capabilities.
| |
| | |
| ==== OS Hints (<code>hints/os/<osname>.lua</code>) ====
| |
| lua
| |
| <code>return {
| |
| irix65 = {
| |
| posix = "yes",
| |
| architectures = {"sgi-mips", "sgi-mips64"},
| |
| compilers = {"mipspro", "gcc"}, ''-- native first''
| |
| endian = "big",
| |
| abi_list = {"n32", "o32", "n64"}, ''-- default first''
| |
| include_path = "/usr/include",
| |
| library_search_paths = {"/usr/lib", "/usr/lib32", "/usr/lib64"},
| |
| standard_libs = {"c", "m", "pthread"},
| |
| headers = {"stdio.h", "stdlib.h", "unistd.h", ...},
| |
| }
| |
| }</code>
| |
| | |
| ==== Compiler Hints (<code>hints/compiler/<compiler>.lua</code>) ====
| |
| lua
| |
| <code>return {
| |
| mipspro = {
| |
| architecture = {"sgi-mips", "sgi-mips64"},
| |
| ["compiler.drivers"] = {"/usr/bin/cc", "/usr/bin/c99", "/usr/bin/CC"},
| |
| languages = {"ansi-c", "c99", "c++98", "c++03"},
| |
| ["ansi-c.driver"] = "cc", ''-- Use `cc` for ANSI C''
| |
| ["c99.driver"] = "c99", ''-- Use `c99` for C99 (NOT cc -std=c99!)''
| |
| ["c++98.driver"] = "CC",
| |
| version_flag = "-version",
| |
| warning_flags = "-fullwarn",
| |
| pic_flag = "-KPIC",
| |
| shared_link_flags = "-shared",
| |
| rpath_flag = "-rpath",
| |
| uses_ranlib = "no",
| |
| atomic_builtins = "no",
| |
| thread_local = "no",
| |
| }
| |
| }
| |
| ```
| |
|
| |
| **Key Principle:** Hints describe *capabilities*, not build commands. The generator converts hints → build rules.
| |
|
| |
| ''---''
| |
|
| |
| ### 2.4 Dependency Resolution
| |
|
| |
| **Strategy:**
| |
| 1. Parse `dependencies.requires` from project file
| |
| 2. Check OS hints for `library_mappings` (platform-specific knowledge)
| |
| 3. Query pkg-config/pkgconf for library flags
| |
| 4. Fall back to generic search in `library_search_paths`
| |
| 5. Respect `dependencies.prefer` (static/shared/any)
| |
| 6. Warn if library not found, but don't block
| |
|
| |
| **Example Flow:**
| |
| ```
| |
| User requests: "mbedtls >= 2.16"
| |
| ↓
| |
| Check OS hints: library_mappings.mbedtls → {pkg_config = "mbedtls"}
| |
| ↓
| |
| Run: pkg-config ''--modversion mbedtls → "2.28.0" ✓''
| |
| ↓
| |
| Run: pkg-config ''--libs --static mbedtls → "-lmbedtls -lmbedx509 -lmbedcrypto"''
| |
| ↓
| |
| Cache result: mbedtls.libs = {...}</code>
| |
| ----
| |
| | |
| === 2.5 Build File Generation ===
| |
| '''Supported Targets:'''
| |
| | |
| * POSIX Make (maximum portability)
| |
| * GNU Make (extensions like pattern rules)
| |
| * Ninja (fast incremental builds)
| |
| | |
| '''Generator Responsibilities:'''
| |
| | |
| * Read project file + cache
| |
| * Resolve dependencies
| |
| * Select compiler based on language + OS hints
| |
| * Construct CFLAGS/LDFLAGS from hints + config
| |
| * Output build rules to target format
| |
| | |
| '''Example Output (POSIX Make):'''
| |
| | |
| make
| |
| <code># Generated by Kindler v0.1.0
| |
| # Config: debug
| |
|
| |
| CC = /usr/bin/c99
| |
| CFLAGS = -g -O0 -DDEBUG=1 -fullwarn
| |
| LDFLAGS =
| |
| LIBS = -lmbedtls -lmbedx509 -lmbedcrypto -lpthread
| |
|
| |
| OBJS = main.o net.o util.o
| |
|
| |
| all: myapp
| |
|
| |
| myapp: $(OBJS)
| |
| $(CC) $(OBJS) $(LIBS) -o myapp $(LDFLAGS)
| |
|
| |
| .c.o:
| |
| $(CC) $(CFLAGS) -c $
| |
|
| |
| clean:
| |
| rm -f $(OBJS) myapp</code>
| |
| ----
| |
| | |
| === 2.6 Module System ===
| |
| For complex tasks that exceed UCL's capabilities, users write '''Lua modules''' that hook into build phases.
| |
| | |
| '''Module Example:'''
| |
| | |
| lua
| |
| <code>''-- modules/version_gen.lua''
| |
| return {
| |
| name = "version_gen",
| |
| hooks = {"pre-build"},
| |
|
| |
| ["pre-build"] = function(context)
| |
| ''-- Generate version.h from git tags''
| |
| local handle = io.popen("git describe --tags")
| |
| local version = handle:read("*a"):gsub("\n", "")
| |
| handle:close()
| |
|
| |
| local f = io.open("version.h", "w")
| |
| f:write('#define VERSION "' .. version .. '"\n')
| |
| f:close()
| |
|
| |
| print("Generated version.h: " .. version)
| |
| end
| |
| }</code>
| |
| '''Hook Phases:'''
| |
| | |
| * <code>pre-parse</code> — Before reading project file
| |
| * <code>post-parse</code> — After parsing, before generation
| |
| * <code>pre-build</code> — After Makefile generation
| |
| | |
| '''Loading Modules:'''
| |
| | |
| ucl
| |
| <code>modules {
| |
| load = ["version_gen", "custom_checks"];
| |
| }</code>
| |
| ----
| |
| | |
| == 3. Supported Platforms (v0.1.0) ==
| |
| '''Target Systems:'''
| |
| | |
| * IRIX 6.5.x (MIPS, MIPS64)
| |
| * GNU/Linux (glibc 2.17+)
| |
| * NetBSD 9.0+
| |
| * FreeBSD 13.0+
| |
| * Solaris 11+ / OpenIndiana (if testable)
| |
| | |
| '''Required Tools:'''
| |
| | |
| * Lua 5.1, 5.2, 5.3, or 5.4
| |
| * POSIX shell (<code>/bin/sh</code>)
| |
| * <code>uname</code>, <code>test</code>, <code>mkdir</code>
| |
| * pkg-config or pkgconf (recommended)
| |
| * Make or Ninja
| |
| | |
| ----
| |
| | |
| == 4. Design Decisions ==
| |
| | |
| === 4.1 Why UCL? ===
| |
| | |
| * Human-readable (better than JSON, simpler than YAML)
| |
| * Not Turing-complete (forces separation of config vs. logic)
| |
| * Lua-parseable (no external dependencies)
| |
| | |
| === 4.2 Why Generate, Not Build? ===
| |
| | |
| * Leverage decades of Make/Ninja optimization
| |
| * Interoperate with existing toolchains
| |
| * Users get native incremental builds "for free"
| |
| | |
| === 4.3 Why Lua Source Caches? ===
| |
| | |
| * Portable across architectures (unlike bytecode)
| |
| * Fast to parse (Lua's parser is optimized)
| |
| * Debuggable (users can inspect/edit caches)
| |
| | |
| === 4.4 Why Non-Blocking Warnings? ===
| |
| | |
| * Developers know their toolchains better than Kindler does
| |
| * Experimental builds should be possible
| |
| * Kindler provides info, humans make decisions
| |
| | |
| === 4.5 Why Per-Driver Language Selection? ===
| |
| | |
| * Compilers like MIPSpro use ''different binaries'' for C89 vs C99
| |
| * GCC-style <code>-std=</code> flags are not universal
| |
| * Hints encode the "right way" per compiler
| |
| | |
| ----
| |
| | |
| == 5. Limitations & Non-Goals ==
| |
| '''Limitations:'''
| |
| | |
| * No dependency fetching (use system packages or vendor code)
| |
| * No cross-compilation auto-detection (user must bootstrap target system)
| |
| * No built-in testing framework (integrate with existing tools)
| |
| * No IDE integration (yet)
| |
| | |
| '''Non-Goals:'''
| |
| | |
| * Replace CMake/Meson for GUI apps or complex projects
| |
| * Compete with Bazel/Buck for monorepos
| |
| * Support Windows natively (WSL/Cygwin maybe)
| |
| * Implement a package manager
| |
| | |
| ----
| |
| | |
| == 6. Workflow Example ==
| |
| bash
| |
| <code>''# One-time bootstrap (per machine)''
| |
| $ kindler bootstrap
| |
| Detecting OS... IRIX 6.5.30
| |
| Found compilers: mipspro (/usr/bin/cc), gcc (/usr/local/bin/gcc)
| |
| Scanning headers... 342 found
| |
| Cache written: ~/.config/kindler/cache/sgi-onyx.lua
| |
|
| |
| ''# Generate build files''
| |
| $ cd myproject/
| |
| $ kindler generate --config=debug --target=make
| |
| Reading: project.ucl
| |
| Resolving dependencies... mbedtls [OK], pthread [OK]
| |
| Generating: Makefile (POSIX)
| |
|
| |
| ''# Build (using native tools)''
| |
| $ make
| |
| cc -g -O0 -DDEBUG=1 -c main.c
| |
| cc -g -O0 -DDEBUG=1 -c net.c
| |
| cc main.o net.o -lmbedtls -lpthread -o myapp
| |
|
| |
| ''# Switch configs''
| |
| $ kindler generate --config=release --target=ninja
| |
| Generating: build.ninja (Ninja)
| |
| $ ninja
| |
| [2/2] Linking myapp</code>
| |
| ----
| |
| | |
| == 7. Future Considerations (Post-v1.0) ==
| |
| | |
| * IDE plugins (VSCode, Vim)
| |
| * CI/CD templates
| |
| * Cross-compilation wizard
| |
| * Hint database versioning
| |
| * Community hint repository
| |