Build lifecycle#
Every LIBRA project follows the same sequence of phases. Understanding this sequence makes it clear why certain commands must happen before others, and how the CLI and raw CMake map to each phase.
The phases#
Note
If no build type is specified at configure time, LIBRA defaults to
Release. This is deliberate — see LIBRA Design Philosophy for
the rationale. The debug preset in the recommended hierarchy
overrides this by setting CMAKE_BUILD_TYPE=Debug explicitly.
Phase |
What happens |
Raw CMake |
|
|---|---|---|---|
Configure |
CMake reads |
|
Automatic on cold start; |
Build |
The build system compiles sources, links targets, and builds any enabled test binaries. |
|
|
Test |
CTest runs the registered test executables and reports results. |
|
|
Coverage |
Coverage instrumentation data is collected from test runs and processed into reports or checked against thresholds. |
|
|
Analysis |
Static analysis tools (clang-tidy, cppcheck, etc.) inspect source files and report issues or auto-fix them. |
|
|
Docs |
Doxygen and/or Sphinx generate API and project documentation. |
|
|
Formatting |
Checking/applying formatting to source code |
|
|
Phase dependencies#
The phases have natural ordering constraints:
Configure must precede build.
clibra builddetects a missing build directory and runs configure automatically. Subsequent builds skip configure unless--reconfigureor--freshis given, or CMake’s internal dependency tracking detects that inputs have changed.Build must precede test.
clibra testalways buildsall-testsfirst unless--no-buildis given. Runningctestdirectly against stale or absent test binaries is a common source of confusing failures.Test must precede coverage. Coverage reports are generated from data produced by running instrumented test binaries. Running
gcovr-reportbefore running tests produces an empty or stale report.Analysis, docs and formatting are independent. These phases do not depend on a prior test run and can run after configure and build only. The
analyzebuild preset sets"targets": ["analyze"]so thatcmake --build --preset analyzeruns analysis without building the full project first.
The CI pipeline#
The ci preset and clibra ci command sequence the phases that
matter for continuous integration:
configure → build (with coverage) → test → coverage check
This is the sequence that validates a change is correct (tests pass)
and meets quality thresholds (coverage does not regress). Analysis is
a separate concern — it runs in a dedicated analyze preset and a
separate CI job because it is slow and its failures represent style or
safety issues rather than correctness issues.
When a workflow preset named ci exists, clibra ci delegates the
entire sequence to cmake --workflow --preset ci, which is the CMake
native way to express a multi-phase pipeline. See
ci for the fallback behaviour when no workflow
preset exists.
Cold start vs. incremental builds#
The configure phase is expensive relative to an incremental build. Each preset
has its own build directory (when using "binaryDir":
"${sourceDir}/build/${presetName}"), so switching between debug and
coverage is a directory switch, not a reconfigure. This is the main
practical benefit of the per-preset binaryDir convention.
Presets and the lifecycle#
clibra requires configure and build presets to exist for a given
name. Test presets are used by clibra test when present. Workflow
presets are used by clibra ci when a preset named ci (or the
resolved name) is found.
See CMakePresets.json for the recommended preset
hierarchy, and Preset resolution for how clibra resolves preset
names. See the CMake
preset docs<https://cmake.org/cmake/help/latest/manual/cmake-presets.7.html>
for more info on presets.