Complete guide to building Kairos from source, with all configuration options, cross-platform instructions, and testing procedures.
- Prerequisites
- Quick Build
- Build Scripts (Recommended)
- Manual CMake Build
- CMake Feature Flags
- Build Profiles
- CMake Presets
- Sanitizer Builds
- Testing
- Packaging
- Docker Build
- CI/CD Pipeline
- IDE Integration
- Troubleshooting
sudo apt-get update
sudo apt-get install -y \
cmake \ # >= 3.21
g++ \ # >= 12 (C++20 support)
libsqlite3-dev \ # SQLite development headers
git # For FetchContent downloads
# Optional: for packaging
sudo apt-get install -y dpkg-dev rpm # DEB + RPMsudo dnf install cmake gcc-c++ sqlite-devel git
# Optional: rpm-build for RPM packaging# Xcode Command Line Tools (provides AppleClang)
xcode-select --install
# Dependencies via Homebrew
brew install cmake sqlite3- Install Visual Studio 2022 (Community is free) with the "Desktop development with C++" workload.
- Alternatively, install Build Tools for Visual Studio 2022.
- CMake is included with VS, or install standalone from cmake.org.
- Git for Windows from git-scm.com.
Open a Developer PowerShell for VS 2022 or x64 Native Tools Command Prompt for builds.
| Feature | Dependency | Install |
|---|---|---|
HTTP server (KAIROS_HTTP) |
(bundled via FetchContent) | No extra install needed |
OpenTelemetry (KAIROS_OTEL) |
opentelemetry-cpp | System install or FetchContent |
Vault secrets (KAIROS_VAULT) |
OpenSSL >= 1.1 | apt install libssl-dev / brew install openssl |
Docker runner (KAIROS_DOCKER) |
Docker CLI on PATH | Install Docker Desktop or Docker Engine |
TUI dashboard (KAIROS_TUI) |
FTXUI | FetchContent (automatic) |
The fastest path from clone to running binary:
# Clone
git clone https://github.com/araray/kairos.git
cd kairos
# Build (debug, with tests)
cmake -B build -DCMAKE_BUILD_TYPE=Debug -DKAIROS_BUILD_TESTS=ON
cmake --build build -j$(nproc) # Linux/macOS
cmake --build build -j # Windows (auto-detects cores)
# Test
cd build && ctest --output-on-failure
# Run
./build/kairos versionThe build scripts provide a richer experience with colored output, profiles, sanitizer support, and packaging.
# Default debug build with tests
./scripts/build.sh
# Release build
./scripts/build.sh --release
# Clean rebuild
./scripts/build.sh --clean --release
# All features enabled
./scripts/build.sh --profile full
# Sanitizer build (ASan + UBSan)
./scripts/build.sh --profile san
# Use Clang instead of GCC
./scripts/build.sh --compiler clang
# Build + generate DEB package
./scripts/build.sh --release --http --package-deb
# Dry run (show CMake commands without executing)
./scripts/build.sh --release --http --dry-run
# Full option reference
./scripts/build.sh --help# Default debug build
.\scripts\build.ps1
# Release build
.\scripts\build.ps1 -Release
# Sanitizer build (ASan)
.\scripts\build.ps1 -Profile san
# Full-featured build
.\scripts\build.ps1 -Profile full
# Clean rebuild
.\scripts\build.ps1 -Clean -Release
# Help
.\scripts\build.ps1 -ShowHelp| Option | Description | Default |
|---|---|---|
--debug / --release / --relwithdebinfo / --minsizerel |
Build type | Debug |
--tests / --no-tests |
Build test suite | ON |
--http |
Enable HTTP server + Web UI | OFF |
--otel |
Enable OpenTelemetry tracing | OFF |
--vault |
Enable Ansible Vault support (requires OpenSSL) | OFF |
--docker |
Enable Docker runner | OFF |
--tui |
Enable TUI dashboard (FTXUI) | OFF |
--asan / --ubsan / --tsan |
Individual sanitizers | OFF |
--sanitizers |
ASan + UBSan together | OFF |
--compiler gcc / --compiler clang |
Select compiler | System default |
--clean |
Remove build directory before configuring | false |
--build-dir <path> |
Custom build directory | build/<type> |
--prefix <path> |
Install prefix | /usr/local |
--install |
Build then install | false |
--configure-only |
Configure without building | false |
--dry-run |
Print commands without executing | false |
--verbose |
Verbose build output | false |
-j <N> / --jobs <N> |
Parallel build jobs | Auto (nproc) |
--package |
Generate all packages (DEB + RPM + ZIP) | false |
--package-deb / --package-rpm / --package-zip |
Specific package | false |
-- <args...> |
Pass extra arguments to CMake |
For full control over the build process.
# Configure
cmake -B build \
-DCMAKE_BUILD_TYPE=Release \
-DKAIROS_BUILD_TESTS=ON \
-DKAIROS_HTTP=ON \
-DKAIROS_VAULT=ON \
-DKAIROS_DOCKER=ON
# Build
cmake --build build -j$(nproc)
# Install
sudo cmake --install build --prefix /usr/local# Configure (Visual Studio generator)
cmake -B build -G "Visual Studio 17 2022" -A x64 `
-DKAIROS_BUILD_TESTS=ON `
-DKAIROS_HTTP=ON
# Build
cmake --build build --config Release -j
# Install
cmake --install build --config Release --prefix C:\kairos# From Developer PowerShell
cmake -B build -G Ninja `
-DCMAKE_BUILD_TYPE=Release `
-DKAIROS_BUILD_TESTS=ON
cmake --build build -jThese are defined in cmake/KairosOptions.cmake:
| Flag | Description | Default | Extra Dependencies |
|---|---|---|---|
KAIROS_BUILD_TESTS |
Build test suite (Google Test) | ON |
None (fetched) |
KAIROS_HTTP |
Build HTTP server and Web UI | OFF |
cpp-httplib, inja (fetched) |
KAIROS_OTEL |
Build with OpenTelemetry tracing | OFF |
opentelemetry-cpp (system) |
KAIROS_VAULT |
Build with Ansible Vault decryption | OFF |
OpenSSL >= 1.1 (system) |
KAIROS_DOCKER |
Build with Docker runner support | OFF |
None (shells to Docker CLI) |
KAIROS_TUI |
Build TUI dashboard (FTXUI) | OFF |
FTXUI (fetched) |
KAIROS_USE_SYSTEM_DEPS |
Prefer system-installed libs over FetchContent | OFF |
Varies |
KAIROS_EMBED_ASSETS |
Embed web assets into binary | ON |
None |
Enable a flag by passing -D<FLAG>=ON to CMake:
cmake -B build -DKAIROS_HTTP=ON -DKAIROS_VAULT=ON -DKAIROS_DOCKER=ONBy default, all dependencies are fetched via CMake FetchContent at configure time. This requires internet access during the first build. Subsequent builds use cached downloads.
To use pre-cloned or system-installed dependencies:
# Point to a pre-cloned confy-cpp
cmake -B build -DFETCHCONTENT_SOURCE_DIR_CONFY-CPP=/path/to/confy-cpp
# Use system-installed libraries
cmake -B build -DKAIROS_USE_SYSTEM_DEPS=ONFeature flags control which source files are compiled:
| Flag | Compiled Sources | Stub Sources (when OFF) |
|---|---|---|
KAIROS_HTTP |
src/http/http_server.cpp |
(excluded entirely) |
KAIROS_VAULT |
src/security/secret_store.cpp |
src/security/secret_store_stub.cpp |
KAIROS_DOCKER |
src/exec/docker_process_handle.cpp |
src/exec/docker_process_handle_stub.cpp |
KAIROS_OTEL |
src/observability/otel_tracer.cpp |
src/observability/null_tracer.cpp |
Platform-specific sources are automatically selected:
| Platform | Process Execution | Instance Lock | Paths | Signals | Terminal |
|---|---|---|---|---|---|
| POSIX | process_handle_posix.cpp |
instance_lock_posix.cpp |
paths_posix.cpp |
signals_posix.cpp |
terminal_posix.cpp |
| Windows | (future: process_handle_win32.cpp) |
(future) | (future) | (future) | (future) |
Profiles are predefined bundles of options. Use --profile <name> with the build scripts.
| Profile | Build Type | Tests | Features | Sanitizers |
|---|---|---|---|---|
dev |
Debug | ON | None | None |
san |
Debug | ON | None | ASan + UBSan |
release |
Release | OFF | None | None |
ci |
Debug | ON | None | ASan + UBSan |
full |
Release | ON | HTTP, OTel, Vault, Docker | None |
full-debug |
Debug | ON | HTTP, OTel, Vault, Docker | None |
full-san-debug |
Debug | ON | HTTP, OTel, Vault, Docker | ASan + UBSan |
package |
Release | OFF | HTTP, Vault, Docker | None + DEB/RPM/ZIP |
CMakePresets.json provides named presets for common configurations:
# List available presets
cmake --list-presets
# Use a preset
cmake --preset debug
cmake --build --preset debug
cmake --preset release
cmake --build --preset releaseSanitizers detect memory errors, undefined behavior, and data races at runtime.
./scripts/build.sh --asan
# or manually:
cmake -B build -DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_CXX_FLAGS="-fsanitize=address -fno-omit-frame-pointer"Detects: use-after-free, buffer overflows, stack overflows, memory leaks.
./scripts/build.sh --ubsanDetects: signed integer overflow, null pointer dereference, misaligned access, shift errors.
./scripts/build.sh --tsanDetects: data races between threads. Cannot be combined with ASan.
./scripts/build.sh --sanitizers
# or:
./scripts/build.sh --profile sanThis is the recommended sanitizer configuration for development.
MSVC supports ASan via /fsanitize=address:
.\scripts\build.ps1 -Profile sanUBSan and TSan are not available on MSVC. Use GCC or Clang for full sanitizer coverage.
Kairos includes over 1100 tests organized by module:
| Category | Location | Description |
|---|---|---|
| Unit tests | tests/unit/ |
Per-module tests (KEL, DAG, scheduler, config, persistence, etc.) |
| Integration tests | tests/integration/ |
Config reload, HTTP API, YAML wiring, watch integration |
| End-to-end tests | tests/e2e/ |
Full daemon lifecycle tests |
# Linux / macOS
./scripts/test.sh # Run all tests
./scripts/test.sh --filter "Kel" # Filter by test name
./scripts/test.sh --list # List all tests without running
./scripts/test.sh --verbose # Full output
./scripts/test.sh --repeat 5 # Stress test (run 5 times)
./scripts/test.sh --rerun-failed # Rerun only previously failed tests
./scripts/test.sh --stop-on-fail # Stop at first failure
./scripts/test.sh --help # Full option reference
# Windows
.\scripts\test.ps1
.\scripts\test.ps1 -Filter "Kel"
.\scripts\test.ps1 -List
.\scripts\test.ps1 -Verbosecd build
ctest --output-on-failure # All tests
ctest --output-on-failure -R "kel" # Filter by regex
ctest --output-on-failure -j$(nproc) # Parallel execution
ctest --output-on-failure --timeout 120 # Per-test timeout
ctest --output-on-failure --rerun-failed # Rerun failures
ctest --output-on-failure -L unit # Only unit tests
ctest --output-on-failure -L integration # Only integration tests# Run a specific test binary
./build/tests/unit/test_kel_evaluator
# With Google Test flags
./build/tests/unit/test_kel_evaluator --gtest_filter="*Duration*"
./build/tests/unit/test_kel_evaluator --gtest_list_tests
./build/tests/unit/test_kel_evaluator --gtest_repeat=10
./build/tests/unit/test_kel_evaluator --gtest_shuffleTest binaries are organized by module:
tests/
├── unit/
│ ├── cli/ # CLI table rendering, completions
│ ├── config/ # ConfigStore, validation, YAML loader
│ ├── core/ # ID generator, exit codes
│ ├── daemon/ # Command reader
│ ├── engine/ # DAG, pipeline, scheduler, triggers, explain
│ ├── exec/ # Process handle, runner pool, env builder, Docker
│ ├── http/ # HTTP server
│ ├── kel/ # Lexer, parser, evaluator (most comprehensive)
│ ├── mcp/ # MCP handler, transport, log streaming
│ ├── migration/ # Legacy tool migration (17 tests)
│ ├── observability/ # JSON formatter, metrics, tracer
│ ├── persist/ # Schema migration, DB writer, queries, retention
│ ├── platform/ # Path normalization
│ ├── security/ # Secret store
│ ├── testing/ # Fake clock
│ └── watch/ # Watch engine, scanner, debounce, hash, rules
├── integration/ # Cross-module integration tests
├── e2e/ # Full daemon lifecycle tests (7 tests)
└── helpers/ # Test utilities (test_helpers.hpp)
Tests use Google Test and follow these conventions:
- Each source file has a corresponding
_test.cppin the matching test directory. - Tests use temporary directories (via
std::filesystem::temp_directory_path()) to avoid filesystem conflicts. - Time-sensitive tests use
kairos::testing::FakeClockinstead of real clocks. - Database tests create in-memory SQLite databases (
:memory:) or temporary files.
Example test structure:
#include <gtest/gtest.h>
#include "kairos/kel/evaluator.hpp"
class KelEvaluatorTest : public ::testing::Test {
protected:
kairos::kel::EvalContext ctx_;
kairos::kel::EvalLimits limits_;
void SetUp() override {
ctx_ = kairos::kel::make_default_context();
}
};
TEST_F(KelEvaluatorTest, BooleanLiteral) {
auto result = kairos::kel::eval_expression("true", ctx_, limits_);
EXPECT_TRUE(result.is_bool());
EXPECT_TRUE(result.as_bool());
}After building, generate packages using CPack:
# Build first
./scripts/build.sh --release --http --no-tests
# Generate all packages
cd build/release
cpack # All generators
cpack -G DEB # Debian package only
cpack -G RPM # RPM package only (needs rpmbuild)
cpack -G ZIP # ZIP archive only
# Or use the build script
./scripts/build.sh --profile package # Release + all packages
./scripts/build.sh --release --package-debGenerated packages:
| Generator | Output | Contents |
|---|---|---|
| DEB | kairos_0.1.0_amd64.deb |
Binary, headers, service files, completions, example config |
| RPM | kairos-0.1.0-1.x86_64.rpm |
Same as DEB |
| ZIP | kairos-0.1.0-Linux-x86_64.zip |
Binary + headers + example config |
The DEB postinst script automatically:
- Creates a
kairossystem user. - Creates
/var/lib/kairosand/var/log/kairosdirectories. - Enables the systemd service (
systemctl enable kairos). - Installs the default configuration if none exists.
cmake --install installs:
| Component | Destination |
|---|---|
kairos binary |
${PREFIX}/bin/kairos |
| Public headers | ${PREFIX}/include/kairos/ |
| systemd unit | ${PREFIX}/lib/systemd/system/kairos.service |
| launchd plist | ${PREFIX}/Library/LaunchDaemons/com.kairos.daemon.plist |
| Example config | ${PREFIX}/share/kairos/kairos.toml.example |
| Shell completions | ${PREFIX}/share/bash-completion/completions/kairos etc. |
brew install --formula deploy/homebrew/kairos.rbThe formula builds from source with CMake, installs completions, and creates the Homebrew service block.
# Build the image
docker build -t kairos:latest -f deploy/docker/Dockerfile .
# Run with config mount
docker run -d \
-v /path/to/config:/etc/kairos \
-v kairos-data:/var/lib/kairos \
--name kairos \
kairos:latest
# Health check
docker exec kairos kairos statusThe Dockerfile uses a two-stage build:
- Builder (ubuntu:24.04): installs cmake, build-essential, libsqlite3-dev; builds release binary.
- Runtime (ubuntu:24.04): copies binary, installs libsqlite3-0 and ca-certificates only. Runs as non-root.
Build and test in a container without installing anything locally:
docker run --rm -v "$(pwd):/src" -w /src ubuntu:24.04 bash -c '
apt-get update -qq && apt-get install -y -qq cmake g++ libsqlite3-dev git
cmake -B build -DCMAKE_BUILD_TYPE=Debug -DKAIROS_BUILD_TESTS=ON
cmake --build build -j$(nproc)
cd build && ctest --output-on-failure
'The GitHub Actions pipeline (.github/workflows/ci.yml) runs on every push and PR:
| Compiler | Platform | Sanitizers | Purpose |
|---|---|---|---|
| GCC 12+ | Ubuntu 24.04 | ASan + UBSan | Memory safety, UB detection |
| Clang 16+ | Ubuntu 24.04 | None | Fast build for PR feedback |
| AppleClang | macOS 14 | None | macOS compatibility |
| MSVC 17 | Windows Server 2022 | None | Windows compatibility |
- Build — configure and compile on all 4 compilers.
- Test — run full test suite on all platforms.
- Package — generate DEB + RPM on
mainbranch (Ubuntu only). - Docker — build, test, and push to GHCR on release tags.
Recommended extensions: C/C++ (ms-vscode), CMake Tools (ms-vscode.cmake-tools), clangd.
.vscode/settings.json:
{
"cmake.buildDirectory": "${workspaceFolder}/build/debug",
"cmake.configureArgs": ["-DKAIROS_BUILD_TESTS=ON"],
"cmake.debugConfig": {
"args": ["start", "--config", "deploy/kairos.toml.example", "--log-level", "debug"]
}
}Open the project root. CLion auto-detects CMake. Configure feature flags in Settings → Build → CMake → CMake options.
Open the project with "Open a local folder" and select the project root. VS auto-detects CMakeLists.txt and CMakePresets.json.
Kairos requires CMake >= 3.21. On older Ubuntu:
pip install cmake --upgrade
# or install from Kitware APT repo:
# https://apt.kitware.com/Requires GCC >= 12, Clang >= 16, AppleClang >= 15, or MSVC >= 19.30 (VS 2022).
# Check your compiler version
g++ --version
clang++ --versionCMake FetchContent downloads from GitHub. If behind a firewall:
# Pre-clone dependencies
git clone https://github.com/araray/confy-cpp.git /tmp/deps/confy-cpp
cmake -B build -DFETCHCONTENT_SOURCE_DIR_CONFY-CPP=/tmp/deps/confy-cppOr set a proxy:
export http_proxy=http://proxy:port
export https_proxy=http://proxy:port# Ubuntu/Debian
sudo apt-get install libsqlite3-dev
# Fedora/RHEL
sudo dnf install sqlite-devel
# macOS
brew install sqlite3# Ubuntu/Debian
sudo apt-get install libssl-dev
# macOS
brew install openssl
cmake -B build -DOPENSSL_ROOT_DIR=$(brew --prefix openssl)Multiple test processes are sharing the same database file. Tests use temporary directories by default. Check for stale test processes:
pkill -f test_persistEnsure you are running from a Developer PowerShell or x64 Native Tools Command Prompt, not a regular PowerShell window. The MSVC toolchain must be on PATH.
On Linux, CMake defaults to Unix Makefiles. For faster builds:
sudo apt-get install ninja-build
cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug
cmake --build build -j