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

479 lines
15 KiB
Markdown

# 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:
```cmake
cc_project()
```
Use in the root `CMakeLists.txt` after native `project()` and after any cache variables that should influence helper options.
```cmake
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:
```cmake
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:
```cmake
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:
```cmake
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:
```cmake
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:
```cmake
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:
```cmake
cc_executable(my_tool
SRCS main.cpp
ALIAS my_ns::my_tool
INSTALL
)
```
## `cc_test()`
Signature:
```cmake
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:
```cmake
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:
```cmake
cc_test(mock_test
SRCS test_mock.cpp
NO_MAIN
DEPS PRIVATE my_mock_framework
)
```
## `cc_benchmark()`
Signature:
```cmake
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:
```cmake
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:
```cmake
cc_benchmark(no_main_bench
SRCS bench_no_main.cc
NO_MAIN
DEPS PRIVATE calc
)
```
## `cc_fuzz()`
Signature:
```cmake
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:
```cmake
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:
```cmake
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:
```cmake
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:
```cmake
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:
```cmake
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:
```cmake
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:
```cmake
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:
```cmake
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:
```cmake
# 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
```