Skip to content

Commit d3892af

Browse files
authored
Merge pull request #7 from stlab/sean-parent/cleanup
Cleanup
2 parents 6e83d11 + aaa4c69 commit d3892af

File tree

5 files changed

+99
-131
lines changed

5 files changed

+99
-131
lines changed

README.md

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ Modern CMake template for C++ libraries with comprehensive infrastructure.
1212
`cpp-library` provides a standardized CMake infrastructure template for C++ libraries. It eliminates boilerplate and provides consistent patterns for:
1313

1414
- **Project Declaration**: Uses existing `project()` declaration with automatic git tag-based versioning
15-
- **Library Setup**: INTERFACE targets with proper installation and package config
1615
- **Testing**: Integrated doctest with CTest and compile-fail test support
1716
- **Documentation**: Doxygen with doxygen-awesome-css theme
1817
- **Development Tools**: clangd integration, CMakePresets.json, clang-tidy support
@@ -29,7 +28,10 @@ cmake_minimum_required(VERSION 3.20)
2928
# Project declaration - cpp_library_setup will use this name and detect version from git tags
3029
project(your-library)
3130
32-
set(CPM_SOURCE_CACHE ${CMAKE_SOURCE_DIR}/.cache/cpm CACHE PATH "CPM cache")
31+
# Setup cpp-library infrastructure
32+
if(PROJECT_IS_TOP_LEVEL)
33+
set(CPM_SOURCE_CACHE ${CMAKE_SOURCE_DIR}/.cache/cpm CACHE PATH "CPM cache")
34+
endif()
3335
include(cmake/CPM.cmake)
3436
3537
# Fetch cpp-library via CPM
@@ -64,13 +66,13 @@ cpp_library_setup(
6466
DESCRIPTION description # e.g., "Type-safe operators for enums"
6567
NAMESPACE namespace # e.g., "stlab"
6668
HEADERS header_list # List of header filenames (e.g., "your_header.hpp")
67-
69+
6870
# Source specification for non-header-only libraries
6971
SOURCES source_list # List of source filenames (e.g., "your_library.cpp", omit for header-only libraries)
7072
7173
# Optional features
7274
[EXAMPLES example_list] # Example source files to build (e.g., "example.cpp example_fail.cpp")
73-
[TESTS test_list] # Test source files to build (e.g., "tests.cpp")
75+
[TESTS test_list] # Test source files to build (e.g., "tests.cpp")
7476
[DOCS_EXCLUDE_SYMBOLS symbols] # Symbols to exclude from docs
7577
[REQUIRES_CPP_VERSION 17|20|23] # C++ version (default: 17)
7678
)
@@ -118,6 +120,7 @@ The template automatically generates the full paths based on these conventions.
118120
### Library Types
119121

120122
**Header-only libraries**: Specify only `HEADERS`, omit `SOURCES`
123+
121124
```cmake
122125
cpp_library_setup(
123126
DESCRIPTION "Header-only library"
@@ -128,6 +131,7 @@ cpp_library_setup(
128131
```
129132

130133
**Non-header-only libraries**: Specify both `HEADERS` and `SOURCES`
134+
131135
```cmake
132136
cpp_library_setup(
133137
DESCRIPTION "Library with implementation"
@@ -138,15 +142,15 @@ cpp_library_setup(
138142
```
139143

140144
## Features
145+
141146
### Non-Header-Only Library Support
142147

143148
- **Non-header-only library support**: For libraries with source files, specify them explicitly with the `SOURCES` argument as filenames (e.g., `"your_library.cpp"`).
144-
Both header-only and compiled libraries are supported seamlessly.
149+
Both header-only and compiled libraries are supported seamlessly.
145150

146151
### Automated Infrastructure
147152

148153
- **CMakePresets.json**: Generates standard presets (default, test, docs, clang-tidy, init)
149-
- **Installation**: Modern CMake package config with FILE_SET headers
150154
- **Testing**: doctest integration with CTest and compile-fail test support
151155
- **Documentation**: Doxygen with doxygen-awesome-css theme
152156
- **Development**: clangd compile_commands.json symlink
@@ -155,12 +159,12 @@ cpp_library_setup(
155159
### Smart Defaults
156160

157161
- **C++17** standard requirement (configurable)
158-
- **Ninja** generator in presets
162+
- **Ninja** generator in presets
159163
- **Debug** builds for testing, **Release** for default
160164
- **Build isolation** with separate build directories
161165
- **Two-mode operation**: Full infrastructure when top-level, lightweight when consumed
162166
- **Automatic version detection**: Version is automatically extracted from git tags (e.g., `v1.2.3` becomes `1.2.3`)
163-
- **Always-enabled features**: CI/CD, CMakePresets.json, and proper installation are always generated
167+
- **Always-enabled features**: CI/CD, and CMakePresets.json, are always generated
164168

165169
### Testing Features
166170

@@ -172,7 +176,7 @@ cpp_library_setup(
172176
### Documentation Features
173177

174178
- **Doxygen integration** with modern configuration
175-
- **[email protected].0** theme for beautiful output
179+
- **[email protected].1** theme for beautiful output
176180
- **Symbol exclusion** support for implementation details
177181
- **GitHub Pages deployment** via CI
178182
- **Custom Doxyfile support** (falls back to template)
@@ -223,7 +227,9 @@ cmake_minimum_required(VERSION 3.20)
223227
project(enum-ops)
224228
225229
# Setup cpp-library infrastructure
226-
set(CPM_SOURCE_CACHE ${CMAKE_SOURCE_DIR}/.cache/cpm CACHE PATH "CPM cache" FORCE)
230+
if(PROJECT_IS_TOP_LEVEL)
231+
set(CPM_SOURCE_CACHE ${CMAKE_SOURCE_DIR}/.cache/cpm CACHE PATH "CPM cache")
232+
endif()
227233
include(cmake/CPM.cmake)
228234
229235
# Fetch cpp-library via CPM
@@ -244,13 +250,14 @@ cpp_library_setup(
244250
## Quick Start
245251

246252
1. **Initialize a new project**:
253+
247254
```bash
248255
# Clone or create your project
249256
mkdir my-library && cd my-library
250-
257+
251258
# Create basic structure
252259
mkdir -p include/your_namespace src examples tests cmake
253-
260+
254261
# Add CPM.cmake
255262
curl -L https://github.com/cpm-cmake/CPM.cmake/releases/latest/download/get_cpm.cmake -o cmake/CPM.cmake
256263
```
@@ -264,6 +271,7 @@ cpp_library_setup(
264271
5. **Add tests** to `tests/` (use `_fail` suffix for compile-fail tests, e.g., `tests.cpp`, `tests_fail.cpp`)
265272

266273
6. **Build and test**:
274+
267275
```bash
268276
cmake --preset=test
269277
cmake --build --preset=test
@@ -280,11 +288,11 @@ cpp_library_setup(
280288

281289
The template automatically generates:
282290

283-
- **CMakePresets.json**: Build configurations for different purposes
284-
- **.github/workflows/ci.yml**: Multi-platform CI/CD pipeline
285-
- **.gitignore**: Standard ignores for C++ projects
286-
- **src/**: Source directory for non-header-only libraries (auto-detected)
287-
- **Package config files**: For proper CMake integration
291+
- **CMakePresets.json**: Build configurations for different purposes
292+
- **.github/workflows/ci.yml**: Multi-platform CI/CD pipeline
293+
- **.gitignore**: Standard ignores for C++ projects
294+
- **src/**: Source directory for non-header-only libraries (auto-detected)
295+
- **Package config files**: For proper CMake integration
288296

289297
## License
290298

cmake/cpp-library-docs.cmake

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,28 +11,29 @@ function(_cpp_library_setup_docs)
1111
set(multiValueArgs
1212
DOCS_EXCLUDE_SYMBOLS
1313
)
14-
14+
1515
cmake_parse_arguments(ARG "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
16-
16+
1717
find_package(Doxygen REQUIRED)
1818
if(NOT DOXYGEN_FOUND)
1919
message(WARNING "Doxygen not found. Documentation will not be built.")
2020
return()
2121
endif()
22-
22+
2323
# Download doxygen-awesome-css theme via CPM
24+
# https://github.com/jothepro/doxygen-awesome-css
2425
CPMAddPackage(
25-
URI gh:jothepro/[email protected].0
26+
URI gh:jothepro/[email protected].1
2627
DOWNLOAD_ONLY YES
2728
)
28-
29+
2930
# Set the CSS directory path
3031
set(AWESOME_CSS_DIR ${doxygen-awesome-css_SOURCE_DIR})
31-
32+
3233
# Configure Doxyfile from template
3334
set(DOXYFILE_IN ${CPP_LIBRARY_ROOT}/templates/Doxyfile.in)
3435
set(DOXYFILE_OUT ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)
35-
36+
3637
# Set variables for Doxyfile template
3738
set(PROJECT_NAME "${ARG_NAME}")
3839
set(PROJECT_BRIEF "${ARG_DESCRIPTION}")
@@ -41,27 +42,27 @@ function(_cpp_library_setup_docs)
4142
set(OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}")
4243
set(AWESOME_CSS_PATH "${AWESOME_CSS_DIR}")
4344
set(EXAMPLES_PATH "${CMAKE_CURRENT_SOURCE_DIR}/examples")
44-
45+
4546
# Convert exclude symbols list to space-separated string
4647
if(ARG_DOCS_EXCLUDE_SYMBOLS)
4748
string(REPLACE ";" " " EXCLUDE_SYMBOLS_STR "${ARG_DOCS_EXCLUDE_SYMBOLS}")
4849
set(EXCLUDE_SYMBOLS "${EXCLUDE_SYMBOLS_STR}")
4950
else()
5051
set(EXCLUDE_SYMBOLS "")
5152
endif()
52-
53+
5354
# Check if we have a custom Doxyfile, otherwise use template
5455
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/docs/Doxyfile")
5556
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/docs/Doxyfile" ${DOXYFILE_OUT} @ONLY)
5657
else()
5758
configure_file(${DOXYFILE_IN} ${DOXYFILE_OUT} @ONLY)
5859
endif()
59-
60+
6061
# Add custom target for documentation with proper stderr capture
6162
if(WIN32)
6263
# On Windows, use PowerShell to redirect stderr to stdout
6364
add_custom_target(docs
64-
COMMAND PowerShell -Command "& { ${DOXYGEN_EXECUTABLE} ${DOXYFILE_OUT} 2>&1 }"
65+
COMMAND PowerShell -Command "& '${DOXYGEN_EXECUTABLE}' '${DOXYFILE_OUT}' 2>&1"
6566
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
6667
COMMENT "Generating API documentation with Doxygen"
6768
VERBATIM
@@ -75,11 +76,11 @@ function(_cpp_library_setup_docs)
7576
VERBATIM
7677
)
7778
endif()
78-
79+
7980
# Ensure the output directory exists
8081
file(MAKE_DIRECTORY ${OUTPUT_DIR})
81-
82+
8283
message(STATUS "Documentation target 'docs' configured")
8384
message(STATUS "Run 'cmake --build . --target docs' to generate documentation")
84-
85+
8586
endfunction()

cmake/cpp-library-setup.cmake

Lines changed: 10 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ function(_cpp_library_get_git_version OUTPUT_VAR)
1212
OUTPUT_STRIP_TRAILING_WHITESPACE
1313
ERROR_QUIET
1414
)
15-
15+
1616
# If git tag found, use it (remove 'v' prefix if present)
1717
if(GIT_TAG_VERSION)
1818
string(REGEX REPLACE "^v" "" CLEAN_VERSION "${GIT_TAG_VERSION}")
@@ -27,7 +27,7 @@ endfunction()
2727
function(_cpp_library_setup_core)
2828
set(oneValueArgs
2929
NAME
30-
VERSION
30+
VERSION
3131
DESCRIPTION
3232
NAMESPACE
3333
REQUIRES_CPP_VERSION
@@ -37,28 +37,27 @@ function(_cpp_library_setup_core)
3737
HEADERS
3838
SOURCES
3939
)
40-
40+
4141
cmake_parse_arguments(ARG "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
42-
42+
4343
# Get version from git tags if not provided
4444
if(NOT ARG_VERSION)
4545
_cpp_library_get_git_version(GIT_VERSION)
4646
set(ARG_VERSION "${GIT_VERSION}")
4747
endif()
48-
48+
4949
# Note: Project declaration is now handled in the main cpp_library_setup function
5050
# No need to check ARG_TOP_LEVEL here for project declaration
51-
51+
5252
# Extract the library name without namespace prefix for target naming
5353
string(REPLACE "${ARG_NAMESPACE}-" "" CLEAN_NAME "${ARG_NAME}")
54-
54+
5555
if(ARG_SOURCES)
5656
# Create a regular library if sources are present
5757
add_library(${ARG_NAME} STATIC ${ARG_SOURCES})
5858
add_library(${ARG_NAMESPACE}::${CLEAN_NAME} ALIAS ${ARG_NAME})
5959
target_include_directories(${ARG_NAME} PUBLIC
6060
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
61-
$<INSTALL_INTERFACE:include>
6261
)
6362
target_compile_features(${ARG_NAME} PUBLIC cxx_std_${ARG_REQUIRES_CPP_VERSION})
6463
if(ARG_HEADERS)
@@ -75,7 +74,6 @@ function(_cpp_library_setup_core)
7574
add_library(${ARG_NAMESPACE}::${CLEAN_NAME} ALIAS ${ARG_NAME})
7675
target_include_directories(${ARG_NAME} INTERFACE
7776
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
78-
$<INSTALL_INTERFACE:include>
7977
)
8078
target_compile_features(${ARG_NAME} INTERFACE cxx_std_${ARG_REQUIRES_CPP_VERSION})
8179
if(ARG_HEADERS)
@@ -87,46 +85,7 @@ function(_cpp_library_setup_core)
8785
)
8886
endif()
8987
endif()
90-
91-
# Only set up full installation when building as top-level project
92-
if(ARG_TOP_LEVEL)
93-
include(GNUInstallDirs)
94-
include(CMakePackageConfigHelpers)
95-
96-
# Install the target
97-
install(TARGETS ${ARG_NAME}
98-
EXPORT ${ARG_NAME}Targets
99-
FILE_SET headers DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
100-
)
101-
102-
# Generate package config files
103-
write_basic_package_version_file(
104-
"${CMAKE_CURRENT_BINARY_DIR}/${ARG_NAME}ConfigVersion.cmake"
105-
VERSION ${ARG_VERSION}
106-
COMPATIBILITY SameMajorVersion
107-
)
108-
109-
configure_file(
110-
"${CPP_LIBRARY_ROOT}/templates/Config.cmake.in"
111-
"${CMAKE_CURRENT_BINARY_DIR}/${ARG_NAME}Config.cmake"
112-
@ONLY
113-
)
114-
115-
# Install export targets
116-
install(EXPORT ${ARG_NAME}Targets
117-
FILE ${ARG_NAME}Targets.cmake
118-
NAMESPACE ${ARG_NAMESPACE}::
119-
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${ARG_NAME}
120-
)
121-
122-
# Install config files
123-
install(FILES
124-
"${CMAKE_CURRENT_BINARY_DIR}/${ARG_NAME}Config.cmake"
125-
"${CMAKE_CURRENT_BINARY_DIR}/${ARG_NAME}ConfigVersion.cmake"
126-
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${ARG_NAME}
127-
)
128-
endif()
129-
88+
13089
endfunction()
13190

13291
# Function to copy static template files
@@ -148,15 +107,15 @@ function(_cpp_library_copy_templates)
148107
foreach(template_file IN LISTS TEMPLATE_FILES)
149108
set(source_file "${CPP_LIBRARY_ROOT}/templates/${template_file}")
150109
set(dest_file "${CMAKE_CURRENT_SOURCE_DIR}/${template_file}")
151-
110+
152111
# Check if template file exists
153112
if(EXISTS "${source_file}")
154113
# Copy if file doesn't exist or FORCE_INIT is enabled
155114
if(NOT EXISTS "${dest_file}" OR ARG_FORCE_INIT)
156115
# Create directory if needed
157116
get_filename_component(dest_dir "${dest_file}" DIRECTORY)
158117
file(MAKE_DIRECTORY "${dest_dir}")
159-
118+
160119
# Copy the file
161120
file(COPY "${source_file}" DESTINATION "${dest_dir}")
162121
message(STATUS "Copied template file: ${template_file}")

0 commit comments

Comments
 (0)