No description
Find a file
Rolando Abarca 77012ba139
All checks were successful
Release / build (push) Successful in 30s
Add static binary support and link-flags spec option
Compile modules as units (-c -unit) for static builds and link them
into a single self-contained binary. Add link-flags spec option for
extra linker flags needed by egg dependencies (e.g. -lssl -lcrypto).
2026-02-27 17:56:28 -08:00
.forgejo/workflows Use default dist/release dir for release assets 2026-02-24 22:24:12 -08:00
tests Switch build specs to .lsp extension, add -p flag, deployed option, fix chicken.* classification 2026-02-24 21:57:18 -08:00
.gitignore Add auto-discovery, parallel compilation, example build spec, and static linkage 2026-02-24 16:00:16 -08:00
build.example.lsp Add static binary support and link-flags spec option 2026-02-27 17:56:28 -08:00
build.lsp Switch build specs to .lsp extension, add -p flag, deployed option, fix chicken.* classification 2026-02-24 21:57:18 -08:00
discover.scm Switch build specs to .lsp extension, add -p flag, deployed option, fix chicken.* classification 2026-02-24 21:57:18 -08:00
kdp-build.egg Add auto-discovery, parallel compilation, example build spec, and static linkage 2026-02-24 16:00:16 -08:00
LICENSE first commit 2026-02-24 15:57:03 -08:00
main.scm Add static binary support and link-flags spec option 2026-02-27 17:56:28 -08:00
native.scm first commit 2026-02-24 15:57:03 -08:00
README.md Switch build specs to .lsp extension, add -p flag, deployed option, fix chicken.* classification 2026-02-24 21:57:18 -08:00
scheme.scm Add static binary support and link-flags spec option 2026-02-27 17:56:28 -08:00
spec.scm Add static binary support and link-flags spec option 2026-02-27 17:56:28 -08:00
utils.scm first commit 2026-02-24 15:57:03 -08:00

kdp-build

A declarative build system for CHICKEN Scheme applications that mix Scheme modules with native C/C++/Objective-C code.

Why?

CHICKEN's chicken-install is designed for building and installing eggs — libraries and simple programs. It works well for that purpose, but complex applications often need more:

  • Native code with per-file control: Different source files compiled with different compilers (clang, clang++, c++) and different flags. Objective-C .mm files next to C++ .cpp files next to plain C, each with their own include paths and framework dependencies.
  • Static libraries from external sources: Clone a git repository, apply patches, compile dozens of C++ files into a .a archive — all before any Scheme code is touched.
  • Shell variable expansion in flags: $(pkg-config --cflags sdl2) evaluated at build time, per-module and per-object.
  • FFI modules with distinct link flags: Each FFI wrapper links against different native objects and system frameworks. One module needs -framework AVFoundation, another needs -framework MapKit, a third needs $(pkg-config --libs libavcodec).
  • Incremental builds: Only recompile what changed, based on file timestamps.
  • macOS application bundling: Deployment targets, framework linking, resource bundling into .app bundles.

The .egg format has (custom-build ...) for running arbitrary scripts, but that defeats the purpose of a declarative build. kdp-build keeps the build specification readable while handling the complexity.

Install

chicken-install

Or from a local checkout:

cd kdp-build
chicken-install

Usage

Create a build.lsp in your project root, then run:

kdp-build [command] [options]

Commands

Command Description
build Build all targets (default)
clean Remove build artifacts
rebuild Clean then build
list-modules Print all module names
deps Print required eggs (direct)
deps-deep Print all eggs including transitive dependencies
help Show help

Options

Option Description
-p, --project NAME Use build.<NAME>.lsp as spec file
--verbose, -v Show all executed commands
--release Use release flags (-O3 -d0)

Build Specification

A build.lsp file describes your project:

(build-spec
  (app-name "my-app")
  (macos-deployment-target "13.0")
  (csc-flags "-d3 -O0 -c++")

  ;; Egg dependencies
  (eggs srfi-1 srfi-18 sqlite3)

  ;; Static libraries from C/C++ sources
  (static-libs
    (mylib.a
      (sources "vendor/foo.cpp" "vendor/bar.cpp")
      (cxx-flags "-std=c++11 -Ivendor")
      (setup
        "test -d vendor || git clone https://example.com/vendor.git")))

  ;; Native objects: (name source compiler flags)
  (native-objects
    (helper.o "helper.c" "clang" "")
    (bridge.o "bridge.mm" "clang++" "-std=c++11 -fobjc-arc"))

  ;; FFI modules: (name (objects...) (compile-flags...) (link-flags...))
  (ffi-modules
    (my-ffi (helper.o bridge.o)
      ("-Ivendor")
      ("-framework Foundation")))

  ;; Pure Scheme modules (compiled in order)
  (modules config utils main-window)

  ;; Entry point
  (app-entry "app.scm")

  ;; macOS bundle resources
  (bundle-resources "assets/icon.png" "fonts/*.ttf"))

Build Order

  1. Setup — Run setup commands for static libraries (e.g., git clone, patch)
  2. Static libraries — Compile C/C++ sources into .a archives
  3. Native objects — Compile individual .c, .cpp, .mm files
  4. FFI modules — Compile Scheme FFI wrappers, linking against native objects
  5. Pure modules — Compile Scheme modules in declared order
  6. Application binary — Link everything into a deployed executable

Spec Reference

Field Description
app-name Output binary name
macos-deployment-target Minimum macOS version (default "13.0")
csc-flags Base flags passed to csc for all Scheme compilation
eggs Egg dependencies for bundled deployment
static-libs C/C++ static libraries to build from source
native-objects Individual C/C++/ObjC files to compile
ffi-modules Scheme modules that wrap native code
modules Pure Scheme modules
deployed Build binary with -deployed for private repository (#t/#f, default #f)
app-entry Scheme source file for the application entry point
bundle-resources Files to include in macOS .app bundle

License

BSD-3-Clause — Rolando Abarca