Skip to content

Commit e6b20fd

Browse files
committed
Adding support to automatically version from github tag
Reducing redundancy and picking up the version from the project's GitHub tags so they update automatically with each release.
1 parent d7968a8 commit e6b20fd

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)