From ab4bf2d7f09326b8d6be6cf065b35c588c996e20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9B=D0=B5=D0=BE=D0=BD=D0=B8=D0=B4=20=D0=AE=D1=80=D1=8C?= =?UTF-8?q?=D0=B5=D0=B2=20=28Leonid=20Yuriev=29?= Date: Tue, 12 Nov 2024 12:25:51 +0300 Subject: [PATCH] =?UTF-8?q?mdbx-cmake:=20=D1=8D=D0=BA=D1=81=D0=BF=D0=BE?= =?UTF-8?q?=D1=80=D1=82/=D0=B8=D0=BC=D0=BF=D0=BE=D1=80=D1=82=20=D0=B8?= =?UTF-8?q?=D0=BD=D1=84=D0=BE=D1=80=D0=BC=D0=B0=D1=86=D0=B8=D0=B8=20=D0=BE?= =?UTF-8?q?=20=D0=B2=D0=B5=D1=80=D1=81=D0=B8=D0=B8=20=D0=B2=20`VERSION.jso?= =?UTF-8?q?n`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 2 +- cmake/utils.cmake | 311 +++++++++++++++++++++++++++++----------------- 2 files changed, 197 insertions(+), 116 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c2ce48e0..7a0adb35 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -677,7 +677,7 @@ if(MDBX_BUILD_CXX) endif() # Get version -fetch_version(MDBX "${CMAKE_CURRENT_SOURCE_DIR}" FALSE) +fetch_version(MDBX "${CMAKE_CURRENT_SOURCE_DIR}" FALSE "${CMAKE_CURRENT_BINARY_DIR}") message(STATUS "libmdbx version is ${MDBX_VERSION}") # sources list diff --git a/cmake/utils.cmake b/cmake/utils.cmake index 164ce8eb..0348d96d 100644 --- a/cmake/utils.cmake +++ b/cmake/utils.cmake @@ -73,201 +73,282 @@ macro(set_source_files_compile_flags) unset(_lang) endmacro(set_source_files_compile_flags) -macro(fetch_version name source_root_directory parent_scope) - set(${name}_VERSION "") - set(${name}_GIT_DESCRIBE "") - set(${name}_GIT_TIMESTAMP "") - set(${name}_GIT_TREE "") - set(${name}_GIT_COMMIT "") - set(${name}_GIT_REVISION 0) - set(${name}_GIT_VERSION "") - if(GIT AND EXISTS "${source_root_directory}/.git") - execute_process(COMMAND ${GIT} show --no-patch --format=%cI HEAD - OUTPUT_VARIABLE ${name}_GIT_TIMESTAMP +macro(fetch_version name source_root_directory parent_scope build_directory_for_json_output) + set(_version_4dot "") + set(_git_describe "") + set(_git_timestamp "") + set(_git_tree "") + set(_git_commit "") + set(_git_revision 0) + set(_git_version "") + set(_version_from "") + set(_git_root FALSE) + + find_program(GIT git) + if(GIT) + execute_process(COMMAND ${GIT} rev-parse --show-toplevel + OUTPUT_VARIABLE _git_root + ERROR_VARIABLE _git_root_error OUTPUT_STRIP_TRAILING_WHITESPACE WORKING_DIRECTORY ${source_root_directory} - RESULT_VARIABLE rc) - if(rc OR "${name}_GIT_TIMESTAMP" STREQUAL "%cI") + RESULT_VARIABLE _rc) + if(_rc OR _git_root STREQUAL "") + if(EXISTS "${source_root_directory}/.git") + message(ERROR "`git rev-parse --show-toplevel` failed '${_git_root_error}'") + else() + message(VERBOSE "`git rev-parse --show-toplevel` failed '${_git_root_error}'") + endif() + else() + set(_source_root "${source_root_directory}") + if(NOT CMAKE_VERSION VERSION_LESS 3.20) + cmake_path(NORMAL_PATH _git_root) + cmake_path(NORMAL_PATH _source_root) + endif() + if(_source_root STREQUAL _git_root AND EXISTS "${_git_root}/VERSION.json") + message(FATAL_ERROR "Несколько источников информации о версии, допустим только один из: репозиторий git, либо файл VERSION.json") + endif() + endif() + endif() + + if(EXISTS "${source_root_directory}/VERSION.json") + set(_version_from "${source_root_directory}/VERSION.json") + + if(CMAKE_VERSION VERSION_LESS 3.19) + message(FATAL_ERROR "Требуется CMake версии >= 3.19 для чтения VERSION.json") + endif() + file(STRINGS "${_version_from}" _versioninfo_json NEWLINE_CONSUME LIMIT_COUNT 9 LIMIT_INPUT 999 ENCODING UTF-8) + string(JSON _git_describe GET ${_versioninfo_json} git_describe) + string(JSON _git_timestamp GET "${_versioninfo_json}" "git_timestamp") + string(JSON _git_tree GET "${_versioninfo_json}" "git_tree") + string(JSON _git_commit GET "${_versioninfo_json}" "git_commit") + string(JSON _version_4dot GET "${_versioninfo_json}" "version_4dot") + unset(_json_object) + string(REPLACE "." ";" _version_list "${_version_4dot}") + + if(NOT _version_4dot) + message(ERROR "Unable to retrieve ${name} version from \"${_version_from}\" file.") + set(_version_list ${_git_version}) + string(REPLACE ";" "." _version_4dot "${_git_version}") + else() + string(REPLACE "." ";" _version_list ${_version_4dot}) + endif() + + elseif(_git_root AND _source_root STREQUAL _git_root) + set(_version_from git) + + execute_process(COMMAND ${GIT} show --no-patch --format=%cI HEAD + OUTPUT_VARIABLE _git_timestamp + OUTPUT_STRIP_TRAILING_WHITESPACE + WORKING_DIRECTORY ${source_root_directory} + RESULT_VARIABLE _rc) + if(_rc OR _git_timestamp STREQUAL "%cI") execute_process(COMMAND ${GIT} show --no-patch --format=%ci HEAD - OUTPUT_VARIABLE ${name}_GIT_TIMESTAMP + OUTPUT_VARIABLE _git_timestamp OUTPUT_STRIP_TRAILING_WHITESPACE WORKING_DIRECTORY ${source_root_directory} - RESULT_VARIABLE rc) - if(rc OR "${name}_GIT_TIMESTAMP" STREQUAL "%ci") + RESULT_VARIABLE _rc) + if(_rc OR _git_timestamp STREQUAL "%ci") message(FATAL_ERROR "Please install latest version of git (`show --no-patch --format=%cI HEAD` failed)") endif() endif() execute_process(COMMAND ${GIT} show --no-patch --format=%T HEAD - OUTPUT_VARIABLE ${name}_GIT_TREE + OUTPUT_VARIABLE _git_tree OUTPUT_STRIP_TRAILING_WHITESPACE WORKING_DIRECTORY ${source_root_directory} - RESULT_VARIABLE rc) - if(rc OR "${name}_GIT_TREE" STREQUAL "") + RESULT_VARIABLE _rc) + if(_rc OR _git_tree STREQUAL "") message(FATAL_ERROR "Please install latest version of git (`show --no-patch --format=%T HEAD` failed)") endif() execute_process(COMMAND ${GIT} show --no-patch --format=%H HEAD - OUTPUT_VARIABLE ${name}_GIT_COMMIT + OUTPUT_VARIABLE _git_commit OUTPUT_STRIP_TRAILING_WHITESPACE WORKING_DIRECTORY ${source_root_directory} - RESULT_VARIABLE rc) - if(rc OR "${name}_GIT_COMMIT" STREQUAL "") + RESULT_VARIABLE _rc) + if(_rc OR _git_commit STREQUAL "") message(FATAL_ERROR "Please install latest version of git (`show --no-patch --format=%H HEAD` failed)") endif() - execute_process(COMMAND ${GIT} rev-list --tags --count - OUTPUT_VARIABLE tag_count + execute_process(COMMAND ${GIT} status --untracked-files=no --porcelain + OUTPUT_VARIABLE _git_status OUTPUT_STRIP_TRAILING_WHITESPACE WORKING_DIRECTORY ${source_root_directory} - RESULT_VARIABLE rc) - if(rc) + RESULT_VARIABLE _rc) + if(_rc) + message(FATAL_ERROR "Please install latest version of git (`status --untracked-files=no --porcelain` failed)") + endif() + if(NOT _git_status STREQUAL "") + set(_git_commit "${_git_commit}-dirty") + endif() + unset(_git_status) + + execute_process(COMMAND ${GIT} rev-list --tags --count + OUTPUT_VARIABLE _tag_count + OUTPUT_STRIP_TRAILING_WHITESPACE + WORKING_DIRECTORY ${source_root_directory} + RESULT_VARIABLE _rc) + if(_rc) message(FATAL_ERROR "Please install latest version of git (`git rev-list --tags --count` failed)") endif() - if(tag_count EQUAL 0) + if(_tag_count EQUAL 0) execute_process(COMMAND ${GIT} rev-list --all --count - OUTPUT_VARIABLE whole_count + OUTPUT_VARIABLE _whole_count OUTPUT_STRIP_TRAILING_WHITESPACE WORKING_DIRECTORY ${source_root_directory} - RESULT_VARIABLE rc) - if(rc) + RESULT_VARIABLE _rc) + if(_rc) message(FATAL_ERROR "Please install latest version of git (`git rev-list --all --count` failed)") endif() - if(whole_count GREATER 42) - message(FATAL_ERROR "Please fetch tags (no any tags for ${whole_count} commits)") + if(_whole_count GREATER 42) + message(FATAL_ERROR "Please fetch tags (no any tags for ${_whole_count} commits)") endif() - set(${name}_GIT_VERSION "0;0;0") + set(_git_version "0;0;0") execute_process(COMMAND ${GIT} rev-list --count --all --no-merges - OUTPUT_VARIABLE ${name}_GIT_REVISION + OUTPUT_VARIABLE _git_revision OUTPUT_STRIP_TRAILING_WHITESPACE WORKING_DIRECTORY ${source_root_directory} - RESULT_VARIABLE rc) - if(rc OR "${name}_GIT_REVISION" STREQUAL "") + RESULT_VARIABLE _rc) + if(_rc OR _git_revision STREQUAL "") message(FATAL_ERROR "Please install latest version of git (`rev-list --count --all --no-merges` failed)") endif() - else(tag_count EQUAL 0) + else(_tag_count EQUAL 0) execute_process(COMMAND ${GIT} describe --tags --long --dirty=-dirty "--match=v[0-9]*" - OUTPUT_VARIABLE ${name}_GIT_DESCRIBE + OUTPUT_VARIABLE _git_describe OUTPUT_STRIP_TRAILING_WHITESPACE WORKING_DIRECTORY ${source_root_directory} - RESULT_VARIABLE rc) - if(rc OR "${name}_GIT_DESCRIBE" STREQUAL "") + RESULT_VARIABLE _rc) + if(_rc OR _git_describe STREQUAL "") + execute_process(COMMAND ${GIT} rev-list --all --count + OUTPUT_VARIABLE _whole_count + OUTPUT_STRIP_TRAILING_WHITESPACE + WORKING_DIRECTORY ${source_root_directory} + RESULT_VARIABLE _rc) + if(_rc) + message(FATAL_ERROR "Please install latest version of git (`git rev-list --all --count` failed)") + endif() if(_whole_count GREATER 42) message(FATAL_ERROR "Please fetch tags (`describe --tags --long --dirty --match=v[0-9]*` failed)") else() execute_process(COMMAND ${GIT} describe --all --long --dirty=-dirty - OUTPUT_VARIABLE ${name}_GIT_DESCRIBE + OUTPUT_VARIABLE _git_describe OUTPUT_STRIP_TRAILING_WHITESPACE WORKING_DIRECTORY ${source_root_directory} - RESULT_VARIABLE rc) - if(rc OR "${name}_GIT_DESCRIBE" STREQUAL "") + RESULT_VARIABLE _rc) + if(_rc OR _git_describe STREQUAL "") message(FATAL_ERROR "Please install latest version of git (`git rev-list --tags --count` and/or `git rev-list --all --count` failed)") endif() endif() endif() execute_process(COMMAND ${GIT} describe --tags --abbrev=0 "--match=v[0-9]*" - OUTPUT_VARIABLE last_release_tag + OUTPUT_VARIABLE _last_release_tag OUTPUT_STRIP_TRAILING_WHITESPACE WORKING_DIRECTORY ${source_root_directory} - RESULT_VARIABLE rc) - if(rc) + RESULT_VARIABLE _rc) + if(_rc) message(FATAL_ERROR "Please install latest version of git (`describe --tags --abbrev=0 --match=v[0-9]*` failed)") endif() - if (last_release_tag) - set(git_revlist_arg "${last_release_tag}..HEAD") + if (_last_release_tag) + set(_git_revlist_arg "${_last_release_tag}..HEAD") else() execute_process(COMMAND ${GIT} tag --sort=-version:refname - OUTPUT_VARIABLE tag_list + OUTPUT_VARIABLE _tag_list OUTPUT_STRIP_TRAILING_WHITESPACE WORKING_DIRECTORY ${source_root_directory} - RESULT_VARIABLE rc) - if(rc) + RESULT_VARIABLE _rc) + if(_rc) message(FATAL_ERROR "Please install latest version of git (`tag --sort=-version:refname` failed)") endif() - string(REGEX REPLACE "\n" ";" tag_list "${tag_list}") - set(git_revlist_arg "HEAD") - foreach(tag IN LISTS tag_list) - if(NOT last_release_tag) - string(REGEX MATCH "^v[0-9]+(\.[0-9]+)+" last_release_tag "${tag}") - set(git_revlist_arg "${tag}..HEAD") + string(REGEX REPLACE "\n" ";" _tag_list "${_tag_list}") + set(_git_revlist_arg "HEAD") + foreach(_tag IN LISTS _tag_list) + if(NOT _last_release_tag) + string(REGEX MATCH "^v[0-9]+(\.[0-9]+)+" _last_release_tag "${_tag}") + set(_git_revlist_arg "${_tag}..HEAD") endif() - endforeach(tag) + endforeach(_tag) endif() - execute_process(COMMAND ${GIT} rev-list --count "${git_revlist_arg}" - OUTPUT_VARIABLE ${name}_GIT_REVISION + execute_process(COMMAND ${GIT} rev-list --count "${_git_revlist_arg}" + OUTPUT_VARIABLE _git_revision OUTPUT_STRIP_TRAILING_WHITESPACE WORKING_DIRECTORY ${source_root_directory} - RESULT_VARIABLE rc) - if(rc OR "${name}_GIT_REVISION" STREQUAL "") - message(FATAL_ERROR "Please install latest version of git (`rev-list --count ${git_revlist_arg}` failed)") + RESULT_VARIABLE _rc) + if(_rc OR _git_revision STREQUAL "") + message(FATAL_ERROR "Please install latest version of git (`rev-list --count ${_git_revlist_arg}` failed)") endif() - string(REGEX MATCH "^(v)?([0-9]+)\\.([0-9]+)\\.([0-9]+)(.*)?" git_version_valid "${${name}_GIT_DESCRIBE}") - if(git_version_valid) - string(REGEX REPLACE "^(v)?([0-9]+)\\.([0-9]+)\\.([0-9]+)(.*)?" "\\2;\\3;\\4" ${name}_GIT_VERSION ${${name}_GIT_DESCRIBE}) + string(REGEX MATCH "^(v)?([0-9]+)\\.([0-9]+)\\.([0-9]+)(.*)?" _git_version_valid "${_git_describe}") + if(_git_version_valid) + string(REGEX REPLACE "^(v)?([0-9]+)\\.([0-9]+)\\.([0-9]+)(.*)?" "\\2;\\3;\\4" _git_version ${_git_describe}) else() - string(REGEX MATCH "^(v)?([0-9]+)\\.([0-9]+)(.*)?" git_version_valid "${${name}_GIT_DESCRIBE}") - if(git_version_valid) - string(REGEX REPLACE "^(v)?([0-9]+)\\.([0-9]+)(.*)?" "\\2;\\3;0" ${name}_GIT_VERSION ${${name}_GIT_DESCRIBE}) + string(REGEX MATCH "^(v)?([0-9]+)\\.([0-9]+)(.*)?" _git_version_valid "${_git_describe}") + if(_git_version_valid) + string(REGEX REPLACE "^(v)?([0-9]+)\\.([0-9]+)(.*)?" "\\2;\\3;0" _git_version ${_git_describe}) else() - message(AUTHOR_WARNING "Bad ${name} version \"${${name}_GIT_DESCRIBE}\"; falling back to 0.0.0 (have you made an initial release?)") - set(${name}_GIT_VERSION "0;0;0") + message(AUTHOR_WARNING "Bad ${name} version \"${_git_describe}\"; falling back to 0.0.0 (have you made an initial release?)") + set(_git_version "0;0;0") endif() endif() - endif(tag_count EQUAL 0) - endif() + endif(_tag_count EQUAL 0) - if(NOT ${name}_GIT_VERSION OR NOT ${name}_GIT_TIMESTAMP OR ${name}_GIT_REVISION STREQUAL "") - if(GIT AND EXISTS "${source_root_directory}/.git") - message(WARNING "Unable to retrieve ${name} version from git.") - endif() - set(${name}_GIT_VERSION "0;0;0;0") - set(${name}_GIT_TIMESTAMP "") - set(${name}_GIT_REVISION 0) - - # Try to get version from VERSION file - set(version_file "${source_root_directory}/VERSION.txt") - if(NOT EXISTS "${version_file}") - set(version_file "${source_root_directory}/VERSION") - endif() - if(EXISTS "${version_file}") - file(STRINGS "${version_file}" ${name}_VERSION LIMIT_COUNT 1 LIMIT_INPUT 42) - endif() - - if(NOT ${name}_VERSION) - message(WARNING "Unable to retrieve ${name} version from \"${version_file}\" file.") - set(${name}_VERSION_LIST ${${name}_GIT_VERSION}) - string(REPLACE ";" "." ${name}_VERSION "${${name}_GIT_VERSION}") - else() - string(REPLACE "." ";" ${name}_VERSION_LIST ${${name}_VERSION}) - endif() + list(APPEND _git_version "${_git_revision}") + set(_version_list "${_git_version}") + string(REPLACE ";" "." _version_4dot "${_version_list}") + elseif(GIT) + message(FATAL_ERROR "Нет источника информации о версии (${source_root_directory}), требуется один из: репозиторий git, либо VERSION.json") else() - list(APPEND ${name}_GIT_VERSION ${${name}_GIT_REVISION}) - set(${name}_VERSION_LIST ${${name}_GIT_VERSION}) - string(REPLACE ";" "." ${name}_VERSION "${${name}_GIT_VERSION}") + message(FATAL_ERROR "Требуется git для получения информации о версии") endif() - list(GET ${name}_VERSION_LIST 0 "${name}_VERSION_MAJOR") - list(GET ${name}_VERSION_LIST 1 "${name}_VERSION_MINOR") - list(GET ${name}_VERSION_LIST 2 "${name}_VERSION_RELEASE") - list(GET ${name}_VERSION_LIST 3 "${name}_VERSION_REVISION") + list(LENGTH _version_list _version_list_length) + list(GET _version_list 0 _version_major) + list(GET _version_list 1 _version_minor) + list(GET _version_list 2 _version_release) + list(GET _version_list 3 _version_revision) + + if(NOT _git_describe OR NOT _git_timestamp OR NOT _git_tree OR NOT _git_commit OR _git_revision STREQUAL "" OR NOT _version_list_length EQUAL 4 OR _version_major STREQUAL "" OR _version_minor STREQUAL "" OR _version_release STREQUAL "" OR _version_revision STREQUAL "") + message(ERROR "Unable to retrieve ${name} version from ${_version_from}.") + else() + list(APPEND _git_version "${_git_revision}") + endif() if(${parent_scope}) - set(${name}_VERSION_MAJOR "${${name}_VERSION_MAJOR}" PARENT_SCOPE) - set(${name}_VERSION_MINOR "${${name}_VERSION_MINOR}" PARENT_SCOPE) - set(${name}_VERSION_RELEASE "${${name}_VERSION_RELEASE}" PARENT_SCOPE) - set(${name}_VERSION_REVISION "${${name}_VERSION_REVISION}" PARENT_SCOPE) - set(${name}_VERSION "${${name}_VERSION}" PARENT_SCOPE) + set(${name}_VERSION_MAJOR "${_version_major}" PARENT_SCOPE) + set(${name}_VERSION_MINOR "${_version_minor}" PARENT_SCOPE) + set(${name}_VERSION_RELEASE "${_version_release}" PARENT_SCOPE) + set(${name}_VERSION_REVISION "${_version_revision}" PARENT_SCOPE) + set(${name}_VERSION "${_version_4dot}" PARENT_SCOPE) - set(${name}_GIT_DESCRIBE "${${name}_GIT_DESCRIBE}" PARENT_SCOPE) - set(${name}_GIT_TIMESTAMP "${${name}_GIT_TIMESTAMP}" PARENT_SCOPE) - set(${name}_GIT_TREE "${${name}_GIT_TREE}" PARENT_SCOPE) - set(${name}_GIT_COMMIT "${${name}_GIT_COMMIT}" PARENT_SCOPE) - set(${name}_GIT_REVISION "${${name}_GIT_REVISION}" PARENT_SCOPE) - set(${name}_GIT_VERSION "${${name}_GIT_VERSION}" PARENT_SCOPE) + set(${name}_GIT_DESCRIBE "${_git_describe}" PARENT_SCOPE) + set(${name}_GIT_TIMESTAMP "${_git_timestamp}" PARENT_SCOPE) + set(${name}_GIT_TREE "${_git_tree}" PARENT_SCOPE) + set(${name}_GIT_COMMIT "${_git_commit}" PARENT_SCOPE) + set(${name}_GIT_REVISION "${_git_revision}" PARENT_SCOPE) + else() + set(${name}_VERSION_MAJOR "${_version_major}") + set(${name}_VERSION_MINOR "${_version_minor}") + set(${name}_VERSION_RELEASE "${_version_release}") + set(${name}_VERSION_REVISION "${_version_revision}") + set(${name}_VERSION "${_version_4dot}") + + set(${name}_GIT_DESCRIBE "${_git_describe}") + set(${name}_GIT_TIMESTAMP "${_git_timestamp}") + set(${name}_GIT_TREE "${_git_tree}") + set(${name}_GIT_COMMIT "${_git_commit}") + set(${name}_GIT_REVISION "${_git_revision}") + endif() + + if(_version_from STREQUAL "git") + string(CONFIGURE "{ + \"git_describe\" : \"@_git_describe@\", + \"git_timestamp\" : \"@_git_timestamp@\", + \"git_tree\" : \"@_git_tree@\", + \"git_commit\" : \"@_git_commit@\", + \"version_4dot\" : \"@_version_4dot@\"\n}" _versioninfo_json @ONLY ESCAPE_QUOTES) + file(WRITE "${build_directory_for_json_output}/VERSION.json" "${_versioninfo_json}") endif() endmacro(fetch_version)