From b18b84df5eab9829ecbef644ef0af226becf881d Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Mon, 30 Sep 2019 00:10:29 +0200 Subject: [PATCH] build: run git-describe for dev version during build (#11117) This avoids invoking CMake after a new commit, which might take 15s on some systems. Skipped on CMake < 3.2.0 (missing BYPRODUCTS support). Co-Authored-By: Justin M. Keyes --- CMakeLists.txt | 13 -- ci/before_install.sh | 2 +- cmake/GetGitRevisionDescription.cmake | 180 ----------------------- cmake/GetGitRevisionDescription.cmake.in | 38 ----- config/CMakeLists.txt | 29 ++++ scripts/update_version_stamp.lua | 45 ++++++ 6 files changed, 75 insertions(+), 232 deletions(-) delete mode 100644 cmake/GetGitRevisionDescription.cmake delete mode 100644 cmake/GetGitRevisionDescription.cmake.in create mode 100644 scripts/update_version_stamp.lua diff --git a/CMakeLists.txt b/CMakeLists.txt index 26c82449b3..83fd67837d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -122,19 +122,6 @@ set(NVIM_API_LEVEL 6) # Bump this after any API change. set(NVIM_API_LEVEL_COMPAT 0) # Adjust this after a _breaking_ API change. set(NVIM_API_PRERELEASE false) -file(TO_CMAKE_PATH ${CMAKE_CURRENT_LIST_DIR}/.git FORCED_GIT_DIR) -include(GetGitRevisionDescription) -get_git_head_revision(GIT_REFSPEC NVIM_VERSION_COMMIT) -if(NVIM_VERSION_COMMIT) # is a git repo - git_describe(NVIM_VERSION_MEDIUM) - # `git describe` annotates the most recent tagged release; for pre-release - # builds we must replace that with the unreleased version. - string(REGEX REPLACE "^v[0-9]+\\.[0-9]+\\.[0-9]+" - "v${NVIM_VERSION_MAJOR}.${NVIM_VERSION_MINOR}.${NVIM_VERSION_PATCH}" - NVIM_VERSION_MEDIUM - ${NVIM_VERSION_MEDIUM}) -endif() - set(NVIM_VERSION_BUILD_TYPE "${CMAKE_BUILD_TYPE}") # NVIM_VERSION_CFLAGS set further below. diff --git a/ci/before_install.sh b/ci/before_install.sh index 5cb6894b8c..283605e113 100755 --- a/ci/before_install.sh +++ b/ci/before_install.sh @@ -52,7 +52,7 @@ nvm use --lts if [[ -n "$CMAKE_URL" ]]; then echo "Installing custom CMake: $CMAKE_URL" - curl --retry 5 --silent --fail -o /tmp/cmake-installer.sh "$CMAKE_URL" + curl --retry 5 --silent --show-error --fail -o /tmp/cmake-installer.sh "$CMAKE_URL" mkdir -p "$HOME/.local/bin" /opt/cmake-custom bash /tmp/cmake-installer.sh --prefix=/opt/cmake-custom --skip-license ln -sfn /opt/cmake-custom/bin/cmake "$HOME/.local/bin/cmake" diff --git a/cmake/GetGitRevisionDescription.cmake b/cmake/GetGitRevisionDescription.cmake deleted file mode 100644 index 5044c682e4..0000000000 --- a/cmake/GetGitRevisionDescription.cmake +++ /dev/null @@ -1,180 +0,0 @@ -# https://github.com/rpavlik/cmake-modules -# -# - Returns a version string from Git -# -# These functions force a re-configure on each git commit so that you can -# trust the values of the variables in your build system. -# -# get_git_head_revision( [ ...]) -# -# Returns the refspec and sha hash of the current head revision -# -# git_describe( [ ...]) -# -# Returns the results of git describe on the source tree, and adjusting -# the output so that it tests false if an error occurs. -# -# git_get_exact_tag( [ ...]) -# -# Returns the results of git describe --exact-match on the source tree, -# and adjusting the output so that it tests false if there was no exact -# matching tag. -# -# Requires CMake 2.6 or newer (uses the 'function' command) -# -# Original Author: -# 2009-2010 Ryan Pavlik -# http://academic.cleardefinition.com -# Iowa State University HCI Graduate Program/VRAC -# -# Copyright Iowa State University 2009-2010. -# Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE_1_0.txt or copy at -# http://www.boost.org/LICENSE_1_0.txt) - -if(__get_git_revision_description) - return() -endif() -set(__get_git_revision_description YES) - -# We must run the following at "include" time, not at function call time, -# to find the path to this module rather than the path to a calling list file -get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH) - -function(get_git_dir _gitdir) - # check FORCED_GIT_DIR first - if(FORCED_GIT_DIR) - set(${_gitdir} ${FORCED_GIT_DIR} PARENT_SCOPE) - return() - endif() - - # check GIT_DIR in environment - set(GIT_DIR $ENV{GIT_DIR}) - if(NOT GIT_DIR) - set(GIT_PARENT_DIR ${CMAKE_CURRENT_SOURCE_DIR}) - set(GIT_DIR ${GIT_PARENT_DIR}/.git) - endif() - # .git dir not found, search parent directories - while(NOT EXISTS ${GIT_DIR}) - set(GIT_PREVIOUS_PARENT ${GIT_PARENT_DIR}) - get_filename_component(GIT_PARENT_DIR ${GIT_PARENT_DIR} PATH) - if(GIT_PARENT_DIR STREQUAL GIT_PREVIOUS_PARENT) - return() - endif() - set(GIT_DIR ${GIT_PARENT_DIR}/.git) - endwhile() - # check if this is a submodule - if(NOT IS_DIRECTORY ${GIT_DIR}) - file(READ ${GIT_DIR} submodule) - string(REGEX REPLACE "gitdir: (.*)\n$" "\\1" GIT_DIR_RELATIVE ${submodule}) - get_filename_component(SUBMODULE_DIR ${GIT_DIR} PATH) - get_filename_component(GIT_DIR ${SUBMODULE_DIR}/${GIT_DIR_RELATIVE} ABSOLUTE) - endif() - set(${_gitdir} ${GIT_DIR} PARENT_SCOPE) -endfunction() - -function(get_git_head_revision _refspecvar _hashvar) - get_git_dir(GIT_DIR) - if(NOT GIT_DIR) - return() - endif() - - set(GIT_DATA ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data) - if(NOT EXISTS ${GIT_DATA}) - file(MAKE_DIRECTORY ${GIT_DATA}) - endif() - - if(NOT EXISTS ${GIT_DIR}/HEAD) - return() - endif() - set(HEAD_FILE ${GIT_DATA}/HEAD) - configure_file(${GIT_DIR}/HEAD ${HEAD_FILE} COPYONLY) - - configure_file(${_gitdescmoddir}/GetGitRevisionDescription.cmake.in - ${GIT_DATA}/grabRef.cmake - @ONLY) - include(${GIT_DATA}/grabRef.cmake) - - set(${_refspecvar} ${HEAD_REF} PARENT_SCOPE) - set(${_hashvar} ${HEAD_HASH} PARENT_SCOPE) -endfunction() - -function(git_describe _var) - get_git_dir(GIT_DIR) - if(NOT GIT_DIR) - return() - endif() - - if(NOT GIT_FOUND) - find_package(Git QUIET) - endif() - if(NOT GIT_FOUND) - set(${_var} "GIT-NOTFOUND" PARENT_SCOPE) - return() - endif() - - get_git_head_revision(refspec hash) - if(NOT hash) - set(${_var} "HEAD-HASH-NOTFOUND" PARENT_SCOPE) - return() - endif() - - execute_process(COMMAND - ${GIT_EXECUTABLE} - describe - ${hash} - ${ARGN} - WORKING_DIRECTORY - ${GIT_DIR} - RESULT_VARIABLE - res - OUTPUT_VARIABLE - out - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) - if(NOT res EQUAL 0) - set(out "${out}-${res}-NOTFOUND") - endif() - - set(${_var} ${out} PARENT_SCOPE) -endfunction() - -function(git_timestamp _var) - get_git_dir(GIT_DIR) - if(NOT GIT_DIR) - return() - endif() - - if(NOT GIT_FOUND) - find_package(Git QUIET) - endif() - if(NOT GIT_FOUND) - return() - endif() - - get_git_head_revision(refspec hash) - if(NOT hash) - set(${_var} "HEAD-HASH-NOTFOUND" PARENT_SCOPE) - return() - endif() - - execute_process(COMMAND ${GIT_EXECUTABLE} log -1 --format="%ci" ${hash} ${ARGN} - WORKING_DIRECTORY ${GIT_DIR} - RESULT_VARIABLE res - OUTPUT_VARIABLE out - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) - if(res EQUAL 0) - string(REGEX REPLACE "[-\" :]" "" out ${out}) - string(SUBSTRING ${out} 0 12 out) - else() - set(out "${out}-${res}-NOTFOUND") - endif() - - set(${_var} ${out} PARENT_SCOPE) -endfunction() - -function(git_get_exact_tag _var) - git_describe(out --exact-match ${ARGN}) - set(${_var} ${out} PARENT_SCOPE) -endfunction() diff --git a/cmake/GetGitRevisionDescription.cmake.in b/cmake/GetGitRevisionDescription.cmake.in deleted file mode 100644 index 8a085b2671..0000000000 --- a/cmake/GetGitRevisionDescription.cmake.in +++ /dev/null @@ -1,38 +0,0 @@ -# -# Internal file for GetGitRevisionDescription.cmake -# -# Requires CMake 2.6 or newer (uses the 'function' command) -# -# Original Author: -# 2009-2010 Ryan Pavlik -# http://academic.cleardefinition.com -# Iowa State University HCI Graduate Program/VRAC -# -# Copyright Iowa State University 2009-2010. -# Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE_1_0.txt or copy at -# http://www.boost.org/LICENSE_1_0.txt) - -set(HEAD_HASH) - -file(READ "@HEAD_FILE@" HEAD_CONTENTS LIMIT 1024) - -string(STRIP "${HEAD_CONTENTS}" HEAD_CONTENTS) -if(HEAD_CONTENTS MATCHES "ref") - # named branch - string(REPLACE "ref: " "" HEAD_REF "${HEAD_CONTENTS}") - if(EXISTS "@GIT_DIR@/${HEAD_REF}") - configure_file("@GIT_DIR@/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY) - elseif(EXISTS "@GIT_DIR@/logs/${HEAD_REF}") - configure_file("@GIT_DIR@/logs/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY) - set(HEAD_HASH "${HEAD_REF}") - endif() -else() - # detached HEAD - configure_file("@GIT_DIR@/HEAD" "@GIT_DATA@/head-ref" COPYONLY) -endif() - -if(NOT HEAD_HASH) - file(READ "@GIT_DATA@/head-ref" HEAD_HASH LIMIT 1024) - string(STRIP "${HEAD_HASH}" HEAD_HASH) -endif() diff --git a/config/CMakeLists.txt b/config/CMakeLists.txt index 0ca41d5dfd..7bd48a1f1e 100644 --- a/config/CMakeLists.txt +++ b/config/CMakeLists.txt @@ -121,6 +121,35 @@ configure_file ( ) # generate version definitions +if(NVIM_VERSION_MEDIUM) + message(STATUS "NVIM_VERSION_MEDIUM: ${NVIM_VERSION_MEDIUM}") +elseif(${CMAKE_VERSION} VERSION_LESS "3.2.0") + message(STATUS "Skipping version-string generation (requires CMake 3.2.0+)") +elseif(EXISTS ${PROJECT_SOURCE_DIR}/.git) + find_program(GIT_EXECUTABLE git) + if(GIT_EXECUTABLE) + # Get current version. + execute_process( + COMMAND ${GIT_EXECUTABLE} describe --dirty + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} + OUTPUT_VARIABLE NVIM_VERSION_MEDIUM + OUTPUT_STRIP_TRAILING_WHITESPACE) + message(STATUS "NVIM_VERSION_MEDIUM (from git): ${NVIM_VERSION_MEDIUM}") + + # Create a update_version_stamp target to update the version during build. + file(RELATIVE_PATH relbuild "${PROJECT_SOURCE_DIR}" "${CMAKE_BINARY_DIR}") + add_custom_target(update_version_stamp ALL + COMMAND ${LUA_PRG} scripts/update_version_stamp.lua + ${relbuild}/.version_stamp + ${relbuild}/config/auto/versiondef.h + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} + BYPRODUCTS ${CMAKE_BINARY_DIR}/config/auto/versiondef.h) + add_dependencies(nvim update_version_stamp) + else() + message(STATUS "Skipping version-string generation (cannot find git)") + endif() +endif() + configure_file ( "${PROJECT_SOURCE_DIR}/config/versiondef.h.in" "${PROJECT_BINARY_DIR}/config/auto/versiondef.h" diff --git a/scripts/update_version_stamp.lua b/scripts/update_version_stamp.lua new file mode 100644 index 0000000000..f01642043a --- /dev/null +++ b/scripts/update_version_stamp.lua @@ -0,0 +1,45 @@ +#!/usr/bin/env lua +-- +-- Script to update the Git version stamp during build. +-- This is called via the custom update_version_stamp target in +-- src/nvim/CMakeLists.txt. +-- +-- arg[1]: file containing the last git-describe output +-- arg[2]: file in which to update the version string + +local function die(msg) + print(string.format('%s: %s', arg[0], msg)) + -- No error, fall back to using generated "-dev" version. + os.exit(0) +end + +if #arg ~= 2 then + die(string.format("Expected two args, got %d", #arg)) +end + +local stampfile = arg[1] +local stamp = io.open(stampfile, 'r') +if stamp then + stamp = stamp:read('*l') +end + +local current = io.popen('git describe --dirty'):read('*l') +if not current then + die('git-describe failed') +end + +if stamp ~= current then + if stamp then + print(string.format('git version changed: %s -> %s', stamp, current)) + end + local new_lines = {} + local versiondeffile = arg[2] + for line in io.lines(versiondeffile) do + if line:match("NVIM_VERSION_MEDIUM") then + line = '#define NVIM_VERSION_MEDIUM "'..current..'"' + end + new_lines[#new_lines + 1] = line + end + io.open(versiondeffile, 'w'):write(table.concat(new_lines, '\n') .. '\n') + io.open(stampfile, 'w'):write(current) +end