Files
tqcq 85a0ff93c2
cpp-template / format (ubuntu-22.04) (push) Successful in 57s
cpp-template / format (ubuntu-24.04) (push) Successful in 56s
cpp-template / build-test (asan, ubuntu-22.04) (push) Successful in 1m34s
cpp-template / build-test (asan, ubuntu-24.04) (push) Successful in 1m35s
cpp-template / build-test (debug, ubuntu-22.04) (push) Successful in 1m55s
cpp-template / build-test (debug, ubuntu-24.04) (push) Successful in 1m50s
cpp-template / build-test (fuzz, ubuntu-22.04) (push) Successful in 6m18s
cpp-template / build-test (fuzz, ubuntu-24.04) (push) Successful in 7m0s
cpp-template / build-test (release, ubuntu-22.04) (push) Successful in 1m49s
cpp-template / build-test (release, ubuntu-24.04) (push) Successful in 1m53s
cpp-template / clang-tidy (ubuntu-22.04) (push) Successful in 1m37s
cpp-template / clang-tidy (ubuntu-24.04) (push) Successful in 1m52s
cpp-template / install-consumer (ubuntu-22.04) (push) Successful in 1m41s
cpp-template / install-consumer (ubuntu-24.04) (push) Successful in 1m36s
cpp-template / no-network-negative (ubuntu-22.04) (push) Successful in 6m50s
cpp-template / no-network-negative (ubuntu-24.04) (push) Successful in 7m32s
cpp-template / format (ubuntu-20.04) (push) Has been cancelled
cpp-template / build-test (asan, ubuntu-20.04) (push) Has been cancelled
cpp-template / build-test (debug, ubuntu-20.04) (push) Has been cancelled
cpp-template / build-test (fuzz, ubuntu-20.04) (push) Has been cancelled
cpp-template / build-test (release, ubuntu-20.04) (push) Has been cancelled
cpp-template / clang-tidy (ubuntu-20.04) (push) Has been cancelled
cpp-template / install-consumer (ubuntu-20.04) (push) Has been cancelled
cpp-template / no-network-negative (ubuntu-20.04) (push) Has been cancelled
chore: remove ThreadSanitizer (TSan) support
2026-05-19 14:19:49 +08:00

15 KiB

CMake helper API manual

This manual documents the project helper API implemented under cmake/. The examples are intentionally close to the positive helper fixtures and current root usage, but paths and target names are illustrative unless a section explicitly says otherwise.

Global conventions

  • Call native project(<name> LANGUAGES C CXX) before cc_project(); the helper rejects CMake's implicit project(Project) default.
  • The primary project standard is C++14. Fuzz lane targets require the fuzz preset or equivalent Clang + C++17 configuration.
  • INCS, DEPS, and DEFINES use explicit visibility groups. Every item must follow PUBLIC, PRIVATE, or INTERFACE; unqualified items are rejected.
  • Executable-like targets (cc_executable, cc_test, cc_benchmark, and cc_fuzz) do not support INTERFACE visibility because they are not consumed as link interfaces. Use PUBLIC or PRIVATE only.
  • cc_library(TYPE INTERFACE) supports only INTERFACE visibility for INCS, DEPS, and DEFINES.
  • Helpers automatically link the framework Core runtime defaults: spdlog::spdlog, fmt::fmt, nlohmann_json::nlohmann_json, toml11::toml11, CLI11::CLI11, asio::asio, concurrentqueue::concurrentqueue, ghcFilesystem::ghc_filesystem, nonstd::expected-lite, and httplib::httplib. Static/shared libraries receive these defaults as PUBLIC, interface libraries as INTERFACE, and executable-like targets as PRIVATE.
  • Helpers do not acquire lane-specific external dependencies directly. The template infrastructure loads GTest::gtest, benchmark::benchmark, and fuzztest::fuzztest from the committed archive model when the corresponding helper lane is enabled.
  • There are aggregate targets run_tests and run_benchmarks, but no per-target run_test_<name>, run_benchmark_<name>, or run_fuzz_<name> wrappers.

cc_project()

Signature:

cc_project()

Use in the root CMakeLists.txt after native project() and after any cache variables that should influence helper options.

cmake_minimum_required(VERSION 3.19)
project(my_package LANGUAGES C CXX)

include(cmake/cc_project.cmake)
cc_project()

Behavior:

  • Sets C++ defaults: C++14 by default, required standard, extensions off.
  • Enables CMAKE_EXPORT_COMPILE_COMMANDS unless the caller already set it.
  • Enables position-independent code.
  • Defines helper options:
    • CC_ENABLE_INSTALL: ON by default for the top-level project, OFF for subprojects.
    • CC_ENABLE_TESTING: ON by default.
    • CC_ENABLE_BENCHMARKS: ON by default.
    • CC_ENABLE_FUZZTEST: ON by default as a capability-gated request; actual fuzz targets are created only for the isolated Clang + C++17 fuzz lane.
    • CC_ENABLE_ASAN: OFF by default; adds AddressSanitizer compile/link flags.
    • CC_WARNINGS_AS_ERRORS: OFF by default.
  • Uses public lane options only: CC_ENABLE_TESTING, CC_ENABLE_BENCHMARKS, CC_ENABLE_FUZZTEST, and CC_ENABLE_ASAN. Users do not need lane if() wrappers around cc_test(), cc_benchmark(), or cc_fuzz().
  • Creates top-level aggregate targets when enabled:
    • run_tests: runs ctest --output-on-failure.
    • run_benchmarks: aggregate target populated by cc_benchmark().
  • Defers cc_finalize_install() at generate time when the install module is included.

cc_library()

Signature:

cc_library(<target>
    TYPE STATIC|SHARED|INTERFACE
    [SRCS <src>...]
    [HDRS <hdr>...]
    [INCS [PUBLIC|PRIVATE|INTERFACE <dir>...]...]
    [DEPS [PUBLIC|PRIVATE|INTERFACE <dep>...]...]
    [DEFINES [PUBLIC|PRIVATE|INTERFACE <define>...]...]
    [OPTIONS <option>...]
    [FEATURES <feature>...]
    [ALIAS <alias>]
    [INSTALL]
)

Required contract:

  • TYPE is mandatory and must be STATIC, SHARED, or INTERFACE.
  • OBJECT libraries are not supported by this helper.
  • TYPE INTERFACE must not provide SRCS or HDRS.
  • INCS, DEPS, and DEFINES require explicit visibility for every item.
  • TYPE INTERFACE only accepts INTERFACE visibility in visibility-grouped arguments.
  • ALIAS creates a real build-tree library alias with add_library(<alias> ALIAS <target>) and also stores install/export metadata.
  • INSTALL only marks the target. Install rules are produced later by cc_finalize_install() when install is enabled.
  • Automatically links Core runtime defaults PUBLIC for STATIC/SHARED libraries and INTERFACE for INTERFACE libraries.

Static library example, mirroring the positive helper fixture pattern:

include("${CC_PROJECT_ROOT}/cmake/cc_targets.cmake")

cc_library(my_static_lib
    TYPE STATIC
    SRCS lib.cpp
    HDRS lib.h
    INCS PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}
    DEPS PUBLIC m
    DEFINES PUBLIC MY_STATIC_BUILD
    OPTIONS -Wall
    FEATURES cxx_std_14
    ALIAS my_static_lib::my_static_lib
    INSTALL
)

Interface library example:

cc_library(my_headers
    TYPE INTERFACE
    INCS INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/include
    DEFINES INTERFACE MY_HEADERS_ONLY=1
    FEATURES cxx_std_14
)

cc_executable()

Signature:

cc_executable(<target>
    [SRCS <src>...]
    [HDRS <hdr>...]
    [INCS [PUBLIC|PRIVATE <dir>...]...]
    [DEPS [PUBLIC|PRIVATE <dep>...]...]
    [DEFINES [PUBLIC|PRIVATE <define>...]...]
    [OPTIONS <option>...]
    [FEATURES <feature>...]
    [ALIAS <alias>]
    [INSTALL]
)

Behavior:

  • Creates an executable target. SRCS may be omitted, producing an initially empty executable target.
  • Applies OPTIONS and FEATURES privately.
  • Rejects INTERFACE visibility in INCS, DEPS, and DEFINES.
  • ALIAS is install/export metadata only. CMake does not support add_executable(<alias> ALIAS ...), so no build-tree executable alias is created.
  • INSTALL marks the target for later install/export finalization.
  • Automatically links Core runtime defaults PRIVATE.

Example:

include("${CC_PROJECT_ROOT}/cmake/cc_targets.cmake")

cc_executable(hello_exe
    SRCS main.cpp
    DEPS PRIVATE my_static_lib
    OPTIONS -Wall
    FEATURES cxx_std_14
)

Installable executable example:

cc_executable(my_tool
    SRCS main.cpp
    ALIAS my_ns::my_tool
    INSTALL
)

cc_test()

Signature:

cc_test(<target>
    [NO_MAIN]
    SRCS <src>...
    [HDRS <hdr>...]
    [INCS [PUBLIC|PRIVATE <dir>...]...]
    [DEPS [PUBLIC|PRIVATE <dep>...]...]
    [DEFINES [PUBLIC|PRIVATE <define>...]...]
    [OPTIONS <option>...]
    [FEATURES <feature>...]
    [ARGS <arg>...]
)

Behavior:

  • When CC_ENABLE_TESTING is OFF, logs a status message and returns without creating a target.
  • Requires GTest::gtest when target creation is enabled.
  • Requires non-empty SRCS.
  • Registers add_test(NAME <target> COMMAND <target> [<ARGS>...]).
  • Adds the test executable as a dependency of run_tests when that aggregate target exists.
  • Without NO_MAIN, links GTest::gtest_main and GTest::gmock, which implies GTest::gtest.
  • With NO_MAIN, links GTest::gtest and GTest::gmock; use this when the test source or another dependency supplies main().
  • GTest::gmock is linked by default; listing it in DEPS is unnecessary but harmless.
  • GTest::gmock_main requires NO_MAIN; the helper rejects it otherwise because it conflicts with default GTest::gtest_main.
  • Automatically links Core runtime defaults PRIVATE. Basic example:
include("${CC_PROJECT_ROOT}/cmake/cc_project.cmake")
include("${CC_PROJECT_ROOT}/cmake/cc_targets.cmake")
include("${CC_PROJECT_ROOT}/cmake/cc_testing.cmake")

cc_project()
cc_test(calc_test
    SRCS calc_test.cpp
    DEPS PRIVATE calc
    ARGS --gtest_filter=CalcTest.*
)

GMock custom-main example, mirroring the positive helper fixture pattern:

cc_test(mock_test
    SRCS test_mock.cpp
    NO_MAIN
    DEPS PRIVATE my_mock_framework
)

cc_benchmark()

Signature:

cc_benchmark(<target>
    [NO_MAIN]
    SRCS <src>...
    [HDRS <hdr>...]
    [INCS [PUBLIC|PRIVATE <dir>...]...]
    [DEPS [PUBLIC|PRIVATE <dep>...]...]
    [DEFINES [PUBLIC|PRIVATE <define>...]...]
    [OPTIONS <option>...]
    [FEATURES <feature>...]
    [ARGS <arg>...]
)

Behavior:

  • When CC_ENABLE_BENCHMARKS is OFF, logs a status message and returns without creating a target.
  • Requires benchmark::benchmark when target creation is enabled.
  • Without NO_MAIN, also requires and links benchmark::benchmark_main.
  • With NO_MAIN, links benchmark::benchmark only; use this when the benchmark source provides main().
  • Requires non-empty SRCS.
  • Does not register the benchmark with default CTest.
  • Adds the benchmark target as a dependency of run_benchmarks when that aggregate target exists.
  • Adds a POST_BUILD command to run_benchmarks that directly executes the benchmark binary with ARGS.
  • ARGS are native Google Benchmark runtime arguments. There is no helper-specific OUTPUT keyword; use native flags such as --benchmark_out=<path> and --benchmark_out_format=json.
  • Automatically links Core runtime defaults PRIVATE.

Example with native benchmark arguments, mirroring the positive helper fixture pattern:

include("${CC_PROJECT_ROOT}/cmake/cc_targets.cmake")
include("${CC_PROJECT_ROOT}/cmake/cc_benchmark.cmake")

add_custom_target(run_benchmarks
    COMMENT "Running all benchmarks"
    VERBATIM
)

cc_benchmark(args_bench
    SRCS bench_args.cc
    ARGS --benchmark_out=${CMAKE_BINARY_DIR}/bench_output.json
         --benchmark_out_format=json
)

Custom-main example:

cc_benchmark(no_main_bench
    SRCS bench_no_main.cc
    NO_MAIN
    DEPS PRIVATE calc
)

cc_fuzz()

Signature:

cc_fuzz(<target>
    [REQUIRED]
    SRCS <src>...
    [HDRS <hdr>...]
    [INCS [PUBLIC|PRIVATE <dir>...]...]
    [DEPS [PUBLIC|PRIVATE <dep>...]...]
    [DEFINES [PUBLIC|PRIVATE <define>...]...]
    [OPTIONS <option>...]
    [FEATURES <feature>...]
    [SMOKE_ARGS <arg>...]
    [SMOKE_ENV <key=value>...]
    [SMOKE_TIMEOUT <seconds>]
    [ARGS <arg>...]
)

Behavior:

  • When fuzz is requested but unavailable, logs a status message and returns without creating a target. This is the normal behavior for default C++14/test lanes.
  • Fuzz targets are created only when CC_ENABLE_FUZZTEST_AVAILABLE is true: Clang, C++17, and the isolated fuzz GTest lane via cmake --preset fuzz or equivalent setup.
  • Requires non-empty SRCS.
  • Links fuzztest::fuzztest when available, otherwise fuzztest.
  • Links the available FuzzTest GTest main provider when present.
  • With REQUIRED, configure fails if FuzzTest is unavailable with guidance to use the fuzz lane.
  • Materializes FuzzTest dependencies only when target creation is enabled.
  • Registers only a deterministic CTest smoke test named <target>_smoke with label fuzz_smoke.
  • SMOKE_ARGS and SMOKE_ENV are for fast deterministic CI smoke execution; SMOKE_TIMEOUT defaults to 30 seconds.
  • ARGS are stored as _CC_FUZZ_ARGS metadata for long-running direct executable invocation outside CTest.
  • There are no run_fuzz_<name> wrapper targets.
  • Automatically links Core runtime defaults PRIVATE, including nlohmann_json::nlohmann_json.

Example based on current root usage:

include(cmake/cc_targets.cmake)
include(cmake/cc_fuzz.cmake)

cc_fuzz(calc_fuzz
    SRCS src/calc_fuzz.cc
    DEPS PRIVATE calc
    SMOKE_ENV FUZZTEST_PRNG_SEED=42
)

Example with explicit smoke and long-run arguments:

cc_fuzz(parser_fuzz
    REQUIRED
    SRCS parser_fuzz.cc
    DEPS PRIVATE parser
    FEATURES cxx_std_17
    SMOKE_ARGS --fuzz_for=1s
    SMOKE_ENV FUZZTEST_PRNG_SEED=42
    SMOKE_TIMEOUT 10
    ARGS --fuzz_for=600s
)

cc_install()

Signature:

cc_install(<target> [DEPS <logical-name>...])

Behavior:

  • Marks an existing target for install/export by setting _CC_INSTALL TRUE.
  • Fails if the target does not exist.
  • DEPS lists install-time dependency logical names registered with cc_register_dependency().
  • DEPS is not a link dependency list. Link dependencies belong in cc_library(... DEPS ...) or cc_executable(... DEPS ...); install-time DEPS control generated find_dependency() calls and static private dependency validation.
  • Installable targets must have explicit namespaced ALIAS metadata before finalization. The helpers do not auto-create aliases.

Example using explicit install marking instead of an INSTALL keyword:

cc_library(core
    TYPE STATIC
    SRCS core.cpp
    INCS PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include
    DEPS PRIVATE ZLIB::ZLIB
    ALIAS mypkg::core
)

cc_register_dependency(zlib
    PACKAGE ZLIB
    TARGETS ZLIB::ZLIB
)

cc_install(core DEPS zlib)

cc_register_dependency()

Signature:

cc_register_dependency(<logical-name>
    PACKAGE <PackageName>
    [VERSION <version-or-range>]
    [EXACT]
    [COMPONENTS <component>...]
    [OPTIONAL_COMPONENTS <component>...]
    [TARGETS <target>...]
)

Behavior:

  • Registers package metadata for generated package config files.
  • PACKAGE is required and becomes the find_dependency(<PackageName> ...) package name.
  • VERSION, EXACT, COMPONENTS, and OPTIONAL_COMPONENTS are forwarded to find_dependency().
  • TARGETS records the imported targets provided by the package. It is metadata used by install/export validation.
  • Duplicate logical names are allowed only when all metadata matches exactly; conflicting re-registration fails at configure time.
  • Reference registered logical names from cc_install(<target> DEPS <logical-name>...).

Example:

cc_register_dependency(fmt
    PACKAGE fmt
    VERSION 10.0
    TARGETS fmt::fmt
)

cc_library(formatting
    TYPE STATIC
    SRCS formatting.cpp
    DEPS PUBLIC fmt::fmt
    ALIAS mypkg::formatting
    INSTALL
)

cc_install(formatting DEPS fmt)

cc_finalize_install()

Signature:

cc_finalize_install()

Behavior:

  • Idempotent; repeated calls after the first do nothing.
  • Returns without producing install rules when CC_ENABLE_INSTALL is OFF.
  • Uses only targets marked by INSTALL or cc_install().
  • Validates that every install target has an explicit namespaced alias of the form namespace::name.
  • Requires all installed targets to use the same namespace.
  • Sets EXPORT_NAME from the alias leaf and installs targets into a single export set named <project>Targets.
  • Generates and installs <project>Config.cmake and <project>ConfigVersion.cmake.
  • Emits find_dependency() calls for logical dependencies declared with cc_install(... DEPS ...).
  • Installs public headers from include/<project>/ when that directory exists.
  • cc_project() schedules this function with cmake_language(DEFER) for top-level projects, so most projects should not need to call it manually.

Manual finalization example for a narrow fixture or custom project layout:

include(cmake/cc_project.cmake)
include(cmake/cc_targets.cmake)
include(cmake/cc_install.cmake)

cc_project()

cc_library(core
    TYPE STATIC
    SRCS core.cpp
    ALIAS mypkg::core
    INSTALL
)

cc_finalize_install()

Unsupported helper patterns

Do not use these patterns through the helper API:

# Unsupported: OBJECT library type.
cc_library(obj TYPE OBJECT SRCS obj.cpp)

# Unsupported: missing visibility before dependency.
cc_library(core TYPE STATIC SRCS core.cpp DEPS fmt::fmt)

# Unsupported: executable build-tree aliases.
add_executable(mypkg::tool ALIAS tool)

# Unsupported: helper-specific benchmark output keyword.
cc_benchmark(core_bench SRCS bench.cc OUTPUT bench.json)

# Unsupported: expected per-target run wrappers; use run_fuzz_tests or ctest labels instead.
# Do not run: cmake --build build --target run_fuzz_core_fuzz