Builds
Overview
cikit provides reusable build support for CMake and PlatformIO projects.
The build macros execute the native build tool, collect common metrics, persist command logs, and expose the results through cikit data and artifacts.
The generic build report then combines these outputs into one RST page.
Conceptually:
build tool
|
+-- build metrics ---------> cikit data
|
+-- command logs ----------> LOG artifacts
|
+-- project outputs -------> BUILD artifacts
|
+-- release archives ------> BUNDLE artifacts
|
+-- optional timelines ----> TIMELINE artifacts
|
v
write_build_report()
|
v
RST build report
The current reusable build implementations are:
CMake
PlatformIO
Both use the same generic build report format.
Build Environment
Build macros operate on a CiRunEnvironment.
A typical project command starts by creating a logical build run:
from cikit.macros import common
env = common.init_env(run_name="build")
All metrics and artifacts created afterwards belong to that logical run.
This is important because build reports only consume data and artifacts from their active run.
Common Build Data
The build report understands a common set of run data keys.
Key |
Meaning |
|---|---|
|
Number of detected compiled source files. |
|
Number of detected compiler warnings. |
|
Number of detected compiler errors. |
|
CMake configure duration in seconds. |
|
Build duration in seconds. |
|
Combined configure and build duration when available. |
|
Used bytes for one detected memory region. |
|
Total bytes for one detected memory region. |
|
Percentage used for one detected memory region. |
|
Compiler executable used by the build. |
|
Detected compiler version. |
|
Compiler type or tool-specific compiler identifier. |
|
Version of the CMake executable queried for the build. |
|
Detected compiler optimization setting, for example |
|
Detected link-time optimization setting. The value may describe an enabled, disabled, compiler-specific, or mixed setting. |
Not every build tool provides every metric.
The generic report therefore treats most metrics as optional.
CMake Builds
The CMake macro separates configuration and build execution.
Typical usage:
from pathlib import Path
from cikit.macros import cmake, common
env = common.init_env(run_name="build")
build_dir = cmake.get_build_dir(env)
cmake.gather_cmake_meta(env)
cmake.cmake_configure(
env,
source_dir=Path("."),
build_dir=build_dir,
generator="Ninja",
clean=True,
compile_commands=True,
)
cmake.gather_compiler_meta(env, build_dir, "CXX")
cmake.cmake_build(env, build_dir)
cmake.write_rst(env)
Build Directory
cmake.get_build_dir() returns a directory below:
PROJECT_ROOT/build/
The default name is:
rel
For example:
build_dir = cmake.get_build_dir(env)
resolves conceptually to:
<project>/build/rel
A custom name can be supplied:
build_dir = cmake.get_build_dir(env, "debug")
CMake Configuration
cmake_configure() executes the CMake configure step:
cmake.cmake_configure(
env,
source_dir=Path("."),
build_dir=build_dir,
generator="Ninja",
clean=True,
)
The generated command is conceptually:
cmake -G Ninja -S . -B <build-dir>
Additional CMake definitions can be supplied:
cmake.cmake_configure(
env,
source_dir=Path("."),
build_dir=build_dir,
defines=[
"-DCMAKE_BUILD_TYPE=Release",
"-DENABLE_TESTS=ON",
],
)
When clean=True is used, the complete build directory is removed before
configuration.
compile_commands=True requests generation of compile_commands.json by
passing CMAKE_EXPORT_COMPILE_COMMANDS=ON to CMake.
When CMake generates the compilation database, cikit registers it as a
METADATA artifact. Some generators do not provide compile_commands.json;
in that case configuration still succeeds and the related compiler-option
metrics remain unavailable.
Configure Metrics
The configure duration is stored as:
configure_time
The value is measured in seconds and rounded to one decimal place.
Configure Log
The complete command result is persisted as:
cmake-configure.log
and automatically registered as a LOG artifact.
The log is written even when configuration fails. The configure return code is
checked only after the log and configure_time have been persisted.
CMake Metadata
The installed CMake version can be stored in the current run data:
cmake.gather_cmake_meta(env)
The command queries the same cmake executable used by the build workflow and
stores:
cmake_version
Compiler Metadata
After configuration, compiler metadata can be collected for a CMake language:
cmake.gather_compiler_meta(env, build_dir, "CXX")
The language must match a language enabled by the configured CMake project, for
example C or CXX.
cikit uses the CMake File API toolchains-v1 reply generated during
cmake_configure() and stores:
compiler
compiler_version
compiler_type
compiler_type contains the compiler ID reported by CMake, for example
GNU or Clang.
Missing, invalid, or unavailable toolchain metadata is reported as a
CiToolsError.
CMake Build
After configuration:
cmake.cmake_build(env, build_dir)
The build command is based on:
cmake --build <build-dir>
Parallel Execution
cmake_build() accepts a jobs argument.
cmake.cmake_build(env, build_dir, jobs=8)
The behavior is:
jobs = 0
-> cmake --build ... --parallel
jobs = 1
-> no explicit parallel argument
jobs > 1
-> cmake --build ... --parallel <jobs>
The same parallel-argument handling is used by the CTest helper.
CMake Build Metrics
cmake_build() collects the following build metrics:
compiled files
warnings
errors
linker memory usage
build duration
Compiled files, diagnostics, and memory usage are extracted from the build output. Build duration is measured around the CMake build command.
When configure_time is already available, cikit also stores:
total_build_time
When compile_commands.json is available, cmake_build() additionally
inspects the compiler command lines for recognized optimization and LTO options.
The detected settings are stored as:
optimization
lto
If multiple recognized settings are found, the corresponding value is stored as
mixed.
These metrics are optional. They are omitted when the compilation database is not available or the relevant compiler options cannot be recognized.
Compiled Files
Compiled files are detected from CMake/Ninja output containing lines matching the form:
Building ... object
If no such lines are found, build_files is omitted.
This can happen when an incremental build has nothing to compile.
Diagnostics
Compiler diagnostics are detected through GCC/Clang-style output containing:
warning:
error:
The resulting counts are stored as:
warnings
errors
Memory Usage
CMake memory metrics are parsed from linker output compatible with GNU linker
--print-memory-usage.
For example, a region named FLASH becomes:
memory_flash_used
memory_flash_total
memory_flash_percent
Memory metrics are only available when the linker actually emits compatible memory usage information.
Build Log
The complete CMake build command result is stored as:
cmake-build.log
and registered automatically as a LOG artifact.
Metrics and the log are persisted before the build return code is checked.
CTest
The CMake macro also provides a CTest helper:
cmake.ctest(
env,
build_dir,
test_alias="ctest",
)
CTest creates JUnit-compatible XML output and feeds it into the same test-result processing used by the pytest macro.
PlatformIO Builds
PlatformIO builds are configured by the project’s platformio.ini.
cikit does not duplicate PlatformIO board, framework, environment, library, or build settings.
Typical usage:
from pathlib import Path
from cikit.macros import common, platformio
env = common.init_env(run_name="build")
platformio.build(
env,
project_dir=Path("."),
clean=True,
)
platformio.write_rst(env)
Project Directory
When project_dir is omitted, PlatformIO runs in PROJECT_ROOT.
Clean Builds
With:
platformio.build(env, clean=True)
cikit removes the project’s local:
.pio/
directory before invoking PlatformIO.
Build Execution
The macro runs:
pio run
through the configured cikit execution tool.
Compiler Metadata
Compiler metadata can be collected independently from the build:
platformio.gather_compiler_meta(env)
The resolved PlatformIO environment is queried for its configured C compiler. The compiler itself is then queried for its version.
When available, cikit stores:
compiler
compiler_version
compiler_type
These values are also included in the generated build report summary.
Compiler metadata is only stored when exactly one PlatformIO environment can be resolved unambiguously. Missing or unavailable metadata is ignored.
PlatformIO Metrics
PlatformIO output is parsed for:
compiled files
compiler warnings
compiler errors
memory usage
build duration
build_files, warnings, and errors are always stored, even when they
are zero.
Compiled files are detected from lines beginning with:
Compiling
Warnings and errors are counted from compiler-style diagnostics on stderr.
Memory Usage
When PlatformIO emits its standard memory summary, cikit converts detected regions into the same flat key structure used by the CMake macro:
memory_<region>_used
memory_<region>_total
memory_<region>_percent
Memory metrics are omitted when the PlatformIO output does not contain a recognized memory table.
Build Log
The PlatformIO command result is persisted as:
platformio-build.log
and automatically registered as a LOG artifact.
Registering Build Outputs
The CMake and PlatformIO macros do not automatically decide which generated files are project deliverables.
The project command should explicitly register outputs that should appear in the build report.
For example:
from cikit.artifacts import ArtifactType
env.copy_artifact(
build_dir / "firmware.bin",
ArtifactType.BUILD,
)
Registered BUILD artifacts are exposed by the generic build report as a
table containing download links, file sizes, and SHA-256 hashes.
File size and SHA-256 metadata are populated automatically by copy_artifact().
For details about artifact storage and naming, see Artifacts.
Bundles
Release archives can be created with the bundle macro.
Example:
from cikit.macros import bundle
bundle.create(
env,
"firmware-package.zip",
build_dir / "release",
)
Supported formats are:
.zip.tar.tar.gz
The archive is registered automatically as a BUNDLE artifact.
Bundles registered for the active run are included automatically in the build report using the same table format with download links, file sizes, and SHA-256 hashes as direct build artifacts.
Timelines
A build report can also include timeline charts registered before report generation.
For example:
from cikit.macros.common import chart_timeline
from cikit.timeline import TimelinePreset
timeline = chart_timeline(
env,
keys=["build_time", "warnings"],
title="Build History",
limit=20,
)
timeline.set_preset(TimelinePreset.LINE_REPORT)
timeline.create(env, "build")
The resulting TIMELINE artifact is discovered by the build report through
the artifact registry.
For the complete timeline workflow, see Timeline Charts.
Build Reports
CMake and PlatformIO provide convenience wrappers around the generic build report.
For CMake:
cmake.write_rst(env)
For PlatformIO:
platformio.write_rst(env)
Both delegate to:
reports.write_build_report(env)
The generic build report includes all supported information available for the active run.
It can contain:
compiled file, warning, and error counts
CMake and compiler metadata
optimization and LTO settings when available
configure, build, and total build times
memory usage
timeline charts
BUILDandBUNDLEartifact tables with download links, file sizes, and SHA-256 hashesLOGartifacts
The generated report is itself registered as an RST artifact.
Artifacts must be registered before write_rst() if they should appear in
that report.
Complete CMake Example
A project-specific CMake command can combine the complete workflow:
from pathlib import Path
from cikit.artifacts import ArtifactType
from cikit.macros import bundle, cmake, common
env = common.init_env(run_name="build")
build_dir = cmake.get_build_dir(env)
cmake.gather_cmake_meta(env)
cmake.cmake_configure(
env,
source_dir=Path("."),
build_dir=build_dir,
generator="Ninja",
clean=True,
compile_commands=True,
)
cmake.gather_compiler_meta(env, build_dir, "CXX")
cmake.cmake_build(env, build_dir)
env.copy_artifact(
build_dir / "firmware.bin",
ArtifactType.BUILD,
)
bundle.create(
env,
"firmware-package.zip",
build_dir / "release",
)
cmake.write_rst(env)
The important order is:
gather CMake metadata
|
configure
|
gather compiler metadata
|
build
|
register outputs
|
create bundles
|
create optional timelines
|
write build report
Complete PlatformIO Example
A PlatformIO project follows the same pattern:
from pathlib import Path
from cikit.artifacts import ArtifactType
from cikit.macros import common, platformio
env = common.init_env(run_name="build")
platformio.build(
env,
project_dir=Path("."),
clean=True,
)
env.copy_artifact(
Path(".pio/build/myenv/firmware.bin"),
ArtifactType.BUILD,
)
platformio.write_rst(env)
The exact PlatformIO output path remains project-specific because it depends on the configured PlatformIO environments.
Failed Builds
Both build macros persist available metrics and command logs before checking the tool return code.
As a result, failed builds can still leave useful diagnostics in cikit data and
registered LOG artifacts.
Whether a report is generated after a failed build is controlled by the project’s command orchestration.
Sphinx Integration
Build reports are registered as RST artifacts.
During Sphinx preparation they are copied into:
docs/_generated/
Build outputs, bundles, logs, and timeline charts are copied into the static artifact area according to the common artifact mapping.
See Sphinx Documentation Build for the documentation build workflow.
Responsibilities
Component |
Responsibility |
|---|---|
Project build configuration |
Compiler, linker, board, framework, source files, and tool-specific settings. |
CMake / PlatformIO macro |
Execute the build, collect common metrics, and persist command logs. |
Project command |
Select deliverables and register |
Bundle macro |
Package selected files or directories as |
Timeline support |
Render historical cikit data as |
Generic build report |
Combine run data and supported artifacts into an RST report. |
Sphinx macro |
Collect generated reports and artifacts into the documentation build. |