Skip to content

Developer Build and Configuration

Hugo edited this page Sep 25, 2026 · 2 revisions

Developer Build and Configuration

Back to Home

Build System Overview

CoreTrace is a CMake C++20 project producing a single executable, ctrace. Dependencies are integrated through FetchContent and ExternalProject, one CMake module per dependency in cmake/.

Local Build Commands

mkdir -p build && cd build
cmake .. -DUSE_THREAD_SANITIZER=OFF -DUSE_ADDRESS_SANITIZER=OFF
make -j4
./ctrace --help

CMake Options

Option Default Effect
USE_THREAD_SANITIZER OFF Build with ThreadSanitizer
USE_ADDRESS_SANITIZER OFF Build with AddressSanitizer
CORETRACE_WERROR ON Treat compiler warnings as errors
USE_EXTERNAL_CLI11 OFF Fetch CLI11 instead of using the vendored header
ENABLE_TSCANCODE OFF Build tscancode as an external project
ENABLE_FLAWFINDER OFF Build flawfinder as an external project
ENABLE_PYTHON_ANALYZER OFF Build the Python analyzer as a bundled standalone binary
CORETRACE_VERSION_OVERRIDE — Force the embedded version string
CORETRACE_PYTHON_ANALYZER_SOURCE_DIR — Build a local analyzer checkout instead of the pinned tag

ThreadSanitizer and AddressSanitizer cannot be enabled together.

The CLI parser backend is no longer selectable: PARSER_TYPE, the getopt backend and the parser factory are gone, and CLI11 is used directly in src/App/Config.cpp.

Dependencies

FetchContent

Dependency Pin
nlohmann/json v3.11.3 (release archive)
coretrace-stack-analyzer v0.22.0
coretrace-log main
cpp-httplib v0.14.3
CLI11 (when USE_EXTERNAL_CLI11=ON) v2.3.2

ExternalProject (opt-in)

Dependency Pin Option
coretrace-TscanCode master ENABLE_TSCANCODE
flawfinder master ENABLE_FLAWFINDER
coretrace-python-analyzer pinned tag ENABLE_PYTHON_ANALYZER

cmake/ikos.cmake exists but its include() is commented out of CMakeLists.txt: IKOS is not built by default.

Versioning

Version resolution is centralized at configure time (cmake/CoreTraceVersion.cmake):

  • release builds receive an explicit version string from CI, so published binaries print the exact GitHub release tag;
  • local Git builds resolve it from git describe --tags --dirty --always --match 'v*';
  • without Git metadata the build falls back to dev.
cmake .. -DCORETRACE_VERSION_OVERRIDE=v0.74.0
./ctrace --version

Bundled Python Analyzer

-DENABLE_PYTHON_ANALYZER=ON builds coretrace-python-analyzer into a standalone executable with Nuitka, staged in build/libexec/coretrace/ and installed to <prefix>/libexec/coretrace/. It embeds its own Python runtime, so people running ctrace need neither Python nor any package.

Building it needs Python ≥ 3.11 with Nuitka (python3 -m pip install nuitka), a C compiler, and patchelf on Linux.

cmake .. -DENABLE_PYTHON_ANALYZER=ON -DPython3_EXECUTABLE=/path/to/python3

Release Artifacts

The Linux release archives (amd64, arm64) run on any distribution with glibc 2.34 or newer: RHEL 9 and its rebuilds (Rocky, Alma), Amazon Linux 2023, Ubuntu 22.04+, Debian 12+, Fedora 35+.

  • ctrace is built on Ubuntu 22.04 and carries its own libstdc++.
  • The Python analyzer is built on Rocky Linux 9.
  • Each archive is unpacked and run on bare Rocky Linux 9, Ubuntu 22.04, Debian 12 and Ubuntu 24.04 images, with no compiler and no LLVM, before it is published.
  • Each architecture builds on a native runner (ubuntu-24.04 and ubuntu-24.04-arm): emulating arm64 through QEMU took about 25 minutes for the LLVM-linked analyzer, native takes a few.

CI

Workflow What it does
build.yml Builds on ubuntu-24.04 and macos-14 with LLVM/Clang 20 and ENABLE_PYTHON_ANALYZER=ON, then runs the -h smoke test, ctest, and the F7 async harness
clang-format.yml Installs clang-format 17 and runs scripts/format-check.sh
license-compliance.yml Enforces Apache-2.0 header integrity
release-binaries.yml Builds and validates the Linux release archives, then attaches them to the GitHub release

The F7 async harness (tests/BTP-STACK-ANALYZER-F7) drives cppcheck and the stack analyzer in both scheduling modes and compares diagnostic fingerprints. Its speed-up assertion is disabled in CI (--min-speedup-ratio 0): a timing claim is not reliable on a shared runner, and the fingerprints are the point.

Warnings are errors in CI (CORETRACE_WERROR=ON, the default).

Formatting

./scripts/format.sh          # format in place
./scripts/format-check.sh    # verify only
cmake --build build --target format
cmake --build build --target format-check

Target version: clang-format 17, the version used in CI.

Configuration Flow and Precedence

Every input path — config file, HTTP request, CLI — fills the same ProgramConfig (include/Config/config.hpp) through the same loader, so validation and normalization are identical everywhere.

built-in defaults  <  config file (--config / params.config)  <  CLI options / request params
                                                              ↓
                                                     shipped defaults fill what is still empty
  1. buildConfig() parses the command line with CLI11 from the option table in src/App/Config.cpp. Each entry declares its CLI spelling, its kind, and the config section and key it lands in — the help text is generated from that same table.
  2. When --config is given, the file is loaded first.
  3. CLI values are turned into a sectioned JSON document and applied through applyToolConfigObject(), the loader the file goes through.
  4. applyShippedDefaults() fills what remains empty, see Shipped Defaults.

Loader diagnostics name the internal section key; they are rewritten to the option the user typed (CLI) or the flat parameter the client sent (HTTP) before being shown.

The configuration loader never exits the process: it returns an error that the front end turns into an exit code (1 for a usage or configuration error).

Config File Structure

The file is sectioned, one section per struct of ProgramConfig: analysis, files, output, runtime, server, stack_analyzer, tools, plus a schema_version gate (currently 1).

config/tool-config.json is the canonical default file, and docs/configuration.md is the full reference: type, default, allowed values, impact and CLI equivalent for every key. It is kept next to the code rather than duplicated here.

Relative paths in the file are resolved from the config file's directory.

Deprecated spellings

The pre-section layout still loads, and each occurrence prints a Deprecated config key '<key>' in '<where>': use '<canonical>'. warning:

Legacy Replacement
root invoke analysis.invoke
root input files.input
root stack-analyzer keys stack_analyzer.*
tools.ctrace_stack_analyzer.* stack_analyzer.*

Inside the file, precedence is: the stack_analyzer section, then the legacy root keys, then the legacy tools entry.

External tool paths

"tools": {
  "paths": { "cppcheck": "/usr/local/bin/cppcheck" },
  "args":  { "cppcheck": ["--disable=style"] }
}

A path may be a bare command name resolved through PATH, or an absolute path. Tools absent from the map fall back to their own name. args are appended verbatim after the options CoreTrace derives, so they can override them.

Back to Home