Skip to content

Build, Package, and Distribution

TopoExec is packaged as CMake targets with a runtime-first boundary. The default build includes YAML loading, CLI tools, examples, and tests; runtime-only embedders can switch those surfaces off.

Package-manager registry publication and production adapter distribution remain deferred until a human release owner approves exact artifacts and target registries.

Build from source

cmake -S . -B build -DCMAKE_BUILD_TYPE=RelWithDebInfo
cmake --build build -j
ctest --test-dir build --output-on-failure

Install and consume

cmake --install build --prefix /tmp/topoexec-install
cmake -S tests/cmake/runtime_smoke -B /tmp/topoexec-runtime-smoke \
  -DCMAKE_PREFIX_PATH=/tmp/topoexec-install
cmake --build /tmp/topoexec-runtime-smoke -j
/tmp/topoexec-runtime-smoke/topoexec_runtime_smoke

A downstream runtime-only app should link:

find_package(topoexec CONFIG REQUIRED)
target_link_libraries(my_app PRIVATE topoexec::runtime)

YAML-loading consumers should request the component so the package config can discover parser/JSON dependencies:

find_package(topoexec CONFIG REQUIRED COMPONENTS yaml)
target_link_libraries(my_graph_tool PRIVATE topoexec::yaml)

CLI package checks can request the imported executable component:

find_package(topoexec CONFIG REQUIRED COMPONENTS cli)
add_custom_target(check_topoexec_cli
  COMMAND $<TARGET_FILE:topoexec::topoexec_cli> doctor --format json)

The installed package exports:

  • topoexec::core: header-only common baseline.
  • topoexec::runtime: embeddable runtime library.
  • topoexec::adapter_sdk: dependency-free adapter SDK v0 boundary.
  • topoexec::c_api: optional unstable C API/FFI preview target when TOPOEXEC_BUILD_C_API=ON.
  • topoexec::plugin_loader: optional trusted-native dynamic plugin loader preview target when TOPOEXEC_BUILD_PLUGIN_LOADER=ON.
  • topoexec::yaml: optional YAML graph loader target when built.
  • topoexec::topoexec_cli: optional imported executable target when the CLI is built and installed.
  • topoexec_preview: optional installed Python automation preview under share/topoexec/python when TOPOEXEC_BUILD_PYTHON_PREVIEW=ON.
  • topoexec_adapters::otel: optional dependency-free OTel exporter preview target when TOPOEXEC_BUILD_OTEL_ADAPTER=ON.
  • topoexec_adapters::prometheus: optional dependency-free Prometheus text exporter preview target when TOPOEXEC_BUILD_PROMETHEUS_ADAPTER=ON.
  • topoexec_adapters::ros2: optional dependency-free ROS 2 fake-boundary preview target when TOPOEXEC_BUILD_ROS2_ADAPTER=ON.

The CLI executable is installed as bin/topoexec when TOPOEXEC_BUILD_CLI=ON. The installed config also exposes package metadata variables:

  • TOPOEXEC_VERSION
  • TOPOEXEC_SCHEMA_VERSION
  • TOPOEXEC_SEMANTIC_CONTRACT_VERSION
  • TOPOEXEC_HAS_RUNTIME
  • TOPOEXEC_HAS_ADAPTER_SDK
  • TOPOEXEC_HAS_C_API
  • TOPOEXEC_HAS_PYTHON_PREVIEW
  • TOPOEXEC_HAS_PLUGIN_LOADER
  • TOPOEXEC_HAS_OTEL_ADAPTER
  • TOPOEXEC_HAS_PROMETHEUS_ADAPTER
  • TOPOEXEC_HAS_ROS2_ADAPTER
  • TOPOEXEC_HAS_YAML
  • TOPOEXEC_HAS_CLI
  • TOPOEXEC_HAS_EXAMPLES

Build options

Option Default Purpose
TOPOEXEC_BUILD_YAML ON Build topoexec::yaml and require yaml-cpp.
TOPOEXEC_BUILD_CLI ON Build the CLI; requires YAML and CLI11.
TOPOEXEC_BUILD_EXAMPLES ON Build runnable example applications; requires YAML for YAML-backed apps.
TOPOEXEC_BUILD_TESTING ON Build CTest suite; currently requires YAML, CLI, and examples.
TOPOEXEC_BUILD_FUZZERS OFF Build optional graph-input fuzz targets; requires YAML.
TOPOEXEC_BUILD_C_API OFF Build and export the optional unstable C API/FFI preview target.
TOPOEXEC_BUILD_PYTHON_PREVIEW OFF Install and test the optional CLI-backed Python automation preview; requires the CLI when enabled.
TOPOEXEC_BUILD_PLUGIN_LOADER OFF Build, test, and export the optional trusted-native dynamic plugin loader preview.
TOPOEXEC_BUILD_OTEL_ADAPTER OFF Build and export the optional dependency-free OTel exporter preview target.
TOPOEXEC_BUILD_PROMETHEUS_ADAPTER OFF Build and export the optional dependency-free Prometheus text exporter preview target.
TOPOEXEC_BUILD_ROS2_ADAPTER OFF Build and export the optional dependency-free ROS 2 fake-boundary preview target.
TOPOEXEC_FUZZER_ENGINE AUTO Fuzzer engine when fuzzers are enabled: AUTO, LIBFUZZER, or STANDALONE.
TOPOEXEC_ENABLE_ASAN OFF Add AddressSanitizer instrumentation for GCC/Clang builds.
TOPOEXEC_ENABLE_UBSAN OFF Add UndefinedBehaviorSanitizer instrumentation for GCC/Clang builds.
TOPOEXEC_ENABLE_TSAN OFF Add ThreadSanitizer instrumentation; cannot be combined with ASAN/UBSAN.

Runtime-only configure smoke:

cmake -S . -B build-runtime-only -DCMAKE_BUILD_TYPE=RelWithDebInfo \
  -DTOPOEXEC_BUILD_YAML=OFF \
  -DTOPOEXEC_BUILD_CLI=OFF \
  -DTOPOEXEC_BUILD_EXAMPLES=OFF \
  -DTOPOEXEC_BUILD_TESTING=OFF
cmake --build build-runtime-only --target topoexec_runtime -j
cmake --install build-runtime-only --prefix /tmp/topoexec-runtime-only

This path is covered by cmake_runtime_only_options_smoke.

Optional C API preview target:

cmake -S . -B build-ffi -DCMAKE_BUILD_TYPE=RelWithDebInfo \
  -DTOPOEXEC_BUILD_C_API=ON
cmake --build build-ffi -j
ctest --test-dir build-ffi --output-on-failure -R test_c_api

Installed C consumers request the optional component and link the C API target:

find_package(topoexec CONFIG REQUIRED COMPONENTS c_api)
add_executable(my_c_embedder main.c)
set_property(TARGET my_c_embedder PROPERTY LINKER_LANGUAGE CXX)
target_link_libraries(my_c_embedder PRIVATE topoexec::c_api)

This preview target exports topoexec/c_api/topoexec.h, opaque handles, create/run/destroy, error strings, and metric iteration. It is ABI version 0, unstable, and covered by cmake_c_api_options_smoke.

Optional Python automation preview:

cmake -S . -B build-python-preview -DCMAKE_BUILD_TYPE=RelWithDebInfo \
  -DTOPOEXEC_BUILD_PYTHON_PREVIEW=ON
cmake --build build-python-preview -j
ctest --test-dir build-python-preview --output-on-failure -R python_preview_smoke

The preview installs topoexec_preview under share/topoexec/python and shells out to bin/topoexec for JSON validate/plan/run/metrics/trace automation. It is not a native extension, has no pybind11 dependency, and is covered by cmake_python_preview_options_smoke, which also proves a disabled runtime-only C++ build still has no Python requirement.

Optional dynamic plugin loader preview:

cmake -S . -B build-plugins -DCMAKE_BUILD_TYPE=RelWithDebInfo \
  -DTOPOEXEC_BUILD_PLUGIN_LOADER=ON
cmake --build build-plugins -j
ctest --test-dir build-plugins --output-on-failure -R test_plugin_loader

Installed consumers request the optional package component and link the preview target explicitly:

find_package(topoexec CONFIG REQUIRED COMPONENTS plugin_loader)
target_link_libraries(my_host PRIVATE topoexec::plugin_loader)

This preview loads trusted native components by explicit path, validates the manifest/plugin API/schema/component descriptors, and defaults to keeping the native handle open. It does not sandbox plugins, discover packages from graph schema, or promise a stable ABI. It is covered by cmake_plugin_loader_options_smoke, which also proves a disabled runtime-only build still has no plugin-loader requirement.

Optional OTel preview target:

cmake -S . -B build-otel -DCMAKE_BUILD_TYPE=RelWithDebInfo \
  -DTOPOEXEC_BUILD_OTEL_ADAPTER=ON
cmake --build build-otel -j
ctest --test-dir build-otel --output-on-failure -R test_otel_adapter

Installed consumers request the optional package component and link the adapter namespace target:

find_package(topoexec CONFIG REQUIRED COMPONENTS otel)
target_link_libraries(my_exporter PRIVATE topoexec_adapters::otel)

This preview target maps existing runtime metrics, trace, health, and errors to in-memory OTel-shaped records. It does not link an external telemetry SDK and is covered by cmake_otel_adapter_options_smoke.

Optional Prometheus preview target:

cmake -S . -B build-prometheus -DCMAKE_BUILD_TYPE=RelWithDebInfo \
  -DTOPOEXEC_BUILD_PROMETHEUS_ADAPTER=ON
cmake --build build-prometheus -j
ctest --test-dir build-prometheus --output-on-failure -R test_prometheus_adapter

Installed consumers request the optional package component and link the adapter namespace target:

find_package(topoexec CONFIG REQUIRED COMPONENTS prometheus)
target_link_libraries(my_exporter PRIVATE topoexec_adapters::prometheus)

This preview target renders runtime metric descriptors and custom histogram summaries as text exposition. It does not start an HTTP server or link a Prometheus library and is covered by cmake_prometheus_adapter_options_smoke.

Optional ROS 2 preview target:

cmake -S . -B build-ros2 -DCMAKE_BUILD_TYPE=RelWithDebInfo \
  -DTOPOEXEC_BUILD_ROS2_ADAPTER=ON
cmake --build build-ros2 -j
ctest --test-dir build-ros2 --output-on-failure -R test_ros2_adapter

Installed consumers request the optional package component and link the adapter namespace target:

find_package(topoexec CONFIG REQUIRED COMPONENTS ros2)
target_link_libraries(my_ros_adapter PRIVATE topoexec_adapters::ros2)

This preview target maps topics, services, actions, and QoS into adapter-owned endpoint descriptors and fake boundary bridges. It does not link ROS packages, create nodes/executors, or add schema fields, and is covered by cmake_ros2_adapter_options_smoke.

Optional fuzzer smoke:

TOPOEXEC_FUZZER_ENGINE=STANDALONE ./scripts/fuzz_smoke.sh

Use TOPOEXEC_FUZZER_ENGINE=LIBFUZZER with CXX=clang++ for the libFuzzer instrumented target.

Optional stress/soak smoke:

./scripts/goal_check.sh stress
TOPOEXEC_STRESS_PROFILE=soak TOPOEXEC_STRESS_DURATION_SECONDS=60 ./scripts/stress_smoke.sh

The first command is a bounded smoke. The soak profile repeats bounded-step stress graph suites only for the caller-selected duration/iteration limits.

Optional benchmark baseline:

./scripts/goal_check.sh bench
./scripts/bench_baseline.sh

The focused goal check validates benchmark output contracts and writes a short temporary baseline without thresholds. The baseline script can generate a local ignored baseline file and optionally compare against a user-selected per-machine threshold.

Optional documentation site/API reference:

cmake -S . -B build-docs -DCMAKE_BUILD_TYPE=Release -DTOPOEXEC_BUILD_DOCS=ON
cmake --build build-docs --target topoexec_doxygen
python -m pip install mkdocs-material=="9.*"
./scripts/docs_build_site.sh

TOPOEXEC_BUILD_DOCS is default-off and only creates topoexec_doxygen when Doxygen is found. The docs-site script uses MkDocs as docs-only tooling and copies generated Doxygen HTML under site/api/; neither tool is a runtime dependency.

Packaging smoke:

./scripts/goal_check.sh package

This installs the current build and verifies downstream runtime-only, topoexec::yaml, and imported CLI consumption without requiring a source-tree clone. It also checks the runtime-only option build/install path, CPack TGZ generation, and package-manager draft files.

Dependency policy

  • Runtime code does not depend on YAML, CLI11, ROS, Python, OpenTelemetry, Prometheus, or dynamic plugin loading APIs.
  • YAML loading requires yaml-cpp and nlohmann_json.
  • CLI builds require CLI11 and nlohmann_json.
  • Fuzzer targets are off by default and require no runtime dependency; libFuzzer instrumentation requires Clang.
  • Stress and soak scripts use the built CLI plus CTest/Python only; they add no runtime dependency.
  • Benchmark scripts use the built CLI, a non-installed test benchmark binary, and Python only; timing thresholds are never mandatory in CI.
  • Doxygen and MkDocs are docs-only tools for generated API/site artifacts and are not required for normal runtime, YAML, CLI, package, or preview builds.
  • Tests require GTest; if unavailable, the test build fetches it through CMake FetchContent.
  • The plugin loader preview uses POSIX dynamic-loading APIs in its optional target only; core/runtime builds do not include or link that target by default.

Package-manager drafts

Draft notes live under:

  • packaging/vcpkg/README.md
  • packaging/vcpkg/vcpkg.json
  • packaging/vcpkg/portfile.cmake
  • packaging/conan/README.md
  • packaging/conan/conanfile.py

They are intentionally not published package recipes yet. Keep them aligned with the CMake options above and do not add package-manager-specific dependencies to the core runtime. The plugin-loader draft feature is off by default and remains a trusted-native preview; it is not a published plugin ecosystem.

CPack drafts

The build defines TGZ source and binary package generators:

cpack -G TGZ --config build/CPackConfig.cmake
cpack -G TGZ --config build/CPackSourceConfig.cmake

cmake_cpack_smoke checks that both packages can be generated. These archives are local release-candidate artifacts, not a substitute for signed source archives and checksums in the final release process.

Release artifacts

Use the release runbook for candidate artifact preparation:

./scripts/release_prepare.sh --version v0.2.0-alpha.0

The script runs the release gates by default, creates the source archive from git archive HEAD, runs CPack for binary/source TGZ artifacts, copies the schema artifact, writes SHA256SUMS, and emits only a human-approved annotated tag command. It does not tag, retag, publish, or upload a public release.

Release candidates should include:

  1. source tarball from the exact candidate commit or signed/tagged commit;
  2. checksum file for generated artifacts;
  3. release notes from CHANGELOG.md;
  4. schema artifact;
  5. default CTest evidence;
  6. runtime-only install/export smoke evidence;
  7. YAML and CLI installed package smoke evidence when those options are enabled;
  8. CPack source/binary archive smoke evidence;
  9. ASAN+UBSAN sanitizer evidence;
  10. known limitations for deferred adapters, trusted-native plugin preview scope, benchmark thresholds, and non-blocking TSAN.

Troubleshooting

  • If TOPOEXEC_BUILD_CLI=ON fails while YAML is disabled, either enable YAML or disable CLI.
  • If tests are enabled while YAML/CLI/examples are disabled, disable tests for a runtime-only build.
  • If a sanitized installed static library fails to link in a downstream smoke, propagate the same sanitizer link flags to the downstream executable.
  • Use topoexec doctor --format json in a default build to inspect schema, example, benchmark discovery paths, and installed CLI schema discovery paths.