forked from jrl-umi3218/jrl-cmakemodules
-
Notifications
You must be signed in to change notification settings - Fork 0
/
version.cmake
218 lines (201 loc) · 8.57 KB
/
version.cmake
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
# Copyright (C) 2008-2019 LAAS-CNRS, JRL AIST-CNRS, INRIA.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#.rst:
# .. command:: VERSION_COMPUTE
#
# Deduce automatically the version number.
# This mechanism makes sure that version number is always up-to-date and
# coherent (i.e. strictly increasing as commits are made).
#
# There is three cases:
#
# - the software comes from a release (stable version). In this case, the
# software is retrieved through a tarball which does not contain the ``.git``
# directory. Hence, there is no way to search in the Git history to generate
# the version number.
# In this case, a ``.version`` file is put at the top-directory of the source
# tree which contains the project version. Read the file to retrieve the
# version number.
#
# - the softwares comes from git (possibly unstable version).
# ``git describe`` is used to retrieve the version number
# (see 'man git-describe'). This tool generates a version number from the git
# history. The version number follows this pattern:
#
# ``TAG[-N-SHA1][-dirty]``
#
# - ``TAG``: last matching tag (i.e. last signed tag starting with v, i.e. v0.1)
# - ``N``: number of commits since the last maching tag
# - ``SHA1``: sha1 of the current commit
# - ``-dirty``: added if the workig directory is dirty (there is some uncommitted
# changes).
#
# For stable releases, i.e. the current commit is a matching tag, ``-N-SHA1`` is
# omitted. If the HEAD is on the signed tag v0.1, the version number will be
# 0.1.
#
# If the HEAD is two commits after v0.5 and the last commit is 034f6d...
# The version number will be:
#
# - ``0.5-2-034f`` if there is no uncommitted changes,
# - ``0.5-2-034f-dirty`` if there is some uncommitted changes.
#
# - the software comes with a package.xml file at the root of the project (for ROS build essentially)
# then the module extracts the version number which is declared inside between the tag <version>x.y.z<\version>
#
MACRO(VERSION_COMPUTE)
SET(PROJECT_STABLE False)
IF("${PROJECT_SOURCE_DIR}" STREQUAL "")
SET(PROJECT_SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/..")
ENDIF()
# Check if a version is embedded in the project.
IF(EXISTS ${PROJECT_SOURCE_DIR}/.version)
# Yes, use it. This is a stable version.
FILE(STRINGS .version PROJECT_VERSION)
SET(PROJECT_STABLE TRUE)
ELSE(EXISTS ${PROJECT_SOURCE_DIR}/.version)
# No, there is no '.version' file. Deduce the version from git.
# Search for git.
FIND_PROGRAM(GIT git)
IF(NOT GIT)
MESSAGE("Warning: failed to compute the version number, git not found.")
SET(PROJECT_VERSION UNKNOWN)
ENDIF()
# Check whether the repository is shallow or not
EXECUTE_PROCESS(COMMAND ${GIT} rev-parse --git-dir
OUTPUT_VARIABLE GIT_PROJECT_DIR
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
OUTPUT_STRIP_TRAILING_WHITESPACE)
SET(GIT_PROJECT_DIR "${PROJECT_SOURCE_DIR}/${GIT_PROJECT_DIR}")
IF(IS_DIRECTORY "${GIT_PROJECT_DIR}/shallow")
SET(IS_SHALLOW TRUE)
ELSE(IS_DIRECTORY "${GIT_PROJECT_DIR}/shallow")
SET(IS_SHALLOW FALSE)
ENDIF(IS_DIRECTORY "${GIT_PROJECT_DIR}/shallow")
IF(IS_SHALLOW)
#EXECUTE_PROCESS(COMMAND ${GIT} fetch --unshallow)
MESSAGE(WARNING "It appears that your git repository is a shallow copy, meaning that the history has been truncated\n.
Please consider updating your git repository with `git fetch --unshallow` in order to download the full history with tags to recover the current release version.")
ENDIF(IS_SHALLOW)
# Run describe: search for *signed* tags starting with v, from the HEAD and
# display only the first four characters of the commit id.
EXECUTE_PROCESS(
COMMAND ${GIT} describe --tags --abbrev=4 --match=v* HEAD
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
RESULT_VARIABLE GIT_DESCRIBE_RESULT
OUTPUT_VARIABLE GIT_DESCRIBE_OUTPUT
ERROR_VARIABLE GIT_DESCRIBE_ERROR
OUTPUT_STRIP_TRAILING_WHITESPACE
)
# Run diff-index to check whether the tree is clean or not.
EXECUTE_PROCESS(
COMMAND ${GIT} diff-index --name-only HEAD
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
RESULT_VARIABLE GIT_DIFF_INDEX_RESULT
OUTPUT_VARIABLE GIT_DIFF_INDEX_OUTPUT
ERROR_VARIABLE GIT_DIFF_INDEX_ERROR
OUTPUT_STRIP_TRAILING_WHITESPACE
)
# Check if the tree is clean.
IF(GIT_DIFF_INDEX_RESULT OR GIT_DIFF_INDEX_OUTPUT)
SET(PROJECT_DIRTY TRUE)
ENDIF()
# Check if git describe worked and store the returned version number.
IF(GIT_DESCRIBE_RESULT)
MESSAGE(AUTHOR_WARNING
"Warning: failed to compute the version number,"
" 'git describe' failed:\n"
"\t" ${GIT_DESCRIBE_ERROR})
SET(PROJECT_VERSION UNKNOWN)
ELSE()
# Get rid of the tag prefix to generate the final version.
STRING(REGEX REPLACE "^v" "" PROJECT_VERSION "${GIT_DESCRIBE_OUTPUT}")
IF(NOT PROJECT_VERSION)
MESSAGE(AUTHOR_WARNING
"Warning: failed to compute the version number,"
"'git describe' returned an empty string.")
SET(PROJECT_VERSION UNKNOWN)
ENDIF()
# If there is a dash in the version number, it is an unstable release,
# otherwise it is a stable release.
# I.e. 1.0, 2, 0.1.3 are stable but 0.2.4-1-dg43 is unstable.
STRING(REGEX MATCH "-" PROJECT_STABLE "${PROJECT_VERSION}")
IF(NOT PROJECT_STABLE STREQUAL -)
SET(PROJECT_STABLE TRUE)
ELSE()
SET(PROJECT_STABLE FALSE)
ENDIF()
ENDIF()
IF(GIT_DESCRIBE_RESULT) # git has failed to retrieve the project version
# Check if a package.xml file exists and try to extract the version from it
IF(EXISTS ${PROJECT_SOURCE_DIR}/package.xml)
FILE(READ "${PROJECT_SOURCE_DIR}/package.xml" PACKAGE_XML)
MESSAGE(STATUS "PACKAGE_XML: ${PACKAGE_XML}")
EXECUTE_PROCESS(COMMAND cat "${PROJECT_SOURCE_DIR}/package.xml"
COMMAND grep <version
COMMAND cut -f2 -d >
COMMAND cut -f1 -d <
OUTPUT_STRIP_TRAILING_WHITESPACE
#COMMAND_ECHO STDOUT
OUTPUT_VARIABLE PACKAGE_XML_VERSION)
MESSAGE(STATUS "CMAKE: ${PACKAGE_XML_VERSION}")
IF(NOT "${PACKAGE_XML_VERSION}" STREQUAL "")
SET(PROJECT_VERSION ${PACKAGE_XML_VERSION})
ENDIF(NOT "${PACKAGE_XML_VERSION}" STREQUAL "")
ENDIF(EXISTS ${PROJECT_SOURCE_DIR}/package.xml)
ENDIF(GIT_DESCRIBE_RESULT)
# Append dirty if the project is dirty.
IF(DEFINED PROJECT_DIRTY)
SET(PROJECT_VERSION "${PROJECT_VERSION}-dirty")
ENDIF()
ENDIF(EXISTS ${PROJECT_SOURCE_DIR}/.version)
# Set PROJECT_VERSION_{MAJOR,MINOR,PATCH} variables
IF(PROJECT_VERSION)
# Compute the major, minor and patch version of the project
IF(NOT DEFINED PROJECT_VERSION_MAJOR AND
NOT DEFINED PROJECT_VERSION_MINOR AND
NOT DEFINED PROJECT_VERSION_PATCH)
SPLIT_VERSION_NUMBER(${PROJECT_VERSION}
PROJECT_VERSION_MAJOR
PROJECT_VERSION_MINOR
PROJECT_VERSION_PATCH)
ENDIF()
ENDIF()
ENDMACRO()
MACRO(SPLIT_VERSION_NUMBER VERSION
VERSION_MAJOR_VAR
VERSION_MINOR_VAR
VERSION_PATCH_VAR)
# Compute the major, minor and patch version of the project
IF(${VERSION} MATCHES UNKNOWN)
SET(${VERSION_MAJOR_VAR} UNKNOWN)
SET(${VERSION_MINOR_VAR} UNKNOWN)
SET(${VERSION_PATCH_VAR} UNKNOWN)
ELSE()
# Extract the version from PROJECT_VERSION
string(REPLACE "." ";" _PROJECT_VERSION_LIST "${VERSION}")
list(LENGTH _PROJECT_VERSION_LIST SIZE)
IF(${SIZE} GREATER 0)
list(GET _PROJECT_VERSION_LIST 0 ${VERSION_MAJOR_VAR})
ENDIF()
IF(${SIZE} GREATER 1)
list(GET _PROJECT_VERSION_LIST 1 ${VERSION_MINOR_VAR})
ENDIF()
IF(${SIZE} GREATER 2)
string(REPLACE "-" ";" _PROJECT_VERSION_LIST "${_PROJECT_VERSION_LIST}")
list(GET _PROJECT_VERSION_LIST 2 ${VERSION_PATCH_VAR})
ENDIF()
ENDIF()
ENDMACRO()