3
3
#
4
4
# https://github.com/sethrj/cmake-git-version
5
5
#
6
- # Copyright 2021 UT-Battelle, LLC and Seth R Johnson
6
+ # Copyright 2021-2023 UT-Battelle, LLC
7
7
#
8
- # Licensed under the Apache License, Version 2.0 (the "License");
9
- # you may not use this file except in compliance with the License.
10
- # You may obtain a copy of the License at
8
+ # Licensed under the Apache License, Version 2.0 (the "License");
9
+ # you may not use this file except in compliance with the License.
10
+ # You may obtain a copy of the License at
11
11
#
12
- # http://www.apache.org/licenses/LICENSE-2.0
12
+ # http://www.apache.org/licenses/LICENSE-2.0
13
13
#
14
- # Unless required by applicable law or agreed to in writing, software
15
- # distributed under the License is distributed on an "AS IS" BASIS,
16
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
- # See the License for the specific language governing permissions and
18
- # limitations under the License.
14
+ # Unless required by applicable law or agreed to in writing, software
15
+ # distributed under the License is distributed on an "AS IS" BASIS,
16
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
+ # See the License for the specific language governing permissions and
18
+ # limitations under the License.
19
19
#[=======================================================================[.rst:
20
20
21
21
CgvFindVersion
@@ -31,13 +31,15 @@ CgvFindVersion
31
31
``<projname>``
32
32
Name of the project.
33
33
34
- This command sets the following variables in the parent package::
34
+ This command sets the numeric (usable in CMake version comparisons) and
35
+ extended (useful for exact versioning) version variables in the parent
36
+ package::
35
37
36
38
${projname}_VERSION
37
39
${projname}_VERSION_STRING
38
40
39
- It takes the project name and version file path as optional arguments to
40
- support using it before the CMake ``project`` command.
41
+ It takes the project name as an optional argument so that it may be used
42
+ * before* calling the CMake ``project`` command.
41
43
42
44
The project version string uses an approximation to SemVer strings, appearing
43
45
as v0.1.2 if the version is actually a tagged release, or v0.1.3+abcdef if
@@ -47,10 +49,13 @@ CgvFindVersion
47
49
it's impossible to determine the version from the tag, so a warning will be
48
50
issued and the version will be set to 0.0.0.
49
51
50
- The exact regex used to match the version tag is::
52
+ The default regex used to match the numeric version and full version string
53
+ from the git tag is::
51
54
52
55
v([0-9.]+)(-dev[0-9.]+)?
53
56
57
+ but you can override the regex by setting the ``CGV_TAG_REGEX`` variable
58
+ before calling ``cgv_find_version``.
54
59
55
60
.. note:: In order for this script to work properly with archived git
56
61
repositories (generated with ``git-archive`` or GitHub's release tarball
@@ -64,108 +69,198 @@ if(CMAKE_SCRIPT_MODE_FILE)
64
69
cmake_minimum_required (VERSION 3.8)
65
70
endif ()
66
71
67
- function (cgv_find_version)
68
- set (projname "${ARGV0} " )
69
- if (NOT projname)
70
- set (projname "${CMAKE_PROJECT_NAME} " )
71
- if (NOT projname)
72
- message (FATAL_ERROR "Project name is not defined" )
73
- endif ()
72
+ #-----------------------------------------------------------------------------#
73
+
74
+ function (_cgv_store_version string suffix hash)
75
+ if (NOT string )
76
+ message (WARNING "The version metadata for ${CGV_PROJECT} could not "
77
+ "be determined: installed version number may be incorrect" )
74
78
endif ()
79
+ set (_CACHED_VERSION "${string} " "${suffix} " "${hash} " )
80
+ # Note: extra 'unset' is necessary if using CMake presets with
81
+ # ${CGV_PROJECT}_GIT_DESCRIBE="", even with INTERNAL/FORCE
82
+ unset (${CGV_CACHE_VAR} CACHE )
83
+ set (${CGV_CACHE_VAR} "${_CACHED_VERSION} " CACHE INTERNAL
84
+ "Version string and hash for ${CGV_PROJECT} " )
85
+ endfunction ()
86
+
87
+ #-----------------------------------------------------------------------------#
75
88
89
+ function (_cgv_try_archive_md)
76
90
# Get a possible Git version generated using git-archive (see the
77
91
# .gitattributes file)
92
+ set (_ARCHIVE_DESCR "$Format:%$" )
78
93
set (_ARCHIVE_TAG "$Format:%D$" )
79
94
set (_ARCHIVE_HASH "$Format:%h$" )
95
+ if (_ARCHIVE_HASH MATCHES "Format:%h" )
96
+ # Not a git archive
97
+ return ()
98
+ endif ()
80
99
81
- set (_TAG_REGEX "v([0-9.]+)(-dev[0-9.]+)?" )
82
- set (_HASH_REGEX "([0-9a-f]+)" )
83
-
84
- if (_ARCHIVE_HASH MATCHES "%h" )
85
- # Not a "git archive": use live git information
86
- set (_CACHE_VAR "${projname} _GIT_DESCRIBE" )
87
- set (_CACHED_VERSION "${${_CACHE_VAR} }" )
88
- if (NOT _CACHED_VERSION)
89
- # Building from a git checkout rather than a distribution
90
- if (NOT GIT_EXECUTABLE)
91
- find_package (Git QUIET REQUIRED)
92
- endif ()
93
- execute_process (
94
- COMMAND "${GIT_EXECUTABLE} " "describe" "--tags" "--match" "v*"
95
- WORKING_DIRECTORY "${CMAKE_CURRENT_LIST_DIR} "
96
- ERROR_VARIABLE _GIT_ERR
97
- OUTPUT_VARIABLE _VERSION_STRING
98
- RESULT_VARIABLE _GIT_RESULT
99
- OUTPUT_STRIP_TRAILING_WHITESPACE
100
- )
101
- if (_GIT_RESULT)
102
- message (AUTHOR_WARNING "No git tags in ${projname} matched 'v*': "
103
- "${_GIT_ERR} " )
104
- elseif (NOT _VERSION_STRING)
105
- message (WARNING "Failed to get ${projname} version from git: "
106
- "git describe returned an empty string" )
107
- else ()
108
- # Process description tag: e.g. v0.4.0-2-gc4af497 or v0.4.0
109
- # or v2.0.0-dev2
110
- string (REGEX MATCH "^${_TAG_REGEX} (-[0-9]+-g${_HASH_REGEX} )?" _MATCH
111
- "${_VERSION_STRING} "
112
- )
113
- if (_MATCH)
114
- set (_VERSION_STRING "${CMAKE_MATCH_1} " )
115
- set (_VERSION_STRING_SUFFIX "${CMAKE_MATCH_2} " )
116
- if (CMAKE_MATCH_3)
117
- # *not* a tagged release
118
- set (_VERSION_HASH "${CMAKE_MATCH_4} " )
119
- endif ()
120
- endif ()
121
- endif ()
122
- if (NOT _VERSION_STRING)
123
- execute_process (
124
- COMMAND "${GIT_EXECUTABLE} " "log" "-1" "--format=%h" "HEAD"
125
- WORKING_DIRECTORY "${CMAKE_CURRENT_LIST_DIR} "
126
- OUTPUT_VARIABLE _VERSION_HASH
127
- OUTPUT_STRIP_TRAILING_WHITESPACE
128
- )
129
- endif ()
130
- set (_CACHED_VERSION "${_VERSION_STRING} " "${_VERSION_STRING_SUFFIX} " "${_VERSION_HASH} " )
131
- set ("${_CACHE_VAR} " "${_CACHED_VERSION} " CACHE INTERNAL
132
- "Version string and hash for ${projname} " )
133
- endif ()
134
- list (GET _CACHED_VERSION 0 _VERSION_STRING)
135
- list (GET _CACHED_VERSION 1 _VERSION_STRING_SUFFIX)
136
- list (GET _CACHED_VERSION 2 _VERSION_HASH)
100
+ string (REGEX MATCH "tag: *${CGV_TAG_REGEX} " _MATCH "${_ARCHIVE_TAG} " )
101
+ if (_MATCH)
102
+ _cgv_store_version("${CMAKE_MATCH_1} " "${CMAKE_MATCH_2} " "" )
137
103
else ()
138
- string (REGEX MATCH "tag: *${_TAG_REGEX} " _MATCH "${_ARCHIVE_TAG} " )
104
+ message (WARNING "Could not match a version tag for "
105
+ "git description '${_ARCHIVE_TAG} ': perhaps this archive was not "
106
+ "exported from a tagged commit?" )
107
+ string (REGEX MATCH " *([0-9a-f]+)" _MATCH "${_ARCHIVE_HASH} " )
139
108
if (_MATCH)
140
- set (_VERSION_STRING "${CMAKE_MATCH_1} " )
141
- set (_VERSION_STRING_SUFFIX "${CMAKE_MATCH_2} " )
109
+ _cgv_store_version("" "" "${CMAKE_MATCH_1} " )
110
+ endif ()
111
+ endif ()
112
+ endfunction ()
113
+
114
+ #-----------------------------------------------------------------------------#
115
+
116
+ function (_cgv_try_git_describe)
117
+ # First time calling "git describe"
118
+ if (NOT Git_FOUND)
119
+ find_package (Git QUIET )
120
+ if (NOT Git_FOUND)
121
+ message (WARNING "Could not find Git, needed to find the version tag" )
122
+ return ()
123
+ endif ()
124
+ endif ()
125
+
126
+ # Load git description
127
+ execute_process (
128
+ COMMAND "${GIT_EXECUTABLE} " "describe" "--tags" "--match" "v*"
129
+ WORKING_DIRECTORY "${CMAKE_CURRENT_LIST_DIR} "
130
+ ERROR_VARIABLE _GIT_ERR
131
+ OUTPUT_VARIABLE _VERSION_STRING
132
+ RESULT_VARIABLE _GIT_RESULT
133
+ OUTPUT_STRIP_TRAILING_WHITESPACE
134
+ )
135
+ if (_GIT_RESULT)
136
+ message (WARNING "No git tags in ${CGV_PROJECT} matched 'v*': "
137
+ "${_GIT_ERR} " )
138
+ return ()
139
+ elseif (NOT _VERSION_STRING)
140
+ message (WARNING "Failed to get ${CGV_PROJECT} version from git: "
141
+ "git describe returned an empty string" )
142
+ return ()
143
+ endif ()
144
+
145
+ # Process description tag: e.g. v0.4.0-2-gc4af497 or v0.4.0
146
+ # or v2.0.0-dev2
147
+ set (_DESCR_REGEX "^${CGV_TAG_REGEX} (-([0-9]+)-g([0-9a-f]+))?" )
148
+ string (REGEX MATCH "${_DESCR_REGEX} " _MATCH "${_VERSION_STRING} " )
149
+ if (NOT _MATCH)
150
+ message (WARNING "Failed to parse description '${_VERSION_STRING} ' "
151
+ "with regex '${_DESCR_REGEX} '"
152
+ )
153
+ return ()
154
+ endif ()
155
+
156
+ if (NOT CMAKE_MATCH_3)
157
+ # This is a tagged release!
158
+ _cgv_store_version("${CMAKE_MATCH_1} " "${CMAKE_MATCH_2} " "" )
159
+ else ()
160
+ if (CMAKE_MATCH_2)
161
+ set (_suffix ${CMAKE_MATCH_2} .${CMAKE_MATCH_4} )
142
162
else ()
143
- message (AUTHOR_WARNING "Could not match a version tag for "
144
- "git description '${_ARCHIVE_TAG} ': perhaps this archive was not "
145
- "exported from a tagged commit?" )
146
- string (REGEX MATCH " *${_HASH_REGEX} " _MATCH "${_ARCHIVE_HASH} " )
147
- if (_MATCH)
148
- set (_VERSION_HASH "${CMAKE_MATCH_1} " )
163
+ set (_suffix -${CMAKE_MATCH_4} )
164
+ endif ()
165
+ # Qualify the version number and save the hash
166
+ _cgv_store_version(
167
+ "${CMAKE_MATCH_1} " # [0-9.]+
168
+ "${_suffix} " # (-dev[0-9.]*)? \. ([0-9]+)
169
+ "${CMAKE_MATCH_5} " ([0-9a-f]+)
170
+ )
171
+ endif ()
172
+ endfunction ()
173
+
174
+ #-----------------------------------------------------------------------------#
175
+
176
+ function (_cgv_try_git_hash)
177
+ if (NOT GIT_EXECUTABLE)
178
+ return ()
179
+ endif ()
180
+ # Fall back to just getting the hash
181
+ execute_process (
182
+ COMMAND "${GIT_EXECUTABLE} " "log" "-1" "--format=%h" "HEAD"
183
+ WORKING_DIRECTORY "${CMAKE_CURRENT_LIST_DIR} "
184
+ OUTPUT_VARIABLE _VERSION_HASH
185
+ RESULT_VARIABLE _GIT_RESULT
186
+ OUTPUT_STRIP_TRAILING_WHITESPACE
187
+ )
188
+ if (_GIT_RESULT)
189
+ message (WARNING "Failed to get current commit hash from git: "
190
+ "${_GIT_ERR} " )
191
+ return ()
192
+ endif ()
193
+ _cgv_store_version("" "" "${_VERSION_HASH} " )
194
+ endfunction ()
195
+
196
+ #-----------------------------------------------------------------------------#
197
+
198
+ function (cgv_find_version)
199
+ # Set CGV_ variables that are used in embedded macros/functions
200
+ if (ARGC GREATER 0)
201
+ set (CGV_PROJECT "${ARGV0} " )
202
+ elseif (NOT CGV_PROJECT)
203
+ if (NOT CMAKE_PROJECT_NAME )
204
+ message (FATAL_ERROR "Project name is not defined" )
205
+ endif ()
206
+ set (CGV_PROJECT "${CMAKE_PROJECT_NAME} " )
207
+ endif ()
208
+
209
+ if (NOT CGV_TAG_REGEX)
210
+ set (CGV_TAG_REGEX "v([0-9.]+)(-[a-z]+[0-9.]*)?" )
211
+ endif ()
212
+
213
+ set (CGV_CACHE_VAR "${CGV_PROJECT} _GIT_DESCRIBE" )
214
+
215
+ # Successively try archive metadata, git description, or just git hash
216
+ if (NOT ${CGV_CACHE_VAR} )
217
+ _cgv_try_archive_md()
218
+ if (NOT ${CGV_CACHE_VAR} )
219
+ _cgv_try_git_describe()
220
+ if (NOT ${CGV_CACHE_VAR} )
221
+ _cgv_try_git_hash()
222
+ if (NOT ${CGV_CACHE_VAR} )
223
+ set (${CGV_CACHE_VAR} "" "-unknown" "" )
224
+ endif ()
149
225
endif ()
150
226
endif ()
151
227
endif ()
152
228
229
+ # Unpack stored version
230
+ set (_CACHED_VERSION "${${CGV_CACHE_VAR} }" )
231
+ list (GET _CACHED_VERSION 0 _VERSION_STRING)
232
+ list (GET _CACHED_VERSION 1 _VERSION_STRING_SUFFIX)
233
+ list (GET _CACHED_VERSION 2 _VERSION_HASH)
234
+
153
235
if (NOT _VERSION_STRING)
154
236
set (_VERSION_STRING "0.0.0" )
155
237
endif ()
156
238
157
239
if (_VERSION_HASH)
158
- set (_FULL_VERSION_STRING "v ${_VERSION_STRING}${_VERSION_STRING_SUFFIX} +${_VERSION_HASH} " )
240
+ set (_FULL_VERSION_STRING "${_VERSION_STRING}${_VERSION_STRING_SUFFIX} +${_VERSION_HASH} " )
159
241
else ()
160
- set (_FULL_VERSION_STRING "v ${_VERSION_STRING}${_VERSION_STRING_SUFFIX} " )
242
+ set (_FULL_VERSION_STRING "${_VERSION_STRING}${_VERSION_STRING_SUFFIX} " )
161
243
endif ()
162
244
163
- set (${projname} _VERSION "${_VERSION_STRING} " PARENT_SCOPE)
164
- set (${projname} _VERSION_STRING "${_FULL_VERSION_STRING} " PARENT_SCOPE)
245
+ # Set version number and descriptive version in parent scope
246
+ set (${CGV_PROJECT} _VERSION "${_VERSION_STRING} " PARENT_SCOPE)
247
+ set (${CGV_PROJECT} _VERSION_STRING "${_FULL_VERSION_STRING} " PARENT_SCOPE)
165
248
endfunction ()
166
249
250
+ #-----------------------------------------------------------------------------#
251
+
167
252
if (CMAKE_SCRIPT_MODE_FILE )
168
253
cgv_find_version(TEMP)
169
- message ("VERSION=\" ${TEMP_VERSION} \" " )
170
- message ("VERSION_STRING=\" ${TEMP_VERSION_STRING} \" " )
254
+ if (DEFINED ONLY)
255
+ # Print only the given variable, presumably VERSION or VERSION_STRING
256
+ # (will print to stderr)
257
+ set (VERSION "${TEMP_VERSION} " )
258
+ set (VERSION_STRING "${TEMP_VERSION_STRING} " )
259
+ message ("${${ONLY} }" )
260
+ else ()
261
+ message ("VERSION=\" ${TEMP_VERSION} \" " )
262
+ message ("VERSION_STRING=\" ${TEMP_VERSION_STRING} \" " )
263
+ endif ()
171
264
endif ()
265
+
266
+ # cmake-git-version 1.1.1
0 commit comments