summaryrefslogtreecommitdiff
path: root/cmake
diff options
context:
space:
mode:
authorJoel Rosdahl <joel@rosdahl.net>2020-09-30 17:13:48 +0200
committerJoel Rosdahl <joel@rosdahl.net>2020-10-01 09:45:54 +0200
commit3c33c79548874e97a3553bf6943c89638326e6f2 (patch)
tree102a40c595039db713dfc045cf49d977e761913e /cmake
parent2bcea18451b3f2d1114435f4b42cc42afde5aaa8 (diff)
downloadccache-3c33c79548874e97a3553bf6943c89638326e6f2.tar.gz
Make it possible to build from “git archive” source archives
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.
Diffstat (limited to 'cmake')
-rw-r--r--cmake/.gitattributes1
-rw-r--r--cmake/CcacheVersion.cmake66
-rw-r--r--cmake/GenerateVersionFile.cmake54
3 files changed, 68 insertions, 53 deletions
diff --git a/cmake/.gitattributes b/cmake/.gitattributes
new file mode 100644
index 00000000..c217b7df
--- /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 00000000..ee338168
--- /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 37baa9ee..66a86b37 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(