From 7f3eb7bb906c397900a99ba05eb8797f9241cb44 Mon Sep 17 00:00:00 2001 From: Eric Kilmer Date: Mon, 25 Apr 2022 18:07:28 -0400 Subject: [PATCH] Update to latest commit of cmake-git-version-tracking https://github.com/andrew-hardin/cmake-git-version-tracking commit 0ef58f1ef2ee02371d3e5be43e6cc6bf4004d8a5 Mar 7, 2022 --- cmake/git_watcher.cmake | 95 +++++++++++++++++++++++++++++------ mcsema/Version/Version.cpp.in | 12 +++-- 2 files changed, 89 insertions(+), 18 deletions(-) diff --git a/cmake/git_watcher.cmake b/cmake/git_watcher.cmake index 1d8dc2e39..2cc8171d8 100644 --- a/cmake/git_watcher.cmake +++ b/cmake/git_watcher.cmake @@ -27,6 +27,15 @@ # -- The path to the git executable. It'll automatically be set if the # user doesn't supply a path. # +# GIT_FAIL_IF_NONZERO_EXIT (OPTIONAL) +# -- Raise a FATAL_ERROR if any of the git commands return a non-zero +# exit code. This is set to TRUE by default. You can set this to FALSE +# if you'd like the build to continue even if a git command fails. +# +# GIT_IGNORE_UNTRACKED (OPTIONAL) +# -- Ignore the presence of untracked files when detecting if the +# working tree is dirty. This is set to FALSE by default. +# # DESIGN # - This script was designed similar to a Python application # with a Main() function. I wanted to keep it compact to @@ -57,10 +66,16 @@ macro(CHECK_REQUIRED_VARIABLE var_name) endmacro() # Check that an optional variable is set, or, set it to a default value. -macro(CHECK_OPTIONAL_VARIABLE var_name default_value) +macro(CHECK_OPTIONAL_VARIABLE_NOPATH var_name default_value) if(NOT DEFINED ${var_name}) set(${var_name} ${default_value}) endif() +endmacro() + +# Check that an optional variable is set, or, set it to a default value. +# Also converts that path to an abspath. +macro(CHECK_OPTIONAL_VARIABLE var_name default_value) + CHECK_OPTIONAL_VARIABLE_NOPATH(${var_name} ${default_value}) PATH_TO_ABSOLUTE(${var_name}) endmacro() @@ -68,6 +83,8 @@ CHECK_REQUIRED_VARIABLE(PRE_CONFIGURE_FILE) CHECK_REQUIRED_VARIABLE(POST_CONFIGURE_FILE) CHECK_OPTIONAL_VARIABLE(GIT_STATE_FILE "${CMAKE_BINARY_DIR}/git-state-hash") CHECK_OPTIONAL_VARIABLE(GIT_WORKING_DIR "${CMAKE_SOURCE_DIR}") +CHECK_OPTIONAL_VARIABLE_NOPATH(GIT_FAIL_IF_NONZERO_EXIT TRUE) +CHECK_OPTIONAL_VARIABLE_NOPATH(GIT_IGNORE_UNTRACKED FALSE) # Check the optional git variable. # If it's not set, we'll try to find it using the CMake packaging system. @@ -86,27 +103,42 @@ set(_state_variable_names GIT_COMMIT_DATE_ISO8601 GIT_COMMIT_SUBJECT GIT_COMMIT_BODY - VERSION_STRING + GIT_DESCRIBE + GIT_BRANCH # >>> # 1. Add the name of the additional git variable you're interested in monitoring # to this list. + VERSION_STRING ) # Macro: RunGitCommand # Description: short-hand macro for calling a git function. Outputs are the -# "exit_code" and "output" variables. +# "exit_code" and "output" variables. The "_permit_git_failure" +# variable can locally override the exit code checking- use it +# with caution. macro(RunGitCommand) execute_process(COMMAND "${GIT_EXECUTABLE}" ${ARGV} WORKING_DIRECTORY "${_working_dir}" RESULT_VARIABLE exit_code OUTPUT_VARIABLE output - ERROR_QUIET + ERROR_VARIABLE stderr OUTPUT_STRIP_TRAILING_WHITESPACE) - if(NOT exit_code EQUAL 0) + if(NOT exit_code EQUAL 0 AND NOT _permit_git_failure) set(ENV{GIT_RETRIEVED_STATE} "false") + + # Issue 26: git info not properly set + # + # Check if we should fail if any of the exit codes are non-zero. + # Most methods have a fall-back default value that's used in case of non-zero + # exit codes. If you're feeling risky, disable this safety check and use + # those default values. + if(GIT_FAIL_IF_NONZERO_EXIT ) + string(REPLACE ";" " " args_with_spaces "${ARGV}") + message(FATAL_ERROR "${stderr} (${GIT_EXECUTABLE} ${args_with_spaces})") + endif() endif() endmacro() @@ -123,7 +155,12 @@ function(GetGitState _working_dir) set(ENV{GIT_RETRIEVED_STATE} "true") # Get whether or not the working tree is dirty. - RunGitCommand(status --porcelain) + if (GIT_IGNORE_UNTRACKED) + set(untracked_flag "-uno") + else() + set(untracked_flag "-unormal") + endif() + RunGitCommand(status --porcelain ${untracked_flag}) if(NOT exit_code EQUAL 0) set(ENV{GIT_IS_DIRTY} "false") else() @@ -158,25 +195,52 @@ function(GetGitState _working_dir) RunGitCommand(show -s "--format=%s" ${object}) if(exit_code EQUAL 0) + # Escape \ + string(REPLACE "\\" "\\\\" output "${output}") + # Escape quotes + string(REPLACE "\"" "\\\"" output "${output}") set(ENV{GIT_COMMIT_SUBJECT} "${output}") endif() RunGitCommand(show -s "--format=%b" ${object}) if(exit_code EQUAL 0) if(output) + # Escape \ + string(REPLACE "\\" "\\\\" output "${output}") + # Escape quotes + string(REPLACE "\"" "\\\"" output "${output}") # Escape line breaks in the commit message. - string(REPLACE "\r\n" "\\r\\n\\\r\n" safe ${output}) + string(REPLACE "\r\n" "\\r\\n\\\r\n" safe "${output}") if(safe STREQUAL output) # Didn't have windows lines - try unix lines. - string(REPLACE "\n" "\\n\\\n" safe ${output}) + string(REPLACE "\n" "\\n\\\n" safe "${output}") endif() else() # There was no commit body - set the safe string to empty. set(safe "") endif() - set(ENV{GIT_COMMIT_BODY} "\"${safe}\"") + set(ENV{GIT_COMMIT_BODY} "${safe}") else() - set(ENV{GIT_COMMIT_BODY} "\"\"") # empty string. + set(ENV{GIT_COMMIT_BODY} "") # empty string. + endif() + + # Get output of git describe + RunGitCommand(describe --always ${object}) + if(NOT exit_code EQUAL 0) + set(ENV{GIT_DESCRIBE} "unknown") + else() + set(ENV{GIT_DESCRIBE} "${output}") + endif() + + # Convert HEAD to a symbolic ref. This can fail, in which case we just + # set that variable to HEAD. + set(_permit_git_failure ON) + RunGitCommand(symbolic-ref --short -q ${object}) + unset(_permit_git_failure) + if(NOT exit_code EQUAL 0) + set(ENV{GIT_BRANCH} "${object}") + else() + set(ENV{GIT_BRANCH} "${output}") endif() # >>> @@ -184,13 +248,12 @@ function(GetGitState _working_dir) # "execute_process()" command. Be sure to set them in # the environment using the same variable name you added # to the "_state_variable_names" list. - if(EXISTS "${GIT_WORKING_DIR}/VERSION") - file(READ "${GIT_WORKING_DIR}/VERSION" version_output_raw) - string(STRIP "${version_output_raw}" version_output) - set(ENV{VERSION_STRING} "${version_output}") + file(READ "${GIT_WORKING_DIR}/VERSION" version_output_raw) + string(STRIP "${version_output_raw}" version_output) + set(ENV{VERSION_STRING} "${version_output}") else() - set(ENV{VERSION_STRING} "") + set(ENV{VERSION_STRING} "") endif() endfunction() @@ -284,6 +347,8 @@ function(SetupGitMonitoring) -DGIT_STATE_FILE=${GIT_STATE_FILE} -DPRE_CONFIGURE_FILE=${PRE_CONFIGURE_FILE} -DPOST_CONFIGURE_FILE=${POST_CONFIGURE_FILE} + -DGIT_FAIL_IF_NONZERO_EXIT=${GIT_FAIL_IF_NONZERO_EXIT} + -DGIT_IGNORE_UNTRACKED=${GIT_IGNORE_UNTRACKED} -P "${CMAKE_CURRENT_LIST_FILE}") endfunction() diff --git a/mcsema/Version/Version.cpp.in b/mcsema/Version/Version.cpp.in index e91333479..8c23b1080 100644 --- a/mcsema/Version/Version.cpp.in +++ b/mcsema/Version/Version.cpp.in @@ -50,12 +50,18 @@ namespace Version { return "@GIT_COMMIT_SUBJECT@"; } std::string GetCommitBody() { - return @GIT_COMMIT_BODY@; + return "@GIT_COMMIT_BODY@"; } + std::string Describe() { + return "@GIT_DESCRIBE@"; + } + std::string Branch() { + return "@GIT_BRANCH@"; + } + + // Extra for mcsema std::string GetVersionString() { return "@VERSION_STRING@"; } - - } // namespace Version } // namespace mcsema