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

Merge branch 'cwg-43-versioning' into 'main'

CWG-45: Implement git tag based version extraction

See merge request !9
parents 48961ba6 2bf0684e
No related branches found
No related tags found
1 merge request!9CWG-45: Implement git tag based version extraction
Pipeline #64387 waiting for manual action
Pipeline: C++ project

#64388

    cmake_minimum_required(VERSION 3.16) 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(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 17)
    set(CMAKE_CXX_STANDARD_REQUIRED YES) set(CMAKE_CXX_STANDARD_REQUIRED YES)
    set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_CXX_EXTENSIONS OFF)
    set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
    option(BUILD_TESTING "Build the test suite" OFF) option(BUILD_TESTING "Build the test suite" OFF)
    option(BUILD_DOCUMENTATION "Build the documentation" OFF) option(BUILD_DOCUMENTATION "Build the documentation" OFF)
    ......
    ...@@ -36,6 +36,15 @@ For instance: ...@@ -36,6 +36,15 @@ For instance:
    - Install the project globally: ``ninja -C ./build/ install`` - Install the project globally: ``ninja -C ./build/ install``
    - Clean caches: `ninja -C ./build/ clean` - 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 ## Contributing
    To contribute, please create a feature branch and a "Draft" merge request. Upon 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 @@ ...@@ -4,5 +4,6 @@
    add_subdirectory(lib) add_subdirectory(lib)
    add_executable(cpp main.cpp) add_executable(cpp main.cpp)
    add_version_info(TARGET cpp)
    target_link_libraries(cpp PRIVATE hello) target_link_libraries(cpp PRIVATE hello)
    // Copyright (C) ASTRON (Netherlands Institute for Radio Astronomy) // Copyright (C) ASTRON (Netherlands Institute for Radio Astronomy)
    // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
    #include <iostream>
    #include "hello.hpp" #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