From 3c33c79548874e97a3553bf6943c89638326e6f2 Mon Sep 17 00:00:00 2001 From: Joel Rosdahl Date: Wed, 30 Sep 2020 17:13:48 +0200 Subject: [PATCH] =?utf8?q?Make=20it=20possible=20to=20build=20from=20?= =?utf8?q?=E2=80=9Cgit=20archive=E2=80=9D=20source=20archives?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit The ccache CMake scripts currently support building from an official release archive or in a Git repository but not from a source archive created by “git archive”. Improve this by adding directives so that “git archive” substitutes needed information when exporting the source tree. Closes #667. --- cmake/.gitattributes | 1 + cmake/CcacheVersion.cmake | 66 +++++++++++++++++++++++++++++++++ cmake/GenerateVersionFile.cmake | 54 +-------------------------- 3 files changed, 68 insertions(+), 53 deletions(-) create mode 100644 cmake/.gitattributes create mode 100644 cmake/CcacheVersion.cmake diff --git a/cmake/.gitattributes b/cmake/.gitattributes new file mode 100644 index 000000000..c217b7df9 --- /dev/null +++ b/cmake/.gitattributes @@ -0,0 +1 @@ +CcacheVersion.cmake export-subst diff --git a/cmake/CcacheVersion.cmake b/cmake/CcacheVersion.cmake new file mode 100644 index 000000000..ee3381683 --- /dev/null +++ b/cmake/CcacheVersion.cmake @@ -0,0 +1,66 @@ +# There are four main scenarios: +# +# 1. Building from an official source code release archive. In this case the +# version is unconditionally read from the file VERSION in the top level +# directory and the code below won't be executed. +# 2. Building from an unofficial source code archive generated by "git +# archive", e.g. from a GitHub "archive download" +# (https://github.com/ccache/ccache/archive/$VERSION.tar.gz). In this case +# the version_info info string below will be substituted because of +# export-subst in the .gitattributes file. The version will then be correct +# if $VERSION refers to a tagged commit. If the commit is not tagged the +# version will be set to the commit hash instead. +# 3. Building from an unofficial source code archive not generated by "git +# archive" (i.e., version_info has not been substituted). In this case we +# fail the configuration. +# 4. Building from a Git repository. In this case the version will be a proper +# version if building a tagged commit, otherwise "branch.hash(+dirty)". + +set(version_info "$Format:%H %D$") + +if(version_info MATCHES "^([0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f])[0-9a-f]* (.*)") + # Scenario 2. + set(hash "${CMAKE_MATCH_1}") + set(ref_names "${CMAKE_MATCH_2}") + if(ref_names MATCHES "tag: v([^,]+)") + # Tagged commit. + set(VERSION "${CMAKE_MATCH_1}") + else() + # Untagged commit. + set(VERSION "${hash}") + endif() +elseif(EXISTS "${CMAKE_SOURCE_DIR}/.git") + # Scenario 4. + find_package(Git QUIET) + if(NOT GIT_FOUND) + message(SEND_ERROR "Could not find git") + endif() + + macro(git) + execute_process( + COMMAND "${GIT_EXECUTABLE}" ${ARGN} + OUTPUT_VARIABLE git_stdout OUTPUT_STRIP_TRAILING_WHITESPACE) + endmacro() + + git(describe --abbrev=8 --dirty) + if(git_stdout MATCHES "^v([^-]+)(-dirty)?$") + set(VERSION "${CMAKE_MATCH_1}") + if(NOT "${CMAKE_MATCH_2}" STREQUAL "") + set(VERSION "${VERSION}+dirty") + endif() + elseif(git_stdout MATCHES "^v[^-]+-[0-9]+-g([0-9a-f]+)(-dirty)?$") + set(hash "${CMAKE_MATCH_1}") + set(dirty "${CMAKE_MATCH_2}") + string(REPLACE "-" "+" dirty "${dirty}") + + git(rev-parse --abbrev-ref HEAD) + set(branch "${git_stdout}") + + set(VERSION "${branch}.${hash}${dirty}") + endif() # else: fail below +endif() + +if(VERSION STREQUAL "") + # Scenario 3 or unexpected error. + message(SEND_ERROR "Cannot determine Ccache version") +endif() diff --git a/cmake/GenerateVersionFile.cmake b/cmake/GenerateVersionFile.cmake index 37baa9ee5..66a86b37d 100644 --- a/cmake/GenerateVersionFile.cmake +++ b/cmake/GenerateVersionFile.cmake @@ -1,62 +1,10 @@ -# Determine VERSION from a Git repository. VERSION_ERROR is set to a non-empty -# string on error. -function(get_version_from_git) - set(VERSION_ERROR "" PARENT_SCOPE) - - find_package(Git) - if(NOT GIT_FOUND) - set(VERSION_ERROR "Git not found" PARENT_SCOPE) - return() - endif() - - execute_process( - COMMAND git describe --exact-match - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} - OUTPUT_VARIABLE git_tag - ERROR_VARIABLE git_tag_error # silence error - RESULT_VARIABLE cmd_result - OUTPUT_STRIP_TRAILING_WHITESPACE) - - if(cmd_result EQUAL 0) - set(VERSION ${git_tag} PARENT_SCOPE) - return() - endif() - - execute_process( - COMMAND git rev-parse --abbrev-ref HEAD - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} - OUTPUT_VARIABLE git_branch OUTPUT_STRIP_TRAILING_WHITESPACE - ERROR_VARIABLE git_branch_error - RESULT_VARIABLE cmd_branch_result) - if(NOT cmd_branch_result EQUAL 0) - set(VERSION_ERROR "Failed to run Git: ${git_branch_error}" PARENT_SCOPE) - return() - endif() - - execute_process( - COMMAND git rev-parse --short=8 HEAD - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} - OUTPUT_VARIABLE git_hash OUTPUT_STRIP_TRAILING_WHITESPACE - ERROR_VARIABLE git_hash_error - RESULT_VARIABLE cmd_hash_result) - if(NOT cmd_hash_result EQUAL 0) - set(VERSION_ERROR "Failed to run Git: ${git_hash_error}" PARENT_SCOPE) - return() - endif() - - set(VERSION "${git_branch}.${git_hash}" PARENT_SCOPE) -endfunction() - set(version_file ${CMAKE_SOURCE_DIR}/VERSION) if(EXISTS ${version_file}) file(READ ${version_file} VERSION) string(STRIP ${VERSION} VERSION) else() - get_version_from_git() - if(NOT ${VERSION_ERROR} STREQUAL "") - message(SEND_ERROR "Cannot determine ccache version: ${VERSION_ERROR}") - endif() + include(CcacheVersion) endif() configure_file( -- 2.47.3