Build & Test Systems

Build system

Lilush uses a custom build generator (buildgen/generate.lua) that compiles Lua modules into LuaJIT bytecode, links them with C libraries, and produces a single static binary. The generator itself runs on plain LuaJIT with no external Lua dependencies.

Docker is used purely as a build medium — it provides the Alpine toolchain and LuaJIT, then runs the generator. No runtime images are produced.

Testing system

Lilush uses a minimal custom test framework called testimony (src/testimony/) for regression prevention and refactoring safety.

Tests live in tests/ and organized into subdirs per module.

Building

./build.bash [app]

app defaults to lilush. Available apps: lilu, lilush, reliw, recall, zxkitty. The built binary is placed in the repo root. To install system-wide, do sudo mv [app] /usr/[local]/bin/

Running Tests

Testing after recent changes

After making changes, build lilush and run:

File layout

Dockerfile                          Docker build template (takes APP build arg)
build.bash                          Build entry point
buildgen/
  generate.lua                      Build orchestrator (runs under luajit)
  c_tmpl                            C source template with preload infrastructure
  modinfo.lua                       Module registry (Lua module names -> C identifiers)
  default_main.c                    Default main() for apps without a custom one
  apps/
    version                         Version string (substituted into {{VERSION}})
    lilush.lua                      App config for lilush
    lilu.lua                        App config for lilu
    reliw.lua                       App config for reliw
    recall.lua                      App config for recall
    zxkitty.lua                     App config for zxkitty
  entrypoints/
    <app>/
      *.lua                         Lua entrypoint code (embedded as C string constants)
      main.c                        Custom main() (optional, per-app)

App configs

Each app config (buildgen/apps/<app>.lua) returns a table:

Build pipeline

What generate.lua does, in order:

  1. Load config — reads the app config and modinfo.lua

  2. Generate entrypoint constants — reads each .lua file referenced in start_code, escapes it for C, and emits static const char declarations

  3. Compile C modules — runs make -C src/<lib> for each C library, strips debug symbols from the resulting .o files

  4. Compile Lua modules — for each Lua module group, finds all .lua files under src/<mod>/, compiles each to a bytecode header with luajit -b, and patches the header to use the project's naming scheme

  5. Assemble C source — fills the c_tmpl template with:

    • {{START_CODE}} — the entrypoint constant declarations

    • {{LUAMODS}} — bytecode #includes and the lua_preload[] table

    • {{CLIBS}}extern declarations and the c_preload[] table

    • Appends the app's main() (custom or default)

    • Substitutes {{VERSION}} and {{APP_NAME}}

  6. Build static libraryar rcs all .o files into liblilush.a

  7. Link binaryclang with static linking against LuaJIT and liblilush.a

The output is written to /build/<binary> inside the Docker container.

Docker

Dockerfile accepts a single build arg APP (the app name). It installs the Alpine build toolchain, compiles LuaJIT from source, copies src/ and buildgen/ into the container, and runs generate.lua apps/${APP}.lua.

build.bash builds the Docker image, copies the binary out, and cleans up the container.

Build dependencies

Provided by the Docker image (Alpine):

Built from source inside Docker:

Cryptographic primitives are provided by LITLS (src/litls/), which ships in-tree and requires no external library installation.