1# CMake-GitVersion. 2# (Yet another) automatic version generation for C++ CMake projects. 3 4# * Generates version information using information from git (tags) with fallback options 5# when building without git (e.g. when building from sources with exported archives). 6# * Use custom templates for generated sources (e.g. also create resource files (see examples)) 7# * Uses semantic versioning (https://semver.org/) 8# * Best suited with git-flow workflows 9# * See: https://www.atlassian.com/de/git/tutorials/comparing-workflows/gitflow-workflow 10# * See: https://nvie.com/posts/a-successful-git-branching-model/ 11# * Generated version strings are compatible to/and can be used by debian and rpm packages. 12 13# ## Version Generation 14 15# Defines 16# - `LAST_TAG_VERSION`: latest tagged version (e.g. 1.2.0 for tag v1.2.0) or 0.0.0 if no tag exists. 17# - `DIST`: commit count distance to latest version tag. 18 19# Version Number rules: 20# - on _master_: `X.Y.Z`[-`DIST`] (using `LAST_TAG_VERSION`), while `DIST` should always be 0 on the master branch. 21# - on _develop_ and other branches: `X.Y.Z`-`ALPHA_FLAG`.`DIST` (using `LAST_TAG_VERSION`, `Y` incremented by 1) 22# - on release branches: `X.Y.Z`-`RC_FLAG`.`DIST` (extracting `X.Y.Z` from release branch name or from _develop_ as fallback). \ 23# `DIST` is either calculated to last version tag or to the closest `rc-X.Y.Z` tag. 24# - `DIST` is added to all version numbers, except: 25# - Versions on _master_ and on _hotfix_ branches with `DIST` equal to 0 26# - All version numbers have a pre-release identifier set, except: 27# - Version on _master_ and 28# - versions on _hotfix_ branches with `DIST` equal to 0 29# - When creating the version string and the PATCH number is 0 - the patch number is omitted. 30# (e.g. 1.2.0 will be 1.2) 31 32### Configuration - this may be adjusted to the personal and project requirements 33set(VERSION_TAG_PREFIX v) # Should be the same as configured in git-flow 34set(VERSION_ALPHA_FLAG alpha) # Pre-release identifier for all builds besides release and hotfix branches 35set(VERSION_RC_FLAG rc) # Pre-release identifier for all builds from release and hotfix branches 36set(VERSION_RC_START_TAG_PREFIX "rc-") # If available tags with the given prefix are used for distance calculation on release branches. 37set(RC_BRANCH_PREFIX release) # e.g. release/0.2 38set(HOTFIX_BRANCH_PREFIX hotfix) # e.g. hotfix/2.0.3 39 40# Let functions in this module know their own directory 41set(_GitVersion_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}") 42 43# -------------------------------------------------------------------------------------------------- 44# Helper method - usually never called directly: 45# Get the version information for a directory, sets the following variables 46# ${prefix}_VERSION_SUCCESS // 0 on error (e.g. git not found), 1 on success 47# ${prefix}_VERSION_MAJOR 48# ${prefix}_VERSION_MINOR 49# ${prefix}_VERSION_PATCH 50# ${prefix}_VERSION_FLAG 51# ${prefix}_VERSION_DISTANCE 52# ${prefix}_VERSION_SHORTHASH 53# ${prefix}_VERSION_FULLHASH 54# ${prefix}_VERSION_ISDIRTY // 0 or 1 if tree has local modifications 55# ${prefix}_VERSION_STRING // Full version string, e.g. 1.2.3-rc.239 56# 57# A created version number can be overruled if the following variables are set and the version number is GREATER 58# than the dynamically created one. 59# - ${prefix}_CUSTOM_VERSION_MAJOR 60# - ${prefix}_CUSTOM_VERSION_MINOR 61# - ${prefix}_CUSTOM_VERSION_PATCH 62# 63# A version 'type' (release or develop) in case the branch cannot be determined via git 64# - #{prefix}_FALLBACK_VERSION_TYPE 65# 66# The environment variable FALLBACK_BRANCH will be used if the branch cannot be determined 67function(get_version_info prefix directory) 68 set(${prefix}_VERSION_SUCCESS 0 PARENT_SCOPE) 69 set(${prefix}_VERSION_MAJOR 0) 70 set(${prefix}_VERSION_MINOR 0) 71 set(${prefix}_VERSION_PATCH 0) 72 set(${prefix}_VERSION_BRANCH unknown) 73 set(${prefix}_VERSION_FLAG unknown) 74 set(${prefix}_VERSION_DISTANCE 0) 75 set(${prefix}_VERSION_STRING 0.0.0-unknown) 76 set(${prefix}_VERSION_ISDIRTY 0 PARENT_SCOPE) 77 78 if("${${prefix}_CUSTOM_VERSION_MAJOR}" STREQUAL "") 79 set(${prefix}_CUSTOM_VERSION_MAJOR 0) 80 endif() 81 if("${${prefix}_CUSTOM_VERSION_MINOR}" STREQUAL "") 82 set(${prefix}_CUSTOM_VERSION_MINOR 0) 83 endif() 84 if("${${prefix}_CUSTOM_VERSION_PATCH}" STREQUAL "") 85 set(${prefix}_CUSTOM_VERSION_PATCH 0) 86 endif() 87 88 find_package(Git) 89 if(GIT_FOUND) 90 # Get the version info from the last tag (using the configured version tag prefix) 91 execute_process(COMMAND ${GIT_EXECUTABLE} describe --tags --match "${VERSION_TAG_PREFIX}[0-9].[0-9]*" 92 RESULT_VARIABLE result 93 OUTPUT_VARIABLE GIT_TAG_VERSION 94 ERROR_VARIABLE error_out 95 OUTPUT_STRIP_TRAILING_WHITESPACE 96 WORKING_DIRECTORY ${directory} 97 ) 98 if(result EQUAL 0) 99 # Extract version major, minor, patch from the result 100 if(GIT_TAG_VERSION MATCHES "^${VERSION_TAG_PREFIX}?([0-9]+)\\.([0-9]+)(\\.([0-9]+))?(-([0-9]+))?.*$") 101 set(${prefix}_VERSION_MAJOR ${CMAKE_MATCH_1}) 102 set(${prefix}_VERSION_MINOR ${CMAKE_MATCH_2}) 103 if(NOT ${CMAKE_MATCH_4} STREQUAL "") 104 set(${prefix}_VERSION_PATCH ${CMAKE_MATCH_4}) 105 endif() 106 if(NOT ${CMAKE_MATCH_6} STREQUAL "") 107 set(${prefix}_VERSION_DISTANCE ${CMAKE_MATCH_6}) 108 endif() 109 endif() 110 else() 111 # git describe return with error - just get the distance 112 execute_process(COMMAND ${GIT_EXECUTABLE} rev-list --count HEAD 113 RESULT_VARIABLE result 114 OUTPUT_VARIABLE GIT_DISTANCE 115 OUTPUT_STRIP_TRAILING_WHITESPACE 116 ERROR_VARIABLE error_out 117 WORKING_DIRECTORY ${directory} 118 ) 119 if(result EQUAL 0) 120 set(${prefix}_VERSION_DISTANCE ${GIT_DISTANCE}) 121 endif() 122 endif() 123 124 # Check for local modifications ... 125 execute_process(COMMAND ${GIT_EXECUTABLE} describe --always --dirty 126 RESULT_VARIABLE result 127 OUTPUT_VARIABLE GIT_ALWAYS_VERSION 128 OUTPUT_STRIP_TRAILING_WHITESPACE 129 ERROR_VARIABLE error_out 130 WORKING_DIRECTORY ${directory} 131 ) 132 if(result EQUAL 0) 133 if(GIT_ALWAYS_VERSION MATCHES "^.*-dirty$") 134 set(${prefix}_VERSION_ISDIRTY 1 PARENT_SCOPE) 135 endif() 136 endif() 137 138 # Check the branch we are on 139 execute_process(COMMAND ${GIT_EXECUTABLE} rev-parse --abbrev-ref HEAD 140 RESULT_VARIABLE result 141 OUTPUT_VARIABLE GIT_BRANCH 142 OUTPUT_STRIP_TRAILING_WHITESPACE 143 ERROR_VARIABLE error_out 144 WORKING_DIRECTORY ${directory} 145 ) 146 147 if(result EQUAL 0) 148 if("${GIT_BRANCH}" STREQUAL "HEAD" 149 AND NOT "$ENV{FALLBACK_BRANCH}" STREQUAL "") 150 set(GIT_BRANCH "$ENV{FALLBACK_BRANCH}") 151 endif() 152 153 set(${prefix}_VERSION_BRANCH "${GIT_BRANCH}") 154 set(${prefix}_VERSION_BRANCH "${GIT_BRANCH}" PARENT_SCOPE) 155 156 # Check for release branch 157 string(LENGTH ${RC_BRANCH_PREFIX} PREFIX_LEN) 158 string(SUBSTRING ${GIT_BRANCH} 0 ${PREFIX_LEN} COMPARE_PREFIX) 159 string(COMPARE EQUAL ${RC_BRANCH_PREFIX} ${COMPARE_PREFIX} ON_RELEASE_BRANCH) 160 # Check for hotfix branch 161 string(LENGTH ${HOTFIX_BRANCH_PREFIX} PREFIX_LEN) 162 string(SUBSTRING ${GIT_BRANCH} 0 ${PREFIX_LEN} COMPARE_PREFIX) 163 string(COMPARE EQUAL ${HOTFIX_BRANCH_PREFIX} ${COMPARE_PREFIX} ON_HOTFIX_BRANCH) 164 # Check for master branch 165 string(COMPARE EQUAL "master" ${GIT_BRANCH} ON_MASTER) 166 167 if(ON_RELEASE_BRANCH) 168 set(${prefix}_VERSION_FLAG ${VERSION_RC_FLAG}) 169 set(RC_VERSION_MAJOR 0) 170 set(RC_VERSION_MINOR 0) 171 set(RC_VERSION_PATCH 0) 172 # Check release branch name for version information (e.g. release/0.8) 173 if(GIT_BRANCH MATCHES "^${RC_BRANCH_PREFIX}.*([0-9]+)\\.([0-9]+)(\\.([0-9]+))?.*$") 174 set(RC_VERSION_MAJOR ${CMAKE_MATCH_1}) 175 set(RC_VERSION_MINOR ${CMAKE_MATCH_2}) 176 if(NOT ${CMAKE_MATCH_4} STREQUAL "") 177 set(RC_VERSION_PATCH ${CMAKE_MATCH_4}) 178 endif() 179 endif() 180 181 # If the release branch version is greater, use that version... 182 if("${RC_VERSION_MAJOR}.${RC_VERSION_MINOR}.${RC_VERSION_PATCH}" VERSION_GREATER 183 "${${prefix}_VERSION_MAJOR}.${${prefix}_VERSION_MINOR}.${${prefix}_VERSION_PATCH}") 184 set(${prefix}_VERSION_MAJOR ${RC_VERSION_MAJOR}) 185 set(${prefix}_VERSION_MINOR ${RC_VERSION_MINOR}) 186 set(${prefix}_VERSION_PATCH ${RC_VERSION_PATCH}) 187 else() # ... else auto increment the version minor number 188 # Auto increment minor number, patch = 0 189 MATH(EXPR ${prefix}_VERSION_MINOR "${${prefix}_VERSION_MINOR}+1") 190 set(${prefix}_VERSION_PATCH 0) 191 endif() 192 193 # Try to get distance from last rc start tag 194 execute_process(COMMAND ${GIT_EXECUTABLE} describe --tags --match "${VERSION_RC_START_TAG_PREFIX}[0-9].[0-9]*" 195 RESULT_VARIABLE result 196 OUTPUT_VARIABLE GIT_RC_TAG_VERSION 197 ERROR_VARIABLE error_out 198 OUTPUT_STRIP_TRAILING_WHITESPACE 199 WORKING_DIRECTORY ${directory} 200 ) 201 if(result EQUAL 0) 202 if(GIT_RC_TAG_VERSION MATCHES "^${VERSION_RC_START_TAG_PREFIX}?([0-9]+)\\.([0-9]+)(\\.([0-9]+))?(-([0-9]+))?.*$") 203 if(NOT ${CMAKE_MATCH_6} STREQUAL "") 204 set(${prefix}_VERSION_DISTANCE ${CMAKE_MATCH_6}) 205 else() 206 set(${prefix}_VERSION_DISTANCE 0) 207 endif() 208 endif() 209 endif() 210 211 elseif(ON_HOTFIX_BRANCH) 212 set(${prefix}_VERSION_FLAG ${VERSION_RC_FLAG}) 213 set(RC_VERSION_MAJOR 0) 214 set(RC_VERSION_MINOR 0) 215 set(RC_VERSION_PATCH 0) 216 if(GIT_BRANCH MATCHES "^${RC_BRANCH_PREFIX}.*([0-9]+)\\.([0-9]+)(\\.([0-9]+))?.*$") 217 set(RC_VERSION_MAJOR ${CMAKE_MATCH_1}) 218 set(RC_VERSION_MINOR ${CMAKE_MATCH_2}) 219 if(NOT ${CMAKE_MATCH_4} STREQUAL "") 220 set(RC_VERSION_PATCH ${CMAKE_MATCH_4}) 221 endif() 222 endif() 223 224 if("${RC_VERSION_MAJOR}.${RC_VERSION_MINOR}.${RC_VERSION_PATCH}" VERSION_GREATER 225 "${${prefix}_VERSION_MAJOR}.${${prefix}_VERSION_MINOR}.${${prefix}_VERSION_PATCH}") 226 set(${prefix}_VERSION_MAJOR ${RC_VERSION_MAJOR}) 227 set(${prefix}_VERSION_MINOR ${RC_VERSION_MINOR}) 228 set(${prefix}_VERSION_PATCH ${RC_VERSION_PATCH}) 229 else() 230 # Auto increment patch number 231 MATH(EXPR ${prefix}_VERSION_PATCH "${${prefix}_VERSION_PATCH}+1") 232 endif() 233 elseif(ON_MASTER) 234 set(${prefix}_VERSION_FLAG "") 235 endif() 236 endif() 237 238 if(NOT ON_MASTER AND NOT ON_RELEASE_BRANCH AND NOT ON_HOTFIX_BRANCH) 239 # Auto increment version number, set alpha flag 240 MATH(EXPR ${prefix}_VERSION_MINOR "${${prefix}_VERSION_MINOR}+1") 241 set(${prefix}_VERSION_PATCH 0) 242 set(${prefix}_VERSION_FLAG ${VERSION_ALPHA_FLAG}) 243 endif() 244 245 set(${prefix}_VERSION_FLAG ${${prefix}_VERSION_FLAG} PARENT_SCOPE) 246 set(${prefix}_VERSION_DISTANCE ${${prefix}_VERSION_DISTANCE} PARENT_SCOPE) 247 248 execute_process(COMMAND ${GIT_EXECUTABLE} rev-parse --short HEAD 249 RESULT_VARIABLE resultSH 250 OUTPUT_VARIABLE GIT_SHORT_HASH 251 OUTPUT_STRIP_TRAILING_WHITESPACE 252 ERROR_VARIABLE error_out 253 WORKING_DIRECTORY ${directory} 254 ) 255 if(resultSH EQUAL 0) 256 set(${prefix}_VERSION_SHORTHASH ${GIT_SHORT_HASH} PARENT_SCOPE) 257 else() 258 message(STATUS "Version-Info: Could not fetch short version hash.") 259 set(${prefix}_VERSION_SHORTHASH "unknown" PARENT_SCOPE) 260 endif() 261 262 execute_process(COMMAND ${GIT_EXECUTABLE} rev-parse HEAD 263 RESULT_VARIABLE resultFH 264 OUTPUT_VARIABLE GIT_FULL_HASH 265 OUTPUT_STRIP_TRAILING_WHITESPACE 266 ERROR_VARIABLE error_out 267 WORKING_DIRECTORY ${directory} 268 ) 269 if(resultFH EQUAL 0) 270 set(${prefix}_VERSION_FULLHASH ${GIT_FULL_HASH} PARENT_SCOPE) 271 else() 272 message(STATUS "Version-Info: Could not fetch full version hash.") 273 set(${prefix}_VERSION_FULLHASH "unknown" PARENT_SCOPE) 274 endif() 275 276 if(resultSH EQUAL 0 AND resultFH EQUAL 0) 277 set(${prefix}_VERSION_SUCCESS 1 PARENT_SCOPE) 278 endif() 279 else() # Git not found ... 280 message(STATUS "Version-Info: Git not found. Possible incomplete version information.") 281 endif() 282 283 if("${${prefix}_VERSION_BRANCH}" STREQUAL "unknown" OR "${${prefix}_VERSION_BRANCH}" STREQUAL "") 284 if("${${prefix}_FALLBACK_VERSION_TYPE}" STREQUAL "release") 285 set(ON_MASTER ON) 286 set(${prefix}_VERSION_FLAG "") 287 set(${prefix}_VERSION_FLAG "" PARENT_SCOPE) 288 endif() 289 set(${prefix}_VERSION_BRANCH "not-within-git-repo" PARENT_SCOPE) 290 endif() 291 292 # Check if overrule version is greater than dynamically created one 293 if("${${prefix}_CUSTOM_VERSION_MAJOR}.${${prefix}_CUSTOM_VERSION_MINOR}.${${prefix}_CUSTOM_VERSION_PATCH}" VERSION_GREATER 294 "${${prefix}_VERSION_MAJOR}.${${prefix}_VERSION_MINOR}.${${prefix}_VERSION_PATCH}") 295 set(${prefix}_VERSION_MAJOR ${${prefix}_CUSTOM_VERSION_MAJOR}) 296 set(${prefix}_VERSION_MINOR ${${prefix}_CUSTOM_VERSION_MINOR}) 297 set(${prefix}_VERSION_PATCH ${${prefix}_CUSTOM_VERSION_PATCH}) 298 endif() 299 300 set(${prefix}_VERSION_MAJOR ${${prefix}_VERSION_MAJOR} PARENT_SCOPE) 301 set(${prefix}_VERSION_MINOR ${${prefix}_VERSION_MINOR} PARENT_SCOPE) 302 set(${prefix}_VERSION_PATCH ${${prefix}_VERSION_PATCH} PARENT_SCOPE) 303 set(${prefix}_VERSION_DISTANCE ${${prefix}_VERSION_DISTANCE} PARENT_SCOPE) 304 305 # Build version string... 306 set(VERSION_STRING "${${prefix}_VERSION_MAJOR}.${${prefix}_VERSION_MINOR}") 307 if(NOT ${${prefix}_VERSION_PATCH} EQUAL 0) 308 set(VERSION_STRING "${VERSION_STRING}.${${prefix}_VERSION_PATCH}") 309 endif() 310 if(NOT ON_MASTER OR NOT ${${prefix}_VERSION_DISTANCE} EQUAL 0) 311 set(VERSION_STRING "${VERSION_STRING}-${${prefix}_VERSION_FLAG}") 312 endif() 313 if(NOT ${${prefix}_VERSION_FLAG} STREQUAL "") 314 set(VERSION_STRING "${VERSION_STRING}.") 315 endif() 316 if(NOT ON_MASTER OR (NOT ON_MASTER AND NOT ${${prefix}_VERSION_DISTANCE} EQUAL 0)) 317 set(VERSION_STRING "${VERSION_STRING}${${prefix}_VERSION_DISTANCE}") 318 endif() 319 set(${prefix}_VERSION_STRING "${VERSION_STRING}" PARENT_SCOPE) 320endfunction() 321 322# -------------------------------------------------------------------------------------------------- 323# Add version information to a target, header and source file are configured from templates. 324# (defaults to GitVersion.h.in and GitVersion.cc.in if no other templates are defined) 325# Variables available to input templates 326# @PREFIX@ = target prefix name given in the function call, must be a valid C-identifier 327# @VERSION_MAJOR@, @VERSION_MINOR@, @VERSION_PATCH@, @VERSION_FLAG@, @VERSION_DISTANCE@ 328# @VERSION_SHORTHASH@, @VERSION_FULLHASH@, @VERSION_STRING@, @VERSION_ISDIRTY, @VERSION_BRANCH@ 329function(add_version_info) 330 set(oneValueArgs 331 TARGET # The build target 332 PREFIX # The prefix/name for templates, must be a valid C identifier 333 DIRECTORY # Directory from which to get the git version info 334 ) 335 set(multiValueArgs TEMPLATES) # Templates that are configured and added to the target 336 set(requiredArgs TARGET) 337 cmake_parse_arguments(VI "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) 338 339 foreach(arg IN LISTS requiredArgs) 340 if("${VI_${arg}}" STREQUAL "") 341 message(FATAL_ERROR "Required argument '${arg}' is not set.") 342 endif() 343 endforeach() 344 345 if(NOT TARGET ${VI_TARGET}) 346 message(FATAL_ERROR "Argument 'TARGET' needs to be a valid target.") 347 endif() 348 349 list(LENGTH VI_TEMPLATES NUM_TEMPLATES) 350 if(NUM_TEMPLATES EQUAL 0) 351 # Add default templates 352 list(APPEND VI_TEMPLATES "${_GitVersion_DIRECTORY}/GitVersion.h.in") 353 list(APPEND VI_TEMPLATES "${_GitVersion_DIRECTORY}/GitVersion.cc.in") 354 endif() 355 string(MAKE_C_IDENTIFIER "${VI_TARGET}" targetid) 356 357 if(NOT VI_PREFIX) 358 string(MAKE_C_IDENTIFIER "${VI_TARGET}" VI_PREFIX) 359 endif() 360 361 if(NOT VI_DIRECTORY) 362 # message(STATUS "add_version_info: defaulting DIRECTORY to '${CMAKE_CURRENT_SOURCE_DIR}'") 363 set(VI_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}") 364 endif() 365 366 # Set default values, in case sth goes wrong 367 set(VERSION_MAJOR 0) 368 set(VERSION_MINOR 0) 369 set(VERSION_PATCH 0) 370 set(VERSION_FLAG unknown) 371 set(VERSION_DISTANCE 0) 372 set(VERSION_SHORTHASH unknown) 373 set(VERSION_FULLHASH unknown) 374 set(VERSION_STRING "0.0-unknown.0") 375 set(VERSION_ISDIRTY 0) 376 set(VERSION_BRANCH unknown) 377 set(output_dir "${CMAKE_CURRENT_BINARY_DIR}/version/${targetid}") 378 379 get_target_property(TARGET_VMAJOR ${VI_TARGET} VERSION_MAJOR) 380 if(TARGET_VMAJOR) 381 set(${VI_PREFIX}_CUSTOM_VERSION_MAJOR ${TARGET_VMAJOR}) 382 endif() 383 get_target_property(TARGET_VMINOR ${VI_TARGET} VERSION_MINOR) 384 if(TARGET_VMINOR) 385 set(${VI_PREFIX}_CUSTOM_VERSION_MINOR ${TARGET_VMINOR}) 386 set(VERSION_MINOR ${TARGET_VMINOR}) 387 endif() 388 get_target_property(TARGET_VPATCH ${VI_TARGET} VERSION_PATCH) 389 if(TARGET_VPATCH) 390 set(${VI_PREFIX}_CUSTOM_VERSION_PATCH ${TARGET_VPATCH}) 391 endif() 392 get_target_property(TARGET_VTYPE ${VI_TARGET} VERSION_TYPE) 393 if(TARGET_VTYPE) 394 set(${VI_PREFIX}_FALLBACK_VERSION_TYPE ${TARGET_VTYPE}) 395 endif() 396 397 # Check for ArchiveVersionInfo within same directory and use that info is available ... 398 include(ArchiveVersionInfo_${VI_PREFIX} OPTIONAL RESULT_VARIABLE ARCHIVE_VERSION_PRESENT) 399 if(ARCHIVE_VERSION_PRESENT AND ${VI_PREFIX}_VERSION_SUCCESS) 400 message(STATUS "Info: Version information from archive file.") 401 402 # ... get version info via git otherwise. 403 else() 404 get_version_info(${VI_PREFIX} "${VI_DIRECTORY}") 405 406 # Check if valid version information could be aquired... 407 if("${${VI_PREFIX}_VERSION_FULLHASH}" STREQUAL "unknown" 408 OR "${${VI_PREFIX}_VERSION_SHORTHASH}" STREQUAL "unknown" 409 OR "${${VI_PREFIX}_VERSION_FULLHASH}" STREQUAL "" 410 OR "${${VI_PREFIX}_VERSION_SHORTHASH}" STREQUAL "") 411 412 # ...and check for ArchiveExportInfo as fallback solution.. 413 include(ArchiveExportInfo OPTIONAL RESULT_VARIABLE GIT_EXPORT_INFO_FILE_PRESENT) 414 if("${GIT_EXPORT_VERSION_SHORTHASH}" MATCHES "(.?Format:).*") 415 set(HAS_GIT_EXPORT_INFO OFF) 416 endif() 417 if(GIT_EXPORT_INFO_FILE_PRESENT AND HAS_GIT_EXPORT_INFO) 418 message(STATUS "Using ArchiveExportInfo as fallback for version info.") 419 set(${VI_PREFIX}_VERSION_SHORTHASH "${GIT_EXPORT_VERSION_SHORTHASH}") 420 set(${VI_PREFIX}_VERSION_FULLHASH "${GIT_EXPORT_VERSION_FULLHASH}") 421 set(${VI_PREFIX}_VERSION_BRANCH "${GIT_EXPORT_VERSION_BRANCH}") 422 if("${${VI_PREFIX}_VERSION_BRANCH}" MATCHES ".*[ \t]+[->]+[\t ]+(.*)([,]?.*)") 423 set(${VI_PREFIX}_VERSION_BRANCH "${CMAKE_MATCH_1}") 424 elseif("${${VI_PREFIX}_VERSION_BRANCH}" MATCHES ".*,[ \t](.*)") 425 if("${CMAKE_MATCH_1}" STREQUAL "master") 426 set(ON_MASTER ON) 427 endif() 428 endif() 429 # Check for release branch 430 string(LENGTH ${RC_BRANCH_PREFIX} PREFIX_LEN) 431 string(SUBSTRING ${${VI_PREFIX}_VERSION_BRANCH} 0 ${PREFIX_LEN} COMPARE_PREFIX) 432 string(COMPARE EQUAL ${RC_BRANCH_PREFIX} ${COMPARE_PREFIX} ON_RELEASE_BRANCH) 433 # Check for hotfix branch 434 string(LENGTH ${HOTFIX_BRANCH_PREFIX} PREFIX_LEN) 435 string(SUBSTRING ${${VI_PREFIX}_VERSION_BRANCH} 0 ${PREFIX_LEN} COMPARE_PREFIX) 436 string(COMPARE EQUAL ${HOTFIX_BRANCH_PREFIX} ${COMPARE_PREFIX} ON_HOTFIX_BRANCH) 437 # Check for master branch 438 if(NOT ON_MASTER) 439 string(COMPARE EQUAL "master" ${${VI_PREFIX}_VERSION_BRANCH} ON_MASTER) 440 endif() 441 if(ON_MASTER) 442 set(${VI_PREFIX}_VERSION_FLAG "") 443 elseif(ON_RELEASE_BRANCH) 444 set(${VI_PREFIX}_VERSION_FLAG "${VERSION_RC_FLAG}") 445 elseiF(ON_HOTFIX_BRANCH) 446 set(${VI_PREFIX}_VERSION_FLAG "hotfix") 447 else() 448 set(${VI_PREFIX}_VERSION_FLAG "${VERSION_ALPHA_FLAG}") 449 endif() 450 # Build version string... 451 set(VERSION_STRING "${${VI_PREFIX}_VERSION_MAJOR}.${${VI_PREFIX}_VERSION_MINOR}") 452 if(NOT ${${VI_PREFIX}_VERSION_PATCH} EQUAL 0) 453 set(VERSION_STRING "${VERSION_STRING}.${${VI_PREFIX}_VERSION_PATCH}") 454 endif() 455 if(NOT ON_MASTER OR NOT ${${VI_PREFIX}_VERSION_DISTANCE} EQUAL 0) 456 set(VERSION_STRING "${VERSION_STRING}-${${VI_PREFIX}_VERSION_FLAG}") 457 endif() 458 if(NOT ${${VI_PREFIX}_VERSION_FLAG} STREQUAL "") 459 set(VERSION_STRING "${VERSION_STRING}.") 460 endif() 461 if(NOT ON_MASTER OR (NOT ON_MASTER AND NOT ${${VI_PREFIX}_VERSION_DISTANCE} EQUAL 0)) 462 set(VERSION_STRING "${VERSION_STRING}${${VI_PREFIX}_VERSION_DISTANCE}") 463 endif() 464 set(${VI_PREFIX}_VERSION_STRING "${VERSION_STRING}") 465 endif() 466 endif() 467 endif() 468 469 if(${${VI_PREFIX}_VERSION_SUCCESS}) 470 # All informations gathered via git 471 else() 472 message(STATUS "Version-Info: Failure during version retrieval. Possible incomplete version information!") 473 endif() 474 # Test if we are building from an archive that has generated version information 475 set(VERSION_MAJOR ${${VI_PREFIX}_VERSION_MAJOR}) 476 set(VERSION_MINOR ${${VI_PREFIX}_VERSION_MINOR}) 477 set(VERSION_PATCH ${${VI_PREFIX}_VERSION_PATCH}) 478 set(VERSION_FLAG ${${VI_PREFIX}_VERSION_FLAG}) 479 set(VERSION_DISTANCE ${${VI_PREFIX}_VERSION_DISTANCE}) 480 set(VERSION_SHORTHASH ${${VI_PREFIX}_VERSION_SHORTHASH}) 481 set(VERSION_FULLHASH ${${VI_PREFIX}_VERSION_FULLHASH}) 482 set(VERSION_STRING ${${VI_PREFIX}_VERSION_STRING}) 483 set(VERSION_ISDIRTY ${${VI_PREFIX}_VERSION_ISDIRTY}) 484 set(VERSION_BRANCH ${${VI_PREFIX}_VERSION_BRANCH}) 485 set_target_properties(${VI_TARGET} PROPERTIES 486 VERSION_MAJOR "${VERSION_MAJOR}" 487 VERSION_MINOR "${VERSION_MINOR}" 488 VERSION_PATCH "${VERSION_PATCH}" 489 VERSION_FLAG "${VERSION_FLAG}" 490 VERSION_DISTANCE "${VERSION_DISTANCE}" 491 VERSION_SHORTHASH "${VERSION_SHORTHASH}" 492 VERSION_FULLHASH "${VERSION_FULLHASH}" 493 VERSION_STRING "${VERSION_STRING}" 494 VERSION_ISDIRTY "${VERSION_ISDIRTY}" 495 VERSION_BRANCH "${VERSION_BRANCH}" 496 ) 497 498 set(TARGET ${VI_PREFIX}) 499 set(PREFIX ${VI_PREFIX}) 500 foreach(template_file ${VI_TEMPLATES}) 501 if(template_file MATCHES "(.*)(\.in)$") 502 get_filename_component(output_basename "${CMAKE_MATCH_1}" NAME) 503 else() 504 get_filename_component(output_basename "${template_file}" NAME) 505 endif() 506 set(output_file "${output_dir}/${VI_PREFIX}-${output_basename}") 507 configure_file("${template_file}" "${output_file}") 508 list(APPEND output_files "${output_file}") 509 endforeach() 510 511 # Generate archive version info. File can be included in source archives to have detailed 512 # version information available without being a git repository. 513 # See https://github.com/jahnf/Projecteur, where it is used for the 'source-archive' build target. 514 configure_file("${_GitVersion_DIRECTORY}/ArchiveVersionInfo.cmake.in" 515 "archive_append/cmake/modules/ArchiveVersionInfo_${VI_PREFIX}.cmake" @ONLY) 516 517 get_target_property(type ${VI_TARGET} TYPE) 518 if(type STREQUAL "SHARED_LIBRARY") 519 set_target_properties(${VI_TARGET} PROPERTIES SOVERSION "${VERSION_MAJOR}.${VERSION_MINOR}") 520 set_property(TARGET ${VI_TARGET} PROPERTY VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}") 521 endif() 522 523 # If any templates where configured, add them to the project sources 524 list(LENGTH output_files NUM_CONFIGURED_FILES) 525 if(NOT NUM_CONFIGURED_FILES EQUAL 0) 526 set_property(TARGET ${VI_TARGET} APPEND PROPERTY SOURCES ${output_files}) 527 target_include_directories(${VI_TARGET} PUBLIC $<BUILD_INTERFACE:${output_dir}>) 528 endif() 529 message(STATUS "Version info for '${VI_TARGET}': ${VERSION_STRING} (prefix=${VI_PREFIX})") 530endfunction() 531 532