Skip to content

Commit 995ba48

Browse files
authored
Merge pull request #2 from stlab/sean-parent/auto-versioning
Adding support to automatically version from github tag
2 parents d7968a8 + e6b20fd commit 995ba48

File tree

3 files changed

+82
-16
lines changed

3 files changed

+82
-16
lines changed

README.md

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ Modern CMake template for C++ header-only libraries with comprehensive infrastru
1111

1212
`cpp-library` provides a standardized CMake infrastructure template for header-only C++ libraries. It eliminates boilerplate and provides consistent patterns for:
1313

14+
- **Project Declaration**: Uses existing `project()` declaration with automatic git tag-based versioning
1415
- **Library Setup**: INTERFACE targets with proper installation and package config
1516
- **Testing**: Integrated doctest with CTest and compile-fail test support
1617
- **Documentation**: Doxygen with doxygen-awesome-css theme
@@ -24,7 +25,9 @@ Use CPMAddPackage to fetch cpp-library directly in your CMakeLists.txt:
2425

2526
```cmake
2627
cmake_minimum_required(VERSION 3.20)
27-
project(your-library VERSION 1.0.0 DESCRIPTION "Your library description" LANGUAGES CXX)
28+
29+
# Project declaration - cpp_library_setup will use this name and detect version from git tags
30+
project(your-library)
2831
2932
set(CPM_SOURCE_CACHE ${CMAKE_SOURCE_DIR}/.cpm-cache CACHE PATH "CPM cache")
3033
include(cmake/CPM.cmake)
@@ -34,9 +37,7 @@ CPMAddPackage("gh:stlab/[email protected]")
3437
include(${cpp-library_SOURCE_DIR}/cpp-library.cmake)
3538
3639
cpp_library_setup(
37-
NAME your-library
38-
VERSION ${PROJECT_VERSION}
39-
DESCRIPTION "${PROJECT_DESCRIPTION}"
40+
DESCRIPTION "Your library description"
4041
NAMESPACE your_namespace
4142
HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/include/your_namespace/your_header.hpp
4243
# Optional: add SOURCES for non-header-only libraries
@@ -60,11 +61,12 @@ cpp_library_setup(
6061
```cmake
6162
cpp_library_setup(
6263
# Required parameters
63-
NAME project_name # e.g., "stlab-enum-ops"
64-
VERSION version_string # e.g., "1.0.0"
6564
DESCRIPTION description # e.g., "Type-safe operators for enums"
6665
NAMESPACE namespace # e.g., "stlab"
6766
67+
# Optional parameters
68+
VERSION version_string # e.g., "1.0.0" (auto-detected from git tags if not provided)
69+
6870
# Header specification (one required)
6971
HEADERS header_list # List of header files
7072
HEADER_DIR directory # Directory to install recursively
@@ -87,6 +89,8 @@ cpp_library_setup(
8789
)
8890
```
8991

92+
**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()`.
93+
9094
## Features
9195
### Non-Header-Only Library Support
9296

@@ -110,6 +114,7 @@ cpp_library_setup(
110114
- **Debug** builds for testing, **Release** for default
111115
- **Build isolation** with separate build directories
112116
- **Two-mode operation**: Full infrastructure when top-level, lightweight when consumed
117+
- **Automatic version detection**: Version is automatically extracted from git tags (e.g., `v1.2.3` becomes `1.2.3`)
113118

114119
### Testing Features
115120

@@ -152,6 +157,13 @@ cpp_library_setup(
152157
- **Version pinning** for reliable builds
153158
- **Git tag versioning** for reliable updates
154159

160+
### Version Management
161+
162+
- **Automatic git tag detection**: Version is automatically extracted from the latest git tag
163+
- **Fallback versioning**: Uses `0.0.0` if no git tag is found (with warning)
164+
- **Manual override**: You can still specify `VERSION` parameter to override automatic detection
165+
- **Tag format support**: Supports both `v1.2.3` and `1.2.3` tag formats
166+
155167
## Example Projects
156168

157169
This template is used by:
@@ -163,7 +175,6 @@ This template is used by:
163175

164176
```cmake
165177
cmake_minimum_required(VERSION 3.20)
166-
project(stlab-enum-ops VERSION 1.0.0 DESCRIPTION "Type-safe operators for enums" LANGUAGES CXX)
167178
168179
# Setup cpp-library infrastructure
169180
set(CPM_SOURCE_CACHE ${CMAKE_SOURCE_DIR}/.cpm-cache CACHE PATH "CPM cache" FORCE)
@@ -179,8 +190,7 @@ include(${cpp-library_SOURCE_DIR}/cpp-library.cmake)
179190
# Configure library (handles both lightweight and full modes automatically)
180191
cpp_library_setup(
181192
NAME stlab-enum-ops
182-
VERSION ${PROJECT_VERSION}
183-
DESCRIPTION "${PROJECT_DESCRIPTION}"
193+
DESCRIPTION "Type-safe operators for enums"
184194
NAMESPACE stlab
185195
HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/include/stlab/enum_ops.hpp
186196
EXAMPLES enum_ops_example enum_ops_example_fail

cmake/cpp-library-setup.cmake

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,28 @@
22
#
33
# cpp-library-setup.cmake - Core library setup functionality
44

5+
# Function to get version from git tags
6+
function(_cpp_library_get_git_version OUTPUT_VAR)
7+
# Try to get version from git tags
8+
execute_process(
9+
COMMAND git describe --tags --abbrev=0
10+
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
11+
OUTPUT_VARIABLE GIT_TAG_VERSION
12+
OUTPUT_STRIP_TRAILING_WHITESPACE
13+
ERROR_QUIET
14+
)
15+
16+
# If git tag found, use it (remove 'v' prefix if present)
17+
if(GIT_TAG_VERSION)
18+
string(REGEX REPLACE "^v" "" CLEAN_VERSION "${GIT_TAG_VERSION}")
19+
set(${OUTPUT_VAR} "${CLEAN_VERSION}" PARENT_SCOPE)
20+
else()
21+
# Fallback to 0.0.0 if no git tag found
22+
set(${OUTPUT_VAR} "0.0.0" PARENT_SCOPE)
23+
message(WARNING "No git tag found, using version 0.0.0. Consider creating a git tag for proper versioning.")
24+
endif()
25+
endfunction()
26+
527
function(_cpp_library_setup_core)
628
set(oneValueArgs
729
NAME
@@ -19,6 +41,15 @@ function(_cpp_library_setup_core)
1941

2042
cmake_parse_arguments(ARG "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
2143

44+
# Get version from git tags if not provided
45+
if(NOT ARG_VERSION)
46+
_cpp_library_get_git_version(GIT_VERSION)
47+
set(ARG_VERSION "${GIT_VERSION}")
48+
endif()
49+
50+
# Note: Project declaration is now handled in the main cpp_library_setup function
51+
# No need to check ARG_TOP_LEVEL here for project declaration
52+
2253
# Extract the library name without namespace prefix for target naming
2354
string(REPLACE "${ARG_NAMESPACE}-" "" CLEAN_NAME "${ARG_NAME}")
2455

cpp-library.cmake

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ function(cpp_library_setup)
2828
FORCE_INIT # Force regeneration of template files
2929
)
3030
set(oneValueArgs
31-
NAME # Project name (e.g., "stlab-enum-ops")
3231
VERSION # Version string (e.g., "1.0.0")
3332
DESCRIPTION # Description string
3433
NAMESPACE # Namespace (e.g., "stlab")
@@ -55,12 +54,6 @@ function(cpp_library_setup)
5554
endif()
5655

5756
# Validate required arguments
58-
if(NOT ARG_NAME)
59-
message(FATAL_ERROR "cpp_library_setup: NAME is required")
60-
endif()
61-
if(NOT ARG_VERSION)
62-
message(FATAL_ERROR "cpp_library_setup: VERSION is required")
63-
endif()
6457
if(NOT ARG_DESCRIPTION)
6558
message(FATAL_ERROR "cpp_library_setup: DESCRIPTION is required")
6659
endif()
@@ -71,6 +64,12 @@ function(cpp_library_setup)
7164
message(FATAL_ERROR "cpp_library_setup: Either HEADERS or HEADER_DIR is required")
7265
endif()
7366

67+
# Use PROJECT_NAME as the library name
68+
if(NOT DEFINED PROJECT_NAME)
69+
message(FATAL_ERROR "cpp_library_setup: PROJECT_NAME must be defined. Call project() before cpp_library_setup()")
70+
endif()
71+
set(ARG_NAME "${PROJECT_NAME}")
72+
7473
# Set defaults
7574
if(NOT ARG_REQUIRES_CPP_VERSION)
7675
set(ARG_REQUIRES_CPP_VERSION 17)
@@ -81,6 +80,32 @@ function(cpp_library_setup)
8180
set(ARG_FORCE_INIT TRUE)
8281
endif()
8382

83+
# Get version from git tags if not provided
84+
if(NOT ARG_VERSION)
85+
_cpp_library_get_git_version(GIT_VERSION)
86+
set(ARG_VERSION "${GIT_VERSION}")
87+
endif()
88+
89+
# Parse version components for manual setting
90+
string(REGEX MATCH "^([0-9]+)\\.([0-9]+)\\.([0-9]+)" VERSION_MATCH "${ARG_VERSION}")
91+
if(VERSION_MATCH)
92+
set(ARG_VERSION_MAJOR ${CMAKE_MATCH_1})
93+
set(ARG_VERSION_MINOR ${CMAKE_MATCH_2})
94+
set(ARG_VERSION_PATCH ${CMAKE_MATCH_3})
95+
else()
96+
set(ARG_VERSION_MAJOR 0)
97+
set(ARG_VERSION_MINOR 0)
98+
set(ARG_VERSION_PATCH 0)
99+
endif()
100+
101+
# Update project version if it was detected from git
102+
if(NOT DEFINED PROJECT_VERSION OR PROJECT_VERSION STREQUAL "")
103+
set(PROJECT_VERSION ${ARG_VERSION} PARENT_SCOPE)
104+
set(PROJECT_VERSION_MAJOR ${ARG_VERSION_MAJOR} PARENT_SCOPE)
105+
set(PROJECT_VERSION_MINOR ${ARG_VERSION_MINOR} PARENT_SCOPE)
106+
set(PROJECT_VERSION_PATCH ${ARG_VERSION_PATCH} PARENT_SCOPE)
107+
endif()
108+
84109
# Create the basic library target (always done)
85110
_cpp_library_setup_core(
86111
NAME "${ARG_NAME}"

0 commit comments

Comments
 (0)