Modern CMake template for C++ libraries with comprehensive infrastructure.
cpp-library
provides a standardized CMake infrastructure template for C++ libraries. It eliminates boilerplate and provides consistent patterns for:
- Project Declaration: Uses existing
project()
declaration with automatic git tag-based versioning - Library Setup: INTERFACE targets with proper installation and package config
- Testing: Integrated doctest with CTest and compile-fail test support
- Documentation: Doxygen with doxygen-awesome-css theme
- Development Tools: clangd integration, CMakePresets.json, clang-tidy support
- CI/CD: GitHub Actions workflows with multi-platform testing
- Dependency Management: CPM.cmake integration
Use CPMAddPackage to fetch cpp-library directly in your CMakeLists.txt:
cmake_minimum_required(VERSION 3.20)
# Project declaration - cpp_library_setup will use this name and detect version from git tags
project(your-library)
set(CPM_SOURCE_CACHE ${CMAKE_SOURCE_DIR}/.cache/cpm CACHE PATH "CPM cache")
include(cmake/CPM.cmake)
# Fetch cpp-library via CPM
CPMAddPackage("gh:stlab/[email protected]")
include(${cpp-library_SOURCE_DIR}/cpp-library.cmake)
cpp_library_setup(
DESCRIPTION "Your library description"
NAMESPACE your_namespace
HEADERS your_header.hpp
# Add SOURCES for non-header-only libraries (omit for header-only)
SOURCES your_library.cpp
EXAMPLES your_example.cpp your_example_fail.cpp
TESTS your_tests.cpp
DOCS_EXCLUDE_SYMBOLS "your_namespace::implementation"
)
- CPM.cmake: Must be included before using cpp-library
- CMake 3.20+: Required for modern CMake features
- C++17+: Default requirement (configurable)
cpp_library_setup(
# Required parameters
DESCRIPTION description # e.g., "Type-safe operators for enums"
NAMESPACE namespace # e.g., "stlab"
HEADERS header_list # List of header filenames (e.g., "your_header.hpp")
# Source specification for non-header-only libraries
SOURCES source_list # List of source filenames (e.g., "your_library.cpp", omit for header-only libraries)
# Optional features
[EXAMPLES example_list] # Example source files to build (e.g., "example.cpp example_fail.cpp")
[TESTS test_list] # Test source files to build (e.g., "tests.cpp")
[DOCS_EXCLUDE_SYMBOLS symbols] # Symbols to exclude from docs
[REQUIRES_CPP_VERSION 17|20|23] # C++ version (default: 17)
)
Note: The project name is automatically taken from PROJECT_NAME
(set by the project()
command). You must call project(your-library)
before cpp_library_setup()
. Version is
automatically detected from git tags.
NOTE: Examples using doctest should have test
in the name if you want them to be visible in
the TestMate test explorer.
To force regeneration of template files (CMakePresets.json, CI workflows, etc.), you can use the init
preset:
cmake --preset=init
cmake --build --preset=init
Alternatively, you can set the CMake variable CPP_LIBRARY_FORCE_INIT
to ON
:
cmake -DCPP_LIBRARY_FORCE_INIT=ON -B build/init
This will regenerate all template files, overwriting any existing ones.
The template uses consistent path conventions for all file specifications:
- HEADERS: Filenames only, automatically placed in
include/<namespace>/
directory- Examples:
your_header.hpp
,enum_ops.hpp
(automatically becomesinclude/your_namespace/your_header.hpp
)
- Examples:
- SOURCES: Filenames only, automatically placed in
src/
directory (omit for header-only libraries)- Examples:
your_library.cpp
,implementation.cpp
(automatically becomessrc/your_library.cpp
)
- Examples:
- EXAMPLES: Source files with
.cpp
extension, located inexamples/
directory- Examples:
example.cpp
,example_fail.cpp
- Examples:
- TESTS: Source files with
.cpp
extension, located intests/
directory- Examples:
tests.cpp
,unit_tests.cpp
- Examples:
The template automatically generates the full paths based on these conventions. HEADERS are placed in include/<namespace>/
and SOURCES are placed in src/
.
Header-only libraries: Specify only HEADERS
, omit SOURCES
cpp_library_setup(
DESCRIPTION "Header-only library"
NAMESPACE my_lib
HEADERS my_header.hpp
# No SOURCES needed for header-only
)
Non-header-only libraries: Specify both HEADERS
and SOURCES
cpp_library_setup(
DESCRIPTION "Library with implementation"
NAMESPACE my_lib
HEADERS my_header.hpp
SOURCES my_library.cpp implementation.cpp
)
- Non-header-only library support: For libraries with source files, specify them explicitly with the
SOURCES
argument as filenames (e.g.,"your_library.cpp"
). Both header-only and compiled libraries are supported seamlessly.
- CMakePresets.json: Generates standard presets (default, test, docs, clang-tidy, init)
- Installation: Modern CMake package config with FILE_SET headers
- Testing: doctest integration with CTest and compile-fail test support
- Documentation: Doxygen with doxygen-awesome-css theme
- Development: clangd compile_commands.json symlink
- CI/CD: GitHub Actions workflows with multi-platform testing and documentation deployment
- C++17 standard requirement (configurable)
- Ninja generator in presets
- Debug builds for testing, Release for default
- Build isolation with separate build directories
- Two-mode operation: Full infrastructure when top-level, lightweight when consumed
- Automatic version detection: Version is automatically extracted from git tags (e.g.,
v1.2.3
becomes1.2.3
) - Always-enabled features: CI/CD, CMakePresets.json, and proper installation are always generated
- [email protected] for unit testing
- Compile-fail tests: Automatic detection for examples with
_fail
suffix - CTest integration: Proper test registration and labeling
- Multi-directory support: Checks both
tests/
directories
- Doxygen integration with modern configuration
- [email protected] theme for beautiful output
- Symbol exclusion support for implementation details
- GitHub Pages deployment via CI
- Custom Doxyfile support (falls back to template)
- clang-tidy integration via CMakePresets.json
- clangd support with compile_commands.json symlink
- CMakePresets.json with multiple configurations:
default
: Release buildtest
: Debug build with testingdocs
: Documentation generationclang-tidy
: Static analysisinit
: Template regeneration (forces regeneration of CMakePresets.json, CI workflows, etc.)
- Multi-platform testing: Ubuntu, macOS, Windows
- Multi-compiler support: GCC, Clang, MSVC
- Static analysis: clang-tidy integration
- Documentation deployment: Automatic GitHub Pages deployment
- Template generation: CI workflow generation
- CPM.cmake integration for seamless fetching
- Automatic caching via CPM's built-in mechanisms
- Version pinning for reliable builds
- Git tag versioning for reliable updates
- Automatic git tag detection: Version is automatically extracted from the latest git tag
- Fallback versioning: Uses
0.0.0
if no git tag is found (with warning) - Tag format support: Supports both
v1.2.3
and1.2.3
tag formats
This template is used by:
- stlab/enum-ops - Type-safe operators for enums
- stlab/copy-on-write - Copy-on-write wrapper
cmake_minimum_required(VERSION 3.20)
project(enum-ops)
# Setup cpp-library infrastructure
set(CPM_SOURCE_CACHE ${CMAKE_SOURCE_DIR}/.cache/cpm CACHE PATH "CPM cache" FORCE)
include(cmake/CPM.cmake)
# Fetch cpp-library via CPM
CPMAddPackage("gh:stlab/[email protected]")
include(${cpp-library_SOURCE_DIR}/cpp-library.cmake)
# Configure library (handles both lightweight and full modes automatically)
cpp_library_setup(
DESCRIPTION "Type-safe operators for enums"
NAMESPACE stlab
HEADERS enum_ops.hpp
EXAMPLES enum_ops_example_test.cpp enum_ops_example_fail.cpp
TESTS enum_ops_tests.cpp
DOCS_EXCLUDE_SYMBOLS "stlab::implementation"
)
-
Initialize a new project:
# Clone or create your project mkdir my-library && cd my-library # Create basic structure mkdir -p include/your_namespace src examples tests cmake # Add CPM.cmake curl -L https://github.com/cpm-cmake/CPM.cmake/releases/latest/download/get_cpm.cmake -o cmake/CPM.cmake
-
Create CMakeLists.txt with the usage example above
-
Add your headers to
include/your_namespace/
-
Add examples to
examples/
(use_fail
suffix for compile-fail tests, e.g.,example.cpp
,example_fail.cpp
) -
Add tests to
tests/
(use_fail
suffix for compile-fail tests, e.g.,tests.cpp
,tests_fail.cpp
) -
Build and test:
cmake --preset=test cmake --build --preset=test ctest --preset=test
-
Regenerate templates (if needed):
cmake --preset=init cmake --build --preset=init
The template automatically generates:
- CMakePresets.json: Build configurations for different purposes
- .github/workflows/ci.yml: Multi-platform CI/CD pipeline
- .gitignore: Standard ignores for C++ projects
- src/: Source directory for non-header-only libraries (auto-detected)
- Package config files: For proper CMake integration
Distributed under the Boost Software License, Version 1.0. See LICENSE
.