This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
cpp-library is not a C++ library itself — it's a CMake infrastructure template/toolkit that other C++ library repositories consume (via CPMAddPackage) to get a standardized build, test, install, docs, and CI setup. There is no C++ source to compile in this repo; the "code" is CMake script (.cmake files) plus template files that get copied/configured into consumer projects.
Two ways consumers use this repo:
setup.cmake— a standalone script (cmake -P setup.cmake) that scaffolds a brand-new library project (directory structure,CMakeLists.txt, template header, git init).cpp-library.cmake— included by a consumer'sCMakeLists.txtvia CPM; provides thecpp_library_setup(...)function and friends that an existing/generated project calls to wire up its library target, tests, docs, install rules, and CI.
Run cpp-library's tests through CMake scripts. Integration fixtures require a C++ compiler and Ninja; documentation rendering also requires Doxygen:
cmake -P tests/install/CMakeLists.txt # dependency mapping/merging unit tests
cmake -P tests/install/test_provider_merge.cmake # dependency provider merge tests
cmake -P tests/setup/test_setup_version_resolution.cmake # setup.cmake version-resolution integration test
cmake -P tests/setup/test_runtime_dlls.cmake # custom target DLL deployment; requires compiler and Ninja
cmake -P tests/docs/test_docs.cmake # docs extensions and rendering; requires Doxygen and NinjaCI (.github/workflows/ci.yml) runs these scripts in its unit-test, Windows
package, and documentation jobs. There is no library build step for cpp-library
itself; integration scripts configure and build their own consumer fixtures.
CI also runs an integration-tests job that generates a throwaway consumer project, configures/builds/installs it against this repo via CPMAddPackage(... SOURCE_DIR ...), then verifies find_package() works against the installed package — this is the best reference for the full round-trip a downstream project goes through.
To exercise cpp-library manually against a local consumer project without publishing a release:
CPMAddPackage(
NAME cpp-library
SOURCE_DIR "${CMAKE_SOURCE_DIR}/../cpp-library"
)or pin to a specific commit: CPMAddPackage("gh:stlab/cpp-library#<commit-sha>").
cpp-library.cmake(root) — entry point; definescpp_library_set_version()andcpp_library_enable_dependency_tracking(), then includes the modules below.cpp_library_enable_dependency_tracking()must be called beforeproject()— it registerscpp-library-dependency-provider.cmakeviaCMAKE_PROJECT_TOP_LEVEL_INCLUDESso CMake's dependency-provider hook (3.24+) is active for theproject()call that follows.cpp-library-setup.cmake— the corecpp_library_setup(...)function (called fromcpp-library.cmake, which is why the module split doesn't map 1:1 to files: some logic that requiresproject()to already have run — install, docs, CI templating — is deferred and included lazily insidecpp_library_setup()rather than at top-levelinclude()time).cpp-library-install.cmake— install rules, packageConfig.cmake/ConfigVersion.cmakegeneration, and thefind_dependency()derivation logic. Onlyinclude()d insidecpp_library_setup()(needsproject()forGNUInstallDirs).cpp-library-dependency-provider.cmake— implements the CMake dependency-provider callback (SET_DEPENDENCY_PROVIDER) that intercepts everyfind_package()/FetchContent_MakeAvailable()call to record the exact package/version/components used, soConfig.cmakecan regenerate accuratefind_dependency()calls at install time. State is stored inGLOBALproperties (_CPP_LIBRARY_TRACKED_DEP_*,_CPP_LIBRARY_PKG_KEYS, etc.) — there's no other persistence mechanism, so tests reset these properties between cases (seetests/install/CMakeLists.txt).cpp-library-docs.cmake— Doxygen + doxygen-awesome-css target (docs).cpp-library-ci.cmake— generates.github/workflows/ci.ymlfor the consumer project fromtemplates/.github/workflows/ci.yml.in, substituting the package name.cpp-library-testing.cmake— publiccpp_library_copy_runtime_dlls()helper and backward-compatibility_cpp_library_setup_testing()wrapper; test/example executable creation lives in_cpp_library_setup_executables()incpp-library.cmake.
- Consumer calls
cpp_library_enable_dependency_tracking()beforeproject(). - Consumer calls
project(name), theninclude(CTest)if using TESTS/EXAMPLES, thencpp_library_setup(NAMESPACE ... HEADERS ... [SOURCES ...] [TESTS ...] [EXAMPLES ...]). cpp_library_setup():- Derives
PACKAGE_NAME(namespace-prefixed, e.g.stlab-enum-ops) andCLEAN_NAME(namespace stripped fromPROJECT_NAME). - Sets project version from git tags (
_cpp_library_get_git_version, overridable viaCPP_LIBRARY_VERSIONcache var for package managers without git history). - Creates the library target (
INTERFACEif noSOURCES, else a compiled target respectingBUILD_SHARED_LIBS) withFILE_SET headers, aliased asNAMESPACE::CLEAN_NAME. - Calls
_cpp_library_setup_install(), which is gated by${NAMESPACE}_INSTALL(defaultPROJECT_IS_TOP_LEVEL) and usescmake_language(DEFER)to generateConfig.cmakeand register install-time dependency validation after alltarget_link_libraries()calls in the consumer'sCMakeLists.txthave executed (deferred calls run LIFO — validation is registered first so it executes last, right before config files are written). - If
PROJECT_IS_TOP_LEVEL: also copies static template files (.clang-format,.gitignore,CMakePresets.json, etc. — skipped if already present unlessCPP_LIBRARY_FORCE_INITis set), configures the CI workflow, downloads doctest, and wires upTESTS/EXAMPLES/docs. When consumed as a subproject (not top-level), it returns early after target creation — "lightweight consumer mode".
- Derives
- At install time, if any dependency was linked but never went through a tracked
find_package()/CPMAddPackage()call at the top-level scope (e.g. added in a subdirectory), the install step fails with a detailed error (_cpp_library_setup_install_validation) rather than silently emitting a brokenConfig.cmake. During plainconfigure/build(no install), the same situation is only a warning ("Untracked dependencies").
project(component-name)+NAMESPACE org→ targetcomponent-name, aliasorg::component-name, packageorg-component-name, GitHub repo must beorg/org-component-name.- Special case:
project(org)+NAMESPACE org→ package/target collapse to justorg(no duplication). - Non-namespaced link targets (e.g.
opencv_core) can't be resolved automatically and requirecpp_library_map_dependency(target "Package Version").
Static files copied verbatim (or via configure_file() for .in files) into a consumer project the first time it configures, or when CPP_LIBRARY_FORCE_INIT/init preset is used to regenerate them. Not used by cpp-library's own build — these are outputs, not inputs.
Not C++ unit tests — these are cmake -P scripts that test the CMake functions themselves in isolation, using mocked get_target_property() and manually-reset GLOBAL properties between cases (see run_test() macro in tests/install/CMakeLists.txt). When adding a new dependency-mapping test case, follow the pattern in tests/install/README.md (run_test() → set up mock target/links → call the function under test → verify_output()).