From aceba5f929671b69d90d379b6f2d42b7248c3928 Mon Sep 17 00:00:00 2001 From: hxf0223 Date: Sun, 31 Aug 2025 09:39:07 +0800 Subject: [PATCH 1/3] fix set VERSION_OUT_DIR not work --- CMake/Version.cmake | 204 +++++++++++++++++++++++--------------------- 1 file changed, 109 insertions(+), 95 deletions(-) diff --git a/CMake/Version.cmake b/CMake/Version.cmake index a9981b4..7f19420 100644 --- a/CMake/Version.cmake +++ b/CMake/Version.cmake @@ -5,22 +5,26 @@ # @note 3.20 required for `GENERATED` attribute to be project-wide i.e. Version.h isn't build until build-time cmake_minimum_required(VERSION 3.20) -#TODO? if ( DEFINED VERSION_SEMANTIC ) - #return() -#endif() - +# TODO? if ( DEFINED VERSION_SEMANTIC ) +# return() +# endif() message(CHECK_START "Version.cmake") list(APPEND CMAKE_MESSAGE_INDENT " ") -set(VERSION_OUT_DIR "${CMAKE_BINARY_DIR}" CACHE PATH "Destination directory into which `Version.cmake` shall genrate Versioning header files") +if(NOT VERSION_OUT_DIR) + set(VERSION_OUT_DIR "${CMAKE_BINARY_DIR}" CACHE PATH "Destination directory into which `Version.cmake` shall genrate Versioning header files") +endif() + set(VERSION_SOURCE_DIR "${CMAKE_SOURCE_DIR}" CACHE PATH "Repositroy directory used for `Version.cmake` repo versioning") set(VERSION_PREFIX "" CACHE STRING "Prefix for generated files and definitions") # Get cmakeVersion information message(CHECK_START "Find git") -if( NOT DEFINED GIT_EXECUTABLE ) # Find Git or bail out - find_package( Git ) - if( NOT Git_FOUND ) + +if(NOT DEFINED GIT_EXECUTABLE) # Find Git or bail out + find_package(Git) + + if(NOT Git_FOUND) message(CHECK_FAIL "Not found in PATH") else() message(CHECK_PASS "Found: '${GIT_EXECUTABLE}'") @@ -28,66 +32,69 @@ if( NOT DEFINED GIT_EXECUTABLE ) # Find Git or bail out else() message(CHECK_PASS "Using pre-defined GIT_EXECUTABLE: '${GIT_EXECUTABLE}'") endif() - + # Git describe # @note Exclude 'tweak' tags in the form v0.1.2-30 i.e. with the '-30' to avoid a second suffix being appended e.g v0.1.2-30-12 set(GIT_VERSION_COMMAND "${GIT_EXECUTABLE}" -C "${VERSION_SOURCE_DIR}" --no-pager describe --tags --exclude "v[0-9]*[._][0-9]*[._][0-9]*-[0-9]*" --always --dirty --long) # Git count # @note We only count commits on the current branch and not comits in merge branches via '--first-parent'. The count is never unique but the Sha will be! -set(GIT_COUNT_COMMAND "${GIT_EXECUTABLE}" -C "${VERSION_SOURCE_DIR}" rev-list --count --first-parent HEAD) +set(GIT_COUNT_COMMAND "${GIT_EXECUTABLE}" -C "${VERSION_SOURCE_DIR}" rev-list --count --first-parent HEAD) # Git cache path set(GIT_CACHE_PATH_COMMAND "${GIT_EXECUTABLE}" -C "${VERSION_SOURCE_DIR}" rev-parse --git-dir) macro(version_parseSemantic semVer) - if( "${semVer}" MATCHES "^v?([0-9]+)[._]([0-9]+)[._]?([0-9]+)?[-]([0-9]+)[-][g]([._0-9A-Fa-f]+)[-]?(dirty)?$") - set( _VERSION_SET TRUE) - math( EXPR _VERSION_MAJOR "${CMAKE_MATCH_1}+0") - math( EXPR _VERSION_MINOR "${CMAKE_MATCH_2}+0") - math( EXPR _VERSION_PATCH "${CMAKE_MATCH_3}+0") - math( EXPR _VERSION_COMMIT "${CMAKE_MATCH_4}+0") - set( _VERSION_SHA "${CMAKE_MATCH_5}") - set( _VERSION_DIRTY "${CMAKE_MATCH_6}") - set( _VERSION_SEMANTIC ${_VERSION_MAJOR}.${_VERSION_MINOR}.${_VERSION_PATCH}.${_VERSION_COMMIT} ) - set( _VERSION_FULL ${git_describe} ) - if("${VERSION_PREFIX}" STREQUAL "") - set( _VERSION_PREFIX "") - else() - set( _VERSION_PREFIX "${VERSION_PREFIX}_") - endif() - else() - set( _VERSION_SET FALSE) + if("${semVer}" MATCHES "^v?([0-9]+)[._]([0-9]+)[._]?([0-9]+)?[-]([0-9]+)[-][g]([._0-9A-Fa-f]+)[-]?(dirty)?$") + set(_VERSION_SET TRUE) + math(EXPR _VERSION_MAJOR "${CMAKE_MATCH_1}+0") + math(EXPR _VERSION_MINOR "${CMAKE_MATCH_2}+0") + math(EXPR _VERSION_PATCH "${CMAKE_MATCH_3}+0") + math(EXPR _VERSION_COMMIT "${CMAKE_MATCH_4}+0") + set(_VERSION_SHA "${CMAKE_MATCH_5}") + set(_VERSION_DIRTY "${CMAKE_MATCH_6}") + set(_VERSION_SEMANTIC ${_VERSION_MAJOR}.${_VERSION_MINOR}.${_VERSION_PATCH}.${_VERSION_COMMIT}) + set(_VERSION_FULL ${git_describe}) + + if("${VERSION_PREFIX}" STREQUAL "") + set(_VERSION_PREFIX "") + else() + set(_VERSION_PREFIX "${VERSION_PREFIX}_") + endif() + else() + set(_VERSION_SET FALSE) endif() endmacro() macro(version_export_variables) - set( VERSION_SET ${_VERSION_SET} CACHE INTERNAL "" FORCE) - set( VERSION_MAJOR ${_VERSION_MAJOR} CACHE INTERNAL "" FORCE) - set( VERSION_MINOR ${_VERSION_MINOR} CACHE INTERNAL "" FORCE) - set( VERSION_PATCH ${_VERSION_PATCH} CACHE INTERNAL "" FORCE) - set( VERSION_COMMIT ${_VERSION_COMMIT} CACHE INTERNAL "" FORCE) - set( VERSION_SHA ${_VERSION_SHA} CACHE INTERNAL "" FORCE) - set( VERSION_DIRTY ${_VERSION_DIRTY} CACHE INTERNAL "" FORCE) - set( VERSION_SEMANTIC ${_VERSION_SEMANTIC} CACHE INTERNAL "" FORCE) - set( VERSION_FULL ${_VERSION_FULL} CACHE INTERNAL "" FORCE) + set(VERSION_SET ${_VERSION_SET} CACHE INTERNAL "" FORCE) + set(VERSION_MAJOR ${_VERSION_MAJOR} CACHE INTERNAL "" FORCE) + set(VERSION_MINOR ${_VERSION_MINOR} CACHE INTERNAL "" FORCE) + set(VERSION_PATCH ${_VERSION_PATCH} CACHE INTERNAL "" FORCE) + set(VERSION_COMMIT ${_VERSION_COMMIT} CACHE INTERNAL "" FORCE) + set(VERSION_SHA ${_VERSION_SHA} CACHE INTERNAL "" FORCE) + set(VERSION_DIRTY ${_VERSION_DIRTY} CACHE INTERNAL "" FORCE) + set(VERSION_SEMANTIC ${_VERSION_SEMANTIC} CACHE INTERNAL "" FORCE) + set(VERSION_FULL ${_VERSION_FULL} CACHE INTERNAL "" FORCE) endmacro() message(CHECK_START "Git Cache-Path") -if ( DEFINED GIT_CACHE_PATH) + +if(DEFINED GIT_CACHE_PATH) message(CHECK_PASS "Using pre-defined GIT_CACHE_PATH '${GIT_CACHE_PATH}'") else() execute_process( - COMMAND ${GIT_CACHE_PATH_COMMAND} - RESULT_VARIABLE _GIT_RESULT - OUTPUT_VARIABLE GIT_CACHE_PATH - ERROR_VARIABLE _GIT_ERROR + COMMAND ${GIT_CACHE_PATH_COMMAND} + RESULT_VARIABLE _GIT_RESULT + OUTPUT_VARIABLE GIT_CACHE_PATH + ERROR_VARIABLE _GIT_ERROR OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_STRIP_TRAILING_WHITESPACE ${capture_output} ) - if( NOT _GIT_RESULT EQUAL 0 ) - message( CHECK_FAIL "Failed: ${GIT_CACHE_PATH_COMMAND}\nRESULT_VARIABLE:'${_GIT_RESULT}' \nOUTPUT_VARIABLE:'${GIT_CACHE_PATH}' \nERROR_VARIABLE:'${_GIT_ERROR}'") + + if(NOT _GIT_RESULT EQUAL 0) + message(CHECK_FAIL "Failed: ${GIT_CACHE_PATH_COMMAND}\nRESULT_VARIABLE:'${_GIT_RESULT}' \nOUTPUT_VARIABLE:'${GIT_CACHE_PATH}' \nERROR_VARIABLE:'${_GIT_ERROR}'") else() file(TO_CMAKE_PATH "${VERSION_SOURCE_DIR}/${GIT_CACHE_PATH}" GIT_CACHE_PATH) message(CHECK_PASS "Success '${GIT_CACHE_PATH}'") @@ -96,17 +103,19 @@ endif() message(CHECK_START "Git Describe") execute_process( - COMMAND ${GIT_VERSION_COMMAND} - RESULT_VARIABLE _GIT_RESULT - OUTPUT_VARIABLE git_describe - ERROR_VARIABLE _GIT_ERROR + COMMAND ${GIT_VERSION_COMMAND} + RESULT_VARIABLE _GIT_RESULT + OUTPUT_VARIABLE git_describe + ERROR_VARIABLE _GIT_ERROR OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_STRIP_TRAILING_WHITESPACE ${capture_output} ) -if( NOT _GIT_RESULT EQUAL 0 ) - message( CHECK_FAIL "Failed: ${GIT_VERSION_COMMAND}\nResult:'${_GIT_RESULT}' Error:'${_GIT_ERROR}'") - if ( "${_GIT_ERROR}" STREQUAL "fatal: bad revision 'HEAD'") + +if(NOT _GIT_RESULT EQUAL 0) + message(CHECK_FAIL "Failed: ${GIT_VERSION_COMMAND}\nResult:'${_GIT_RESULT}' Error:'${_GIT_ERROR}'") + + if("${_GIT_ERROR}" STREQUAL "fatal: bad revision 'HEAD'") set(_VERSION_NOT_GIT_REPO TRUE) # Flag that we don't have a valid git-repository' endif() else() @@ -114,30 +123,33 @@ else() message(CHECK_START "Parse version") version_parseSemantic(${git_describe}) - if( ${_VERSION_SET} ) + + if(${_VERSION_SET}) message(CHECK_PASS "Tag '${git_describe}' is a valid semantic version [${_VERSION_SEMANTIC}]") else() message(CHECK_FAIL "'${git_describe}' is not a valid semantic-version e.g. 'v0.1.2-30'") endif() endif() - + if(NOT DEFINED _VERSION_FULL AND NOT _VERSION_NOT_GIT_REPO) message(CHECK_START "Fallback as Git-Count") execute_process( - COMMAND ${GIT_COUNT_COMMAND} - RESULT_VARIABLE _GIT_RESULT - OUTPUT_VARIABLE git_count - ERROR_VARIABLE _GIT_ERROR + COMMAND ${GIT_COUNT_COMMAND} + RESULT_VARIABLE _GIT_RESULT + OUTPUT_VARIABLE git_count + ERROR_VARIABLE _GIT_ERROR OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_STRIP_TRAILING_WHITESPACE ${capture_output} ) - if( NOT _GIT_RESULT EQUAL 0 ) - message( CHECK_FAIL "Failed: ${GIT_COUNT_COMMAND}\nResult:'${_GIT_RESULT}' Error:'${_GIT_ERROR}'") - else() + + if(NOT _GIT_RESULT EQUAL 0) + message(CHECK_FAIL "Failed: ${GIT_COUNT_COMMAND}\nResult:'${_GIT_RESULT}' Error:'${_GIT_ERROR}'") + else() set(git_describe "0.0.0-${git_count}-g${git_describe}") version_parseSemantic(${git_describe}) - if( ${VERSION_SET} ) + + if(${VERSION_SET}) message(CHECK_PASS "git-tag '${git_describe} is a valid semantic version") else() message(CHECK_FAIL "'${git_describe}' is not a valid semantic-version e.g. 'v0.1.2-30'") @@ -146,7 +158,7 @@ if(NOT DEFINED _VERSION_FULL AND NOT _VERSION_NOT_GIT_REPO) endif() function(gitversion_configure_file VERSION_H_TEMPLATE VERSION_H) - configure_file ( + configure_file( "${VERSION_H_TEMPLATE}" "${VERSION_H}" ) @@ -154,21 +166,22 @@ endfunction() version_export_variables() -if ( VERSION_GENERATE_NOW ) - gitversion_configure_file( ${VERSION_H_TEMPLATE} ${VERSION_H}) -else() +if(VERSION_GENERATE_NOW) + gitversion_configure_file(${VERSION_H_TEMPLATE} ${VERSION_H}) +else() set(VERSION_H_FILENAME "${VERSION_PREFIX}Version.h") set(VERSION_H_TEMPLATE "${CMAKE_CURRENT_LIST_DIR}/${VERSION_H_FILENAME}.in") set(VERSION_H "${VERSION_OUT_DIR}/${VERSION_H_FILENAME}") # If no Version.h.in exists we generate the template with the default message(CHECK_START "Find '${VERSION_H_FILENAME}.in'") - if ( NOT EXISTS ${VERSION_H_TEMPLATE} ) + + if(NOT EXISTS ${VERSION_H_TEMPLATE}) set(VERSION_H_TEMPLATE "${VERSION_OUT_DIR}/${VERSION_H_FILENAME}.in") - message( CHECK_FAIL "Not Found. Generating '${VERSION_H_TEMPLATE}'") + message(CHECK_FAIL "Not Found. Generating '${VERSION_H_TEMPLATE}'") file(WRITE ${VERSION_H_TEMPLATE} - [=[ + [=[ #define @_VERSION_PREFIX@VERSION_MAJOR @_VERSION_MAJOR@ #define @_VERSION_PREFIX@VERSION_MINOR @_VERSION_MINOR@ #define @_VERSION_PREFIX@VERSION_PATCH @_VERSION_PATCH@ @@ -177,49 +190,50 @@ else() #define @_VERSION_PREFIX@VERSION_SEMANTIC "@_VERSION_SEMANTIC@" #define @_VERSION_PREFIX@VERSION_FULL "@_VERSION_FULL@" ]=]) - if ( NOT EXISTS ${VERSION_H_TEMPLATE} ) - message( FATAL_ERROR "Failed to create template ${VERSION_H_TEMPLATE}") + + if(NOT EXISTS ${VERSION_H_TEMPLATE}) + message(FATAL_ERROR "Failed to create template ${VERSION_H_TEMPLATE}") endif() else() - message( CHECK_PASS "Found '${VERSION_H_TEMPLATE}'") + message(CHECK_PASS "Found '${VERSION_H_TEMPLATE}'") endif() # A custom target is used to update Version.h - add_custom_target( genCmakeVersion + add_custom_target(genCmakeVersion ALL BYPRODUCTS "${VERSION_H}" SOURCES "${VERSION_H_TEMPLATE}" DEPENDS "${GIT_CACHE_PATH}/index" - "${GIT_CACHE_PATH}/HEAD" + "${GIT_CACHE_PATH}/HEAD" COMMENT "Version.cmake: Generating `${VERSION_H_FILENAME}`" - COMMAND ${CMAKE_COMMAND} - -B "${VERSION_OUT_DIR}" - -D VERSION_GENERATE_NOW=YES - -D VERSION_H_TEMPLATE=${VERSION_H_TEMPLATE} - -D VERSION_H=${VERSION_H} - -D VERSION_PREFIX=${VERSION_PREFIX} - -D GIT_EXECUTABLE=${GIT_EXECUTABLE} - -D CMAKE_MODULE_PATH=${CMAKE_MODULE_PATH} - -P ${CMAKE_CURRENT_LIST_FILE} - WORKING_DIRECTORY ${VERSION_SOURCE_DIR} + COMMAND ${CMAKE_COMMAND} + -B "${VERSION_OUT_DIR}" + -D VERSION_GENERATE_NOW=YES + -D VERSION_H_TEMPLATE=${VERSION_H_TEMPLATE} + -D VERSION_H=${VERSION_H} + -D VERSION_PREFIX=${VERSION_PREFIX} + -D GIT_EXECUTABLE=${GIT_EXECUTABLE} + -D CMAKE_MODULE_PATH=${CMAKE_MODULE_PATH} + -P ${CMAKE_CURRENT_LIST_FILE} + WORKING_DIRECTORY ${VERSION_SOURCE_DIR} VERBATIM ) - add_library( cmakeVersion INTERFACE ) + add_library(cmakeVersion INTERFACE) target_include_directories(cmakeVersion INTERFACE "${VERSION_OUT_DIR}") # @note Explicit file-names - prevent Cmake finding `Version.h.in` for `Version.h` - if (POLICY CMP0115) + if(POLICY CMP0115) cmake_policy(SET CMP0115 NEW) endif() - target_sources( cmakeVersion - INTERFACE - "${VERSION_H}") - add_dependencies( cmakeVersion - INTERFACE genCmakeVersion ) - - add_library( version::version ALIAS cmakeVersion ) + target_sources(cmakeVersion + INTERFACE + "${VERSION_H}") + add_dependencies(cmakeVersion + INTERFACE genCmakeVersion) + + add_library(version::version ALIAS cmakeVersion) endif() list(POP_BACK CMAKE_MESSAGE_INDENT) @@ -227,13 +241,13 @@ list(POP_BACK CMAKE_MESSAGE_INDENT) if(VERSION_GENERATE_NOW) set(VERSION_H_GENERATED TRUE) else() - get_source_file_property(VERSION_H_GENERATED "${VERSION_H}" GENERATED ) + get_source_file_property(VERSION_H_GENERATED "${VERSION_H}" GENERATED) endif() -if ( NOT _VERSION_NOT_GIT_REPO ) - if ( NOT VERSION_SET ) +if(NOT _VERSION_NOT_GIT_REPO) + if(NOT VERSION_SET) message(CHECK_FAIL "Version.cmake failed - VERSION_SET==false") - elseif ( ${VERSION_H_GENERATED} ) + elseif(${VERSION_H_GENERATED}) message(CHECK_PASS "${VERSION_FULL} [${VERSION_SEMANTIC}] {Generated}") elseif(EXISTS ${VERSION_H}) message(CHECK_PASS "Using pre-defined '${VERSION_H}'") From f07e8c38d1ac2c3a73180c67729c4ba843c406ee Mon Sep 17 00:00:00 2001 From: hxf0223 Date: Wed, 12 Nov 2025 00:49:27 +0800 Subject: [PATCH 2/3] add VERSION_DATE and VERSION_DATETIME --- CMake/Version.cmake | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CMake/Version.cmake b/CMake/Version.cmake index 7f19420..ec27fd7 100644 --- a/CMake/Version.cmake +++ b/CMake/Version.cmake @@ -44,6 +44,10 @@ set(GIT_COUNT_COMMAND "${GIT_EXECUTABLE}" -C "${VERSION_SOURCE_DIR}" rev-list -- # Git cache path set(GIT_CACHE_PATH_COMMAND "${GIT_EXECUTABLE}" -C "${VERSION_SOURCE_DIR}" rev-parse --git-dir) +# Get current date +string(TIMESTAMP VERSION_DATE "%Y-%m-%d" UTC) +string(TIMESTAMP VERSION_DATETIME "%Y-%m-%d %H:%M:%S" UTC) + macro(version_parseSemantic semVer) if("${semVer}" MATCHES "^v?([0-9]+)[._]([0-9]+)[._]?([0-9]+)?[-]([0-9]+)[-][g]([._0-9A-Fa-f]+)[-]?(dirty)?$") set(_VERSION_SET TRUE) @@ -76,6 +80,8 @@ macro(version_export_variables) set(VERSION_DIRTY ${_VERSION_DIRTY} CACHE INTERNAL "" FORCE) set(VERSION_SEMANTIC ${_VERSION_SEMANTIC} CACHE INTERNAL "" FORCE) set(VERSION_FULL ${_VERSION_FULL} CACHE INTERNAL "" FORCE) + set(VERSION_DATE ${VERSION_DATE} CACHE INTERNAL "" FORCE) + set(VERSION_DATETIME ${VERSION_DATETIME} CACHE INTERNAL "" FORCE) endmacro() message(CHECK_START "Git Cache-Path") @@ -189,6 +195,8 @@ else() #define @_VERSION_PREFIX@VERSION_SHA "@_VERSION_SHA@" #define @_VERSION_PREFIX@VERSION_SEMANTIC "@_VERSION_SEMANTIC@" #define @_VERSION_PREFIX@VERSION_FULL "@_VERSION_FULL@" +#define @_VERSION_PREFIX@VERSION_DATE "@VERSION_DATE@" +#define @_VERSION_PREFIX@VERSION_DATETIME "@VERSION_DATETIME@" ]=]) if(NOT EXISTS ${VERSION_H_TEMPLATE}) From 0d91e2015f22a2286bc5ea7a7571d4dcd5d4d726 Mon Sep 17 00:00:00 2001 From: hxf0223 Date: Sat, 29 Nov 2025 04:16:10 +0800 Subject: [PATCH 3/3] add log message of datetime at build --- CMake/Version.cmake | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CMake/Version.cmake b/CMake/Version.cmake index ec27fd7..9a1b2bc 100644 --- a/CMake/Version.cmake +++ b/CMake/Version.cmake @@ -45,8 +45,8 @@ set(GIT_COUNT_COMMAND "${GIT_EXECUTABLE}" -C "${VERSION_SOURCE_DIR}" rev-list -- set(GIT_CACHE_PATH_COMMAND "${GIT_EXECUTABLE}" -C "${VERSION_SOURCE_DIR}" rev-parse --git-dir) # Get current date -string(TIMESTAMP VERSION_DATE "%Y-%m-%d" UTC) -string(TIMESTAMP VERSION_DATETIME "%Y-%m-%d %H:%M:%S" UTC) +string(TIMESTAMP VERSION_DATE "%Y-%m-%d") +string(TIMESTAMP VERSION_DATETIME "%Y-%m-%d %H:%M:%S") macro(version_parseSemantic semVer) if("${semVer}" MATCHES "^v?([0-9]+)[._]([0-9]+)[._]?([0-9]+)?[-]([0-9]+)[-][g]([._0-9A-Fa-f]+)[-]?(dirty)?$") @@ -132,6 +132,7 @@ else() if(${_VERSION_SET}) message(CHECK_PASS "Tag '${git_describe}' is a valid semantic version [${_VERSION_SEMANTIC}]") + message(STATUS "Git Datetime: ${VERSION_DATETIME}") else() message(CHECK_FAIL "'${git_describe}' is not a valid semantic-version e.g. 'v0.1.2-30'") endif()