Skip to content
Snippets Groups Projects
Commit 2bf0684e authored by Corné Lukken's avatar Corné Lukken
Browse files

CWG-45: Implement git tag based version extraction

parent 48961ba6
No related branches found
No related tags found
1 merge request!9CWG-45: Implement git tag based version extraction
cmake_minimum_required(VERSION 3.16)
project({{cookiecutter.project_slug}} VERSION 0.1)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
include(CheckCXXCompilerFlag)
include(GitVersion)
get_version_info({{cookiecutter.project_slug}} "${CMAKE_CURRENT_SOURCE_DIR}")
set(project_slug {{cookiecutter.project_slug}})
project({{cookiecutter.project_slug}} VERSION ${${project_slug}_VERSION})
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED YES)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
option(BUILD_TESTING "Build the test suite" OFF)
option(BUILD_DOCUMENTATION "Build the documentation" OFF)
......
......@@ -36,6 +36,15 @@ For instance:
- Install the project globally: ``ninja -C ./build/ install``
- Clean caches: `ninja -C ./build/ clean`
## Versioning
This project uses git tags or branch names to determine the current version of the
software. The version information is automatically made available in CMake and can be
made available in C/C++ by dynamically adding a generated header.
See for details:
- https://github.com/jahnf/CMake-GitVersion/blob/develop/cmake/GitVersion.cmake
## Contributing
To contribute, please create a feature branch and a "Draft" merge request. Upon
......
# Fallback for version generation from pure git archive exports
set(GIT_EXPORT_VERSION_SHORTHASH "$Format:%h$")
set(GIT_EXPORT_VERSION_FULLHASH "$Format:%H$")
set(GIT_EXPORT_VERSION_BRANCH "$Format:%D$") # needs parsing in cmake...
set(HAS_GIT_EXPORT_INFO 1)
# Auto generated archive version information
# Included in created source archives
set(@PREFIX@_VERSION "@VERSION@")
set(@PREFIX@_VERSION_MAJOR "@VERSION_MAJOR@")
set(@PREFIX@_VERSION_MINOR "@VERSION_MINOR@")
set(@PREFIX@_VERSION_PATCH "@VERSION_PATCH@")
set(@PREFIX@_VERSION_FLAG "@VERSION_FLAG@")
set(@PREFIX@_VERSION_DISTANCE "@VERSION_DISTANCE@")
set(@PREFIX@_VERSION_SHORTHASH "@VERSION_SHORTHASH@")
set(@PREFIX@_VERSION_FULLHASH "@VERSION_FULLHASH@")
set(@PREFIX@_VERSION_STRING "@VERSION_STRING@")
set(@PREFIX@_VERSION_ISDIRTY "@VERSION_ISDIRTY@")
set(@PREFIX@_VERSION_BRANCH "@VERSION_BRANCH@")
set(@PREFIX@_VERSION_SUCCESS 1)
#include "@PREFIX@-GitVersion.h"
namespace @PREFIX@ {
const char* version() { return "@VERSION@"; }
const char* version_string() { return "@VERSION_STRING@"; }
unsigned int version_major() { return @VERSION_MAJOR@; }
unsigned int version_minor() { return @VERSION_MINOR@; }
unsigned int version_patch() { return @VERSION_PATCH@; }
const char* version_flag() { return "@VERSION_FLAG@"; }
unsigned int version_distance() { return @VERSION_DISTANCE@; }
const char* version_shorthash() { return "@VERSION_SHORTHASH@"; }
const char* version_fullhash() { return "@VERSION_FULLHASH@"; }
bool version_isdirty() { return @VERSION_ISDIRTY@; }
const char* version_branch() { return "@VERSION_BRANCH@"; }
}
# https://github.com/jahnf/CMake-GitVersion/blob/develop/cmake/GitVersion.cmake
# CMake-GitVersion.
# (Yet another) automatic version generation for C++ CMake projects.
# * Generates version information using information from git (tags) with fallback options
# when building without git (e.g. when building from sources with exported archives).
# * Use custom templates for generated sources (e.g. also create resource files (see examples))
# * Uses semantic versioning (https://semver.org/)
# * Best suited with git-flow workflows
# * See: https://www.atlassian.com/de/git/tutorials/comparing-workflows/gitflow-workflow
# * See: https://nvie.com/posts/a-successful-git-branching-model/
# * Generated version strings are compatible to/and can be used by debian and rpm packages.
# ## Version Generation
# Defines
# - `LAST_TAG_VERSION`: latest tagged version (e.g. 1.2.0 for tag v1.2.0) or 0.0.0 if no tag exists.
# - `DIST`: commit count distance to latest version tag.
# Version Number rules:
# - on _master_: `X.Y.Z`[-`DIST`] (using `LAST_TAG_VERSION`), while `DIST` should always be 0 on the master branch.
# - on _develop_ and other branches: `X.Y.Z`-`ALPHA_FLAG`.`DIST` (using `LAST_TAG_VERSION`, `Y` incremented by 1)
# - on release branches: `X.Y.Z`-`RC_FLAG`.`DIST` (extracting `X.Y.Z` from release branch name or from _develop_ as fallback). \
# `DIST` is either calculated to last version tag or to the closest `rc-X.Y.Z` tag.
# - `DIST` is added to all version numbers, except:
# - Versions on _master_ and on _hotfix_ branches with `DIST` equal to 0
# - All version numbers have a pre-release identifier set, except:
# - Version on _master_ and
# - versions on _hotfix_ branches with `DIST` equal to 0
# - When creating the version string and the PATCH number is 0 - the patch number is omitted.
# (e.g. 1.2.0 will be 1.2)
### Configuration - this may be adjusted to the personal and project requirements
set(VERSION_TAG_PREFIX v) # Should be the same as configured in git-flow
set(VERSION_ALPHA_FLAG alpha) # Pre-release identifier for all builds besides release and hotfix branches
set(VERSION_RC_FLAG rc) # Pre-release identifier for all builds from release and hotfix branches
set(VERSION_RC_START_TAG_PREFIX "rc-") # If available tags with the given prefix are used for distance calculation on release branches.
set(RC_BRANCH_PREFIX release) # e.g. release/0.2
set(HOTFIX_BRANCH_PREFIX hotfix) # e.g. hotfix/2.0.3
# Let functions in this module know their own directory
set(_GitVersion_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}")
# --------------------------------------------------------------------------------------------------
# Helper method - usually never called directly:
# Get the version information for a directory, sets the following variables
# ${prefix}_VERSION_SUCCESS // 0 on error (e.g. git not found), 1 on success
# ${prefix}_VERSION
# ${prefix}_VERSION_MAJOR
# ${prefix}_VERSION_MINOR
# ${prefix}_VERSION_PATCH
# ${prefix}_VERSION_FLAG
# ${prefix}_VERSION_DISTANCE
# ${prefix}_VERSION_SHORTHASH
# ${prefix}_VERSION_FULLHASH
# ${prefix}_VERSION_ISDIRTY // 0 or 1 if tree has local modifications
# ${prefix}_VERSION_STRING // Full version string, e.g. 1.2.3-rc.239
#
# A created version number can be overruled if the following variables are set and the version number is GREATER
# than the dynamically created one.
# - ${prefix}_CUSTOM_VERSION_MAJOR
# - ${prefix}_CUSTOM_VERSION_MINOR
# - ${prefix}_CUSTOM_VERSION_PATCH
#
# A version 'type' (release or develop) in case the branch cannot be determined via git
# - #{prefix}_FALLBACK_VERSION_TYPE
#
# The environment variable FALLBACK_BRANCH will be used if the branch cannot be determined
function(get_version_info prefix directory)
set(${prefix}_VERSION_SUCCESS 0 PARENT_SCOPE)
set(${prefix}_VERSION "0.0.0")
set(${prefix}_VERSION_MAJOR 0)
set(${prefix}_VERSION_MINOR 0)
set(${prefix}_VERSION_PATCH 0)
set(${prefix}_VERSION_BRANCH unknown)
set(${prefix}_VERSION_FLAG unknown)
set(${prefix}_VERSION_DISTANCE 0)
set(${prefix}_VERSION_STRING 0.0.0-unknown)
set(${prefix}_VERSION_ISDIRTY 0 PARENT_SCOPE)
if("${${prefix}_CUSTOM_VERSION_MAJOR}" STREQUAL "")
set(${prefix}_CUSTOM_VERSION_MAJOR 0)
endif()
if("${${prefix}_CUSTOM_VERSION_MINOR}" STREQUAL "")
set(${prefix}_CUSTOM_VERSION_MINOR 0)
endif()
if("${${prefix}_CUSTOM_VERSION_PATCH}" STREQUAL "")
set(${prefix}_CUSTOM_VERSION_PATCH 0)
endif()
find_package(Git)
if(GIT_FOUND)
# Get the version info from the last tag (using the configured version tag prefix)
execute_process(COMMAND ${GIT_EXECUTABLE} describe --tags --match "${VERSION_TAG_PREFIX}[0-9].[0-9]*"
RESULT_VARIABLE result
OUTPUT_VARIABLE GIT_TAG_VERSION
ERROR_VARIABLE error_out
OUTPUT_STRIP_TRAILING_WHITESPACE
WORKING_DIRECTORY ${directory}
)
if(result EQUAL 0)
# Extract version major, minor, patch from the result
if(GIT_TAG_VERSION MATCHES "^${VERSION_TAG_PREFIX}?([0-9]+)\\.([0-9]+)(\\.([0-9]+))?(-([0-9]+))?.*$")
set(${prefix}_VERSION_MAJOR ${CMAKE_MATCH_1})
set(${prefix}_VERSION_MINOR ${CMAKE_MATCH_2})
if(NOT ${CMAKE_MATCH_4} STREQUAL "")
set(${prefix}_VERSION_PATCH ${CMAKE_MATCH_4})
endif()
if(NOT ${CMAKE_MATCH_6} STREQUAL "")
set(${prefix}_VERSION_DISTANCE ${CMAKE_MATCH_6})
endif()
endif()
else()
# git describe return with error - just get the distance
execute_process(COMMAND ${GIT_EXECUTABLE} rev-list --count HEAD
RESULT_VARIABLE result
OUTPUT_VARIABLE GIT_DISTANCE
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_VARIABLE error_out
WORKING_DIRECTORY ${directory}
)
if(result EQUAL 0)
set(${prefix}_VERSION_DISTANCE ${GIT_DISTANCE})
endif()
endif()
# Check for local modifications ...
execute_process(COMMAND ${GIT_EXECUTABLE} describe --always --dirty
RESULT_VARIABLE result
OUTPUT_VARIABLE GIT_ALWAYS_VERSION
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_VARIABLE error_out
WORKING_DIRECTORY ${directory}
)
if(result EQUAL 0)
if(GIT_ALWAYS_VERSION MATCHES "^.*-dirty$")
set(${prefix}_VERSION_ISDIRTY 1 PARENT_SCOPE)
endif()
endif()
# Check the branch we are on
execute_process(COMMAND ${GIT_EXECUTABLE} rev-parse --abbrev-ref HEAD
RESULT_VARIABLE result
OUTPUT_VARIABLE GIT_BRANCH
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_VARIABLE error_out
WORKING_DIRECTORY ${directory}
)
if(result EQUAL 0)
if("${GIT_BRANCH}" STREQUAL "HEAD"
AND NOT "$ENV{FALLBACK_BRANCH}" STREQUAL "")
set(GIT_BRANCH "$ENV{FALLBACK_BRANCH}")
endif()
set(${prefix}_VERSION_BRANCH "${GIT_BRANCH}")
set(${prefix}_VERSION_BRANCH "${GIT_BRANCH}" PARENT_SCOPE)
# Check for release branch
string(LENGTH ${RC_BRANCH_PREFIX} PREFIX_LEN)
string(SUBSTRING ${GIT_BRANCH} 0 ${PREFIX_LEN} COMPARE_PREFIX)
string(COMPARE EQUAL ${RC_BRANCH_PREFIX} ${COMPARE_PREFIX} ON_RELEASE_BRANCH)
# Check for hotfix branch
string(LENGTH ${HOTFIX_BRANCH_PREFIX} PREFIX_LEN)
string(SUBSTRING ${GIT_BRANCH} 0 ${PREFIX_LEN} COMPARE_PREFIX)
string(COMPARE EQUAL ${HOTFIX_BRANCH_PREFIX} ${COMPARE_PREFIX} ON_HOTFIX_BRANCH)
# Check for master branch
string(COMPARE EQUAL "master" ${GIT_BRANCH} ON_MASTER)
if(ON_RELEASE_BRANCH)
set(${prefix}_VERSION_FLAG ${VERSION_RC_FLAG})
set(RC_VERSION_MAJOR 0)
set(RC_VERSION_MINOR 0)
set(RC_VERSION_PATCH 0)
# Check release branch name for version information (e.g. release/0.8)
if(GIT_BRANCH MATCHES "^${RC_BRANCH_PREFIX}.*([0-9]+)\\.([0-9]+)(\\.([0-9]+))?.*$")
set(RC_VERSION_MAJOR ${CMAKE_MATCH_1})
set(RC_VERSION_MINOR ${CMAKE_MATCH_2})
if(NOT ${CMAKE_MATCH_4} STREQUAL "")
set(RC_VERSION_PATCH ${CMAKE_MATCH_4})
endif()
endif()
# If the release branch version is greater, use that version...
if("${RC_VERSION_MAJOR}.${RC_VERSION_MINOR}.${RC_VERSION_PATCH}" VERSION_GREATER
"${${prefix}_VERSION_MAJOR}.${${prefix}_VERSION_MINOR}.${${prefix}_VERSION_PATCH}")
set(${prefix}_VERSION_MAJOR ${RC_VERSION_MAJOR})
set(${prefix}_VERSION_MINOR ${RC_VERSION_MINOR})
set(${prefix}_VERSION_PATCH ${RC_VERSION_PATCH})
else() # ... else auto increment the version minor number
# Auto increment minor number, patch = 0
MATH(EXPR ${prefix}_VERSION_MINOR "${${prefix}_VERSION_MINOR}+1")
set(${prefix}_VERSION_PATCH 0)
endif()
# Try to get distance from last rc start tag
execute_process(COMMAND ${GIT_EXECUTABLE} describe --tags --match "${VERSION_RC_START_TAG_PREFIX}[0-9].[0-9]*"
RESULT_VARIABLE result
OUTPUT_VARIABLE GIT_RC_TAG_VERSION
ERROR_VARIABLE error_out
OUTPUT_STRIP_TRAILING_WHITESPACE
WORKING_DIRECTORY ${directory}
)
if(result EQUAL 0)
if(GIT_RC_TAG_VERSION MATCHES "^${VERSION_RC_START_TAG_PREFIX}?([0-9]+)\\.([0-9]+)(\\.([0-9]+))?(-([0-9]+))?.*$")
if(NOT ${CMAKE_MATCH_6} STREQUAL "")
set(${prefix}_VERSION_DISTANCE ${CMAKE_MATCH_6})
else()
set(${prefix}_VERSION_DISTANCE 0)
endif()
endif()
endif()
elseif(ON_HOTFIX_BRANCH)
set(${prefix}_VERSION_FLAG ${VERSION_RC_FLAG})
set(RC_VERSION_MAJOR 0)
set(RC_VERSION_MINOR 0)
set(RC_VERSION_PATCH 0)
if(GIT_BRANCH MATCHES "^${RC_BRANCH_PREFIX}.*([0-9]+)\\.([0-9]+)(\\.([0-9]+))?.*$")
set(RC_VERSION_MAJOR ${CMAKE_MATCH_1})
set(RC_VERSION_MINOR ${CMAKE_MATCH_2})
if(NOT ${CMAKE_MATCH_4} STREQUAL "")
set(RC_VERSION_PATCH ${CMAKE_MATCH_4})
endif()
endif()
if("${RC_VERSION_MAJOR}.${RC_VERSION_MINOR}.${RC_VERSION_PATCH}" VERSION_GREATER
"${${prefix}_VERSION_MAJOR}.${${prefix}_VERSION_MINOR}.${${prefix}_VERSION_PATCH}")
set(${prefix}_VERSION_MAJOR ${RC_VERSION_MAJOR})
set(${prefix}_VERSION_MINOR ${RC_VERSION_MINOR})
set(${prefix}_VERSION_PATCH ${RC_VERSION_PATCH})
else()
# Auto increment patch number
MATH(EXPR ${prefix}_VERSION_PATCH "${${prefix}_VERSION_PATCH}+1")
endif()
elseif(ON_MASTER)
set(${prefix}_VERSION_FLAG "")
endif()
endif()
if(NOT ON_MASTER AND NOT ON_RELEASE_BRANCH AND NOT ON_HOTFIX_BRANCH)
# Auto increment version number, set alpha flag
MATH(EXPR ${prefix}_VERSION_MINOR "${${prefix}_VERSION_MINOR}+1")
set(${prefix}_VERSION_PATCH 0)
set(${prefix}_VERSION_FLAG ${VERSION_ALPHA_FLAG})
endif()
set(${prefix}_VERSION_FLAG ${${prefix}_VERSION_FLAG} PARENT_SCOPE)
set(${prefix}_VERSION_DISTANCE ${${prefix}_VERSION_DISTANCE} PARENT_SCOPE)
execute_process(COMMAND ${GIT_EXECUTABLE} rev-parse --short HEAD
RESULT_VARIABLE resultSH
OUTPUT_VARIABLE GIT_SHORT_HASH
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_VARIABLE error_out
WORKING_DIRECTORY ${directory}
)
if(resultSH EQUAL 0)
set(${prefix}_VERSION_SHORTHASH ${GIT_SHORT_HASH} PARENT_SCOPE)
else()
message(STATUS "Version-Info: Could not fetch short version hash.")
set(${prefix}_VERSION_SHORTHASH "unknown" PARENT_SCOPE)
endif()
execute_process(COMMAND ${GIT_EXECUTABLE} rev-parse HEAD
RESULT_VARIABLE resultFH
OUTPUT_VARIABLE GIT_FULL_HASH
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_VARIABLE error_out
WORKING_DIRECTORY ${directory}
)
if(resultFH EQUAL 0)
set(${prefix}_VERSION_FULLHASH ${GIT_FULL_HASH} PARENT_SCOPE)
else()
message(STATUS "Version-Info: Could not fetch full version hash.")
set(${prefix}_VERSION_FULLHASH "unknown" PARENT_SCOPE)
endif()
if(resultSH EQUAL 0 AND resultFH EQUAL 0)
set(${prefix}_VERSION_SUCCESS 1 PARENT_SCOPE)
endif()
else() # Git not found ...
message(STATUS "Version-Info: Git not found. Possible incomplete version information.")
endif()
if("${${prefix}_VERSION_BRANCH}" STREQUAL "unknown" OR "${${prefix}_VERSION_BRANCH}" STREQUAL "")
if("${${prefix}_FALLBACK_VERSION_TYPE}" STREQUAL "release")
set(ON_MASTER ON)
set(${prefix}_VERSION_FLAG "")
set(${prefix}_VERSION_FLAG "" PARENT_SCOPE)
endif()
set(${prefix}_VERSION_BRANCH "not-within-git-repo" PARENT_SCOPE)
endif()
# Check if overrule version is greater than dynamically created one
if("${${prefix}_CUSTOM_VERSION_MAJOR}.${${prefix}_CUSTOM_VERSION_MINOR}.${${prefix}_CUSTOM_VERSION_PATCH}" VERSION_GREATER
"${${prefix}_VERSION_MAJOR}.${${prefix}_VERSION_MINOR}.${${prefix}_VERSION_PATCH}")
set(${prefix}_VERSION_MAJOR ${${prefix}_CUSTOM_VERSION_MAJOR})
set(${prefix}_VERSION_MINOR ${${prefix}_CUSTOM_VERSION_MINOR})
set(${prefix}_VERSION_PATCH ${${prefix}_CUSTOM_VERSION_PATCH})
endif()
set(${prefix}_VERSION_MAJOR ${${prefix}_VERSION_MAJOR} PARENT_SCOPE)
set(${prefix}_VERSION_MINOR ${${prefix}_VERSION_MINOR} PARENT_SCOPE)
set(${prefix}_VERSION_PATCH ${${prefix}_VERSION_PATCH} PARENT_SCOPE)
set(${prefix}_VERSION_DISTANCE ${${prefix}_VERSION_DISTANCE} PARENT_SCOPE)
# build version
set(VERSION "${${prefix}_VERSION_MAJOR}.${${prefix}_VERSION_MINOR}.${${prefix}_VERSION_PATCH}")
set(${prefix}_VERSION "${VERSION}" PARENT_SCOPE)
# Build version string...
set(VERSION_STRING "${${prefix}_VERSION_MAJOR}.${${prefix}_VERSION_MINOR}")
if(NOT ${${prefix}_VERSION_PATCH} EQUAL 0)
set(VERSION_STRING "${VERSION_STRING}.${${prefix}_VERSION_PATCH}")
endif()
if(NOT ON_MASTER OR NOT ${${prefix}_VERSION_DISTANCE} EQUAL 0)
set(VERSION_STRING "${VERSION_STRING}-${${prefix}_VERSION_FLAG}")
endif()
if(NOT ${${prefix}_VERSION_FLAG} STREQUAL "")
set(VERSION_STRING "${VERSION_STRING}.")
endif()
if(NOT ON_MASTER OR (NOT ON_MASTER AND NOT ${${prefix}_VERSION_DISTANCE} EQUAL 0))
set(VERSION_STRING "${VERSION_STRING}${${prefix}_VERSION_DISTANCE}")
endif()
set(${prefix}_VERSION_STRING "${VERSION_STRING}" PARENT_SCOPE)
endfunction()
# --------------------------------------------------------------------------------------------------
# Add version information to a target, header and source file are configured from templates.
# (defaults to GitVersion.h.in and GitVersion.cc.in if no other templates are defined)
# Variables available to input templates
# @PREFIX@ = target prefix name given in the function call, must be a valid C-identifier
# @VERSION_MAJOR@, @VERSION_MINOR@, @VERSION_PATCH@, @VERSION_FLAG@, @VERSION_DISTANCE@
# @VERSION_SHORTHASH@, @VERSION_FULLHASH@, @VERSION_STRING@, @VERSION_ISDIRTY, @VERSION_BRANCH@
function(add_version_info)
set(oneValueArgs
TARGET # The build target
PREFIX # The prefix/name for templates, must be a valid C identifier
DIRECTORY # Directory from which to get the git version info
)
set(multiValueArgs TEMPLATES) # Templates that are configured and added to the target
set(requiredArgs TARGET)
cmake_parse_arguments(VI "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
foreach(arg IN LISTS requiredArgs)
if("${VI_${arg}}" STREQUAL "")
message(FATAL_ERROR "Required argument '${arg}' is not set.")
endif()
endforeach()
if(NOT TARGET ${VI_TARGET})
message(FATAL_ERROR "Argument 'TARGET' needs to be a valid target.")
endif()
list(LENGTH VI_TEMPLATES NUM_TEMPLATES)
if(NUM_TEMPLATES EQUAL 0)
# Add default templates
list(APPEND VI_TEMPLATES "${_GitVersion_DIRECTORY}/GitVersion.h.in")
list(APPEND VI_TEMPLATES "${_GitVersion_DIRECTORY}/GitVersion.cc.in")
endif()
string(MAKE_C_IDENTIFIER "${VI_TARGET}" targetid)
if(NOT VI_PREFIX)
string(MAKE_C_IDENTIFIER "${VI_TARGET}" VI_PREFIX)
endif()
if(NOT VI_DIRECTORY)
# message(STATUS "add_version_info: defaulting DIRECTORY to '${CMAKE_CURRENT_SOURCE_DIR}'")
set(VI_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")
endif()
# Set default values, in case sth goes wrong
set(VERSION "0.0.0")
set(VERSION_MAJOR 0)
set(VERSION_MINOR 0)
set(VERSION_PATCH 0)
set(VERSION_FLAG unknown)
set(VERSION_DISTANCE 0)
set(VERSION_SHORTHASH unknown)
set(VERSION_FULLHASH unknown)
set(VERSION_STRING "0.0-unknown.0")
set(VERSION_ISDIRTY 0)
set(VERSION_BRANCH unknown)
set(output_dir "${CMAKE_CURRENT_BINARY_DIR}/version/${targetid}")
get_target_property(TARGET_VMAJOR ${VI_TARGET} VERSION_MAJOR)
if(TARGET_VMAJOR)
set(${VI_PREFIX}_CUSTOM_VERSION_MAJOR ${TARGET_VMAJOR})
endif()
get_target_property(TARGET_VMINOR ${VI_TARGET} VERSION_MINOR)
if(TARGET_VMINOR)
set(${VI_PREFIX}_CUSTOM_VERSION_MINOR ${TARGET_VMINOR})
set(VERSION_MINOR ${TARGET_VMINOR})
endif()
get_target_property(TARGET_VPATCH ${VI_TARGET} VERSION_PATCH)
if(TARGET_VPATCH)
set(${VI_PREFIX}_CUSTOM_VERSION_PATCH ${TARGET_VPATCH})
endif()
get_target_property(TARGET_VTYPE ${VI_TARGET} VERSION_TYPE)
if(TARGET_VTYPE)
set(${VI_PREFIX}_FALLBACK_VERSION_TYPE ${TARGET_VTYPE})
endif()
# Check for ArchiveVersionInfo within same directory and use that info is available ...
include(ArchiveVersionInfo_${VI_PREFIX} OPTIONAL RESULT_VARIABLE ARCHIVE_VERSION_PRESENT)
if(ARCHIVE_VERSION_PRESENT AND ${VI_PREFIX}_VERSION_SUCCESS)
message(STATUS "Info: Version information from archive file.")
# ... get version info via git otherwise.
else()
get_version_info(${VI_PREFIX} "${VI_DIRECTORY}")
# Check if valid version information could be aquired...
if("${${VI_PREFIX}_VERSION_FULLHASH}" STREQUAL "unknown"
OR "${${VI_PREFIX}_VERSION_SHORTHASH}" STREQUAL "unknown"
OR "${${VI_PREFIX}_VERSION_FULLHASH}" STREQUAL ""
OR "${${VI_PREFIX}_VERSION_SHORTHASH}" STREQUAL "")
# ...and check for ArchiveExportInfo as fallback solution..
include(ArchiveExportInfo OPTIONAL RESULT_VARIABLE GIT_EXPORT_INFO_FILE_PRESENT)
if("${GIT_EXPORT_VERSION_SHORTHASH}" MATCHES "(.?Format:).*")
set(HAS_GIT_EXPORT_INFO OFF)
endif()
if(GIT_EXPORT_INFO_FILE_PRESENT AND HAS_GIT_EXPORT_INFO)
message(STATUS "Using ArchiveExportInfo as fallback for version info.")
set(${VI_PREFIX}_VERSION_SHORTHASH "${GIT_EXPORT_VERSION_SHORTHASH}")
set(${VI_PREFIX}_VERSION_FULLHASH "${GIT_EXPORT_VERSION_FULLHASH}")
set(${VI_PREFIX}_VERSION_BRANCH "${GIT_EXPORT_VERSION_BRANCH}")
if("${${VI_PREFIX}_VERSION_BRANCH}" MATCHES ".*[ \t]+[->]+[\t ]+(.*)([,]?.*)")
set(${VI_PREFIX}_VERSION_BRANCH "${CMAKE_MATCH_1}")
elseif("${${VI_PREFIX}_VERSION_BRANCH}" MATCHES ".*,[ \t](.*)")
if("${CMAKE_MATCH_1}" STREQUAL "master")
set(ON_MASTER ON)
endif()
endif()
# Check for release branch
string(LENGTH ${RC_BRANCH_PREFIX} PREFIX_LEN)
string(SUBSTRING ${${VI_PREFIX}_VERSION_BRANCH} 0 ${PREFIX_LEN} COMPARE_PREFIX)
string(COMPARE EQUAL ${RC_BRANCH_PREFIX} ${COMPARE_PREFIX} ON_RELEASE_BRANCH)
# Check for hotfix branch
string(LENGTH ${HOTFIX_BRANCH_PREFIX} PREFIX_LEN)
string(SUBSTRING ${${VI_PREFIX}_VERSION_BRANCH} 0 ${PREFIX_LEN} COMPARE_PREFIX)
string(COMPARE EQUAL ${HOTFIX_BRANCH_PREFIX} ${COMPARE_PREFIX} ON_HOTFIX_BRANCH)
# Check for master branch
if(NOT ON_MASTER)
string(COMPARE EQUAL "master" ${${VI_PREFIX}_VERSION_BRANCH} ON_MASTER)
endif()
if(ON_MASTER)
set(${VI_PREFIX}_VERSION_FLAG "")
elseif(ON_RELEASE_BRANCH)
set(${VI_PREFIX}_VERSION_FLAG "${VERSION_RC_FLAG}")
elseiF(ON_HOTFIX_BRANCH)
set(${VI_PREFIX}_VERSION_FLAG "hotfix")
else()
set(${VI_PREFIX}_VERSION_FLAG "${VERSION_ALPHA_FLAG}")
endif()
# Build version string...
set(VERSION_STRING "${${VI_PREFIX}_VERSION_MAJOR}.${${VI_PREFIX}_VERSION_MINOR}")
if(NOT ${${VI_PREFIX}_VERSION_PATCH} EQUAL 0)
set(VERSION_STRING "${VERSION_STRING}.${${VI_PREFIX}_VERSION_PATCH}")
endif()
if(NOT ON_MASTER OR NOT ${${VI_PREFIX}_VERSION_DISTANCE} EQUAL 0)
set(VERSION_STRING "${VERSION_STRING}-${${VI_PREFIX}_VERSION_FLAG}")
endif()
if(NOT ${${VI_PREFIX}_VERSION_FLAG} STREQUAL "")
set(VERSION_STRING "${VERSION_STRING}.")
endif()
if(NOT ON_MASTER OR (NOT ON_MASTER AND NOT ${${VI_PREFIX}_VERSION_DISTANCE} EQUAL 0))
set(VERSION_STRING "${VERSION_STRING}${${VI_PREFIX}_VERSION_DISTANCE}")
endif()
set(${VI_PREFIX}_VERSION_STRING "${VERSION_STRING}")
endif()
endif()
endif()
if(${${VI_PREFIX}_VERSION_SUCCESS})
# All informations gathered via git
else()
message(STATUS "Version-Info: Failure during version retrieval. Possible incomplete version information!")
endif()
# Test if we are building from an archive that has generated version information
set(VERSION ${${VI_PREFIX}_VERSION})
set(VERSION_MAJOR ${${VI_PREFIX}_VERSION_MAJOR})
set(VERSION_MINOR ${${VI_PREFIX}_VERSION_MINOR})
set(VERSION_PATCH ${${VI_PREFIX}_VERSION_PATCH})
set(VERSION_FLAG ${${VI_PREFIX}_VERSION_FLAG})
set(VERSION_DISTANCE ${${VI_PREFIX}_VERSION_DISTANCE})
set(VERSION_SHORTHASH ${${VI_PREFIX}_VERSION_SHORTHASH})
set(VERSION_FULLHASH ${${VI_PREFIX}_VERSION_FULLHASH})
set(VERSION_STRING ${${VI_PREFIX}_VERSION_STRING})
set(VERSION_ISDIRTY ${${VI_PREFIX}_VERSION_ISDIRTY})
set(VERSION_BRANCH ${${VI_PREFIX}_VERSION_BRANCH})
set_target_properties(${VI_TARGET} PROPERTIES
VERSION "${VERSION}"
VERSION_MAJOR "${VERSION_MAJOR}"
VERSION_MINOR "${VERSION_MINOR}"
VERSION_PATCH "${VERSION_PATCH}"
VERSION_FLAG "${VERSION_FLAG}"
VERSION_DISTANCE "${VERSION_DISTANCE}"
VERSION_SHORTHASH "${VERSION_SHORTHASH}"
VERSION_FULLHASH "${VERSION_FULLHASH}"
VERSION_STRING "${VERSION_STRING}"
VERSION_ISDIRTY "${VERSION_ISDIRTY}"
VERSION_BRANCH "${VERSION_BRANCH}"
)
set(TARGET ${VI_PREFIX})
set(PREFIX ${VI_PREFIX})
foreach(template_file ${VI_TEMPLATES})
if(template_file MATCHES "(.*)(\.in)$")
get_filename_component(output_basename "${CMAKE_MATCH_1}" NAME)
else()
get_filename_component(output_basename "${template_file}" NAME)
endif()
set(output_file "${output_dir}/${VI_PREFIX}-${output_basename}")
configure_file("${template_file}" "${output_file}")
list(APPEND output_files "${output_file}")
endforeach()
# Generate archive version info. File can be included in source archives to have detailed
# version information available without being a git repository.
# See https://github.com/jahnf/Projecteur, where it is used for the 'source-archive' build target.
configure_file("${_GitVersion_DIRECTORY}/ArchiveVersionInfo.cmake.in"
"archive_append/cmake/modules/ArchiveVersionInfo_${VI_PREFIX}.cmake" @ONLY)
get_target_property(type ${VI_TARGET} TYPE)
if(type STREQUAL "SHARED_LIBRARY")
set_target_properties(${VI_TARGET} PROPERTIES SOVERSION "${VERSION_MAJOR}.${VERSION_MINOR}")
set_property(TARGET ${VI_TARGET} PROPERTY VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}")
endif()
# If any templates where configured, add them to the project sources
list(LENGTH output_files NUM_CONFIGURED_FILES)
if(NOT NUM_CONFIGURED_FILES EQUAL 0)
set_property(TARGET ${VI_TARGET} APPEND PROPERTY SOURCES ${output_files})
target_include_directories(${VI_TARGET} PUBLIC $<BUILD_INTERFACE:${output_dir}>)
endif()
message(STATUS "Version info for '${VI_TARGET}': ${VERSION_STRING} (prefix=${VI_PREFIX})")
endfunction()
#ifndef @PREFIX@_GITVERSION_H
#define @PREFIX@_GITVERSION_H
namespace @PREFIX@ {
const char* version();
const char* version_string();
unsigned int version_major();
unsigned int version_minor();
unsigned int version_patch();
const char* version_flag();
unsigned int version_distance();
const char* version_shorthash();
const char* version_fullhash();
bool version_isdirty();
const char* version_branch();
}
#endif
......@@ -4,5 +4,6 @@
add_subdirectory(lib)
add_executable(cpp main.cpp)
add_version_info(TARGET cpp)
target_link_libraries(cpp PRIVATE hello)
// Copyright (C) ASTRON (Netherlands Institute for Radio Astronomy)
// SPDX-License-Identifier: Apache-2.0
#include <iostream>
#include "hello.hpp"
#include "cpp-GitVersion.h"
int main(int, const char **) {
lib::Hello();
int main(int, const char **) { lib::Hello(); }
std::cout << "CMake-GitVersion example"<< std::endl;
std::cout << "- version: " << cpp::version() << std::endl;
std::cout << "- version_string: " << cpp::version_string() << std::endl;
std::cout << "- version_branch: " << cpp::version_branch() << std::endl;
std::cout << "- version_fullhash: " << cpp::version_fullhash() << std::endl;
std::cout << "- version_shorthash: " << cpp::version_shorthash() << std::endl;
std::cout << "- version_isdirty: " << cpp::version_isdirty() << std::endl;
std::cout << "- version_distance: " << cpp::version_distance() << std::endl;
std::cout << "- version_flag: " << cpp::version_flag() << std::endl;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment