]> git.ipfire.org Git - thirdparty/ccache.git/commitdiff
Make it possible to build from “git archive” source archives
authorJoel Rosdahl <joel@rosdahl.net>
Wed, 30 Sep 2020 15:13:48 +0000 (17:13 +0200)
committerJoel Rosdahl <joel@rosdahl.net>
Thu, 1 Oct 2020 07:45:54 +0000 (09:45 +0200)
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 [new file with mode: 0644]
cmake/CcacheVersion.cmake [new file with mode: 0644]
cmake/GenerateVersionFile.cmake

diff --git a/cmake/.gitattributes b/cmake/.gitattributes
new file mode 100644 (file)
index 0000000..c217b7d
--- /dev/null
@@ -0,0 +1 @@
+CcacheVersion.cmake export-subst
diff --git a/cmake/CcacheVersion.cmake b/cmake/CcacheVersion.cmake
new file mode 100644 (file)
index 0000000..ee33816
--- /dev/null
@@ -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()
index 37baa9ee526a8e94f8b99504327cc36dcf95c1a0..66a86b37dc5a82c1452fd3b43ac1d4eab0dd6af8 100644 (file)
@@ -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(