From 6aea0f12cd00ba36a9697274606b9c0b327248ce Mon Sep 17 00:00:00 2001 From: Alexey Kutepov Date: Fri, 30 Aug 2024 20:01:08 +0700 Subject: [PATCH] Properly persist git hash on each build (#1391) Properly persist git hash on each build Rebuild `git_hash.h` only when `.git` folder changes `add_custom_target()` always considers its target out-of-date which leads to rebuilding of `git_hash.h` on every build (which is ironically what we wanted) and consequently rebuilding of build_options.c and relinking of c3c even when no changes are made, which is mildly annoying. We are replacing `add_custom_target()` with `add_custom_command()` which depends on `.git`, so `git_hash.h` is only rebuilt if any git commands are performed. Which is less annoying. In case of no `.git` we simply do not depend on it which leads to `git_hash.h` being rebuilt only once. --- CMakeLists.txt | 31 ++++++++++++++++--------------- git_hash.cmake | 14 ++++++++++++++ src/build/build_options.c | 3 +-- 3 files changed, 31 insertions(+), 17 deletions(-) create mode 100644 git_hash.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 0144defde..461c0f7ca 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -101,19 +101,6 @@ if(C3_USE_TB AND GIT_FOUND AND EXISTS "${CMAKE_SOURCE_DIR}/.git") endif() endif() -if(GIT_FOUND AND EXISTS "${CMAKE_SOURCE_DIR}/.git") - # Get git hash - execute_process(COMMAND git rev-parse HEAD - OUTPUT_VARIABLE GIT_HASH - RESULT_VARIABLE GIT_REVPARSE_RESULT - OUTPUT_STRIP_TRAILING_WHITESPACE) - if(GIT_REVPARSE_RESULT EQUAL "0") - add_compile_definitions(GIT_HASH="${GIT_HASH}") - else() - message(WARNING "Cannot to get Git Hash: git rev-parse failed with ${GIT_REVPARSE_RESULT}") - endif() -endif() - if(CMAKE_C_COMPILER_ID STREQUAL "MSVC") if (C3_LLVM_VERSION STREQUAL "auto") set(C3_LLVM_VERSION "18") @@ -349,8 +336,21 @@ add_executable(c3c src/utils/time.c src/utils/http.c src/compiler/sema_liveness.c - src/build/common_build.c) + src/build/common_build.c + ${CMAKE_BINARY_DIR}/git_hash.h) +if(GIT_FOUND AND EXISTS "${CMAKE_SOURCE_DIR}/.git") + # We are inside of a git repository so rebuilding the hash every time something changes. + add_custom_command( + OUTPUT ${CMAKE_BINARY_DIR}/git_hash.h + COMMAND ${CMAKE_COMMAND} -P "${CMAKE_CURRENT_LIST_DIR}/git_hash.cmake" + DEPENDS "${CMAKE_CURRENT_LIST_DIR}/.git") +else() + # We are NOT inside of a git repository. Building the has only once. + add_custom_command( + OUTPUT ${CMAKE_BINARY_DIR}/git_hash.h + COMMAND ${CMAKE_COMMAND} -P "${CMAKE_CURRENT_LIST_DIR}/git_hash.cmake") +endif() if (C3_USE_TB) file(GLOB tilde-sources @@ -391,7 +391,8 @@ endif() target_include_directories(c3c PRIVATE "${CMAKE_SOURCE_DIR}/src/" - "${CMAKE_SOURCE_DIR}/wrapper/include/") + "${CMAKE_SOURCE_DIR}/wrapper/include/" + "${CMAKE_BINARY_DIR}") target_include_directories(c3c_wrappers PRIVATE diff --git a/git_hash.cmake b/git_hash.cmake new file mode 100644 index 000000000..9457e60d5 --- /dev/null +++ b/git_hash.cmake @@ -0,0 +1,14 @@ +find_package(Git QUIET) + +set(GIT_HASH "unknown") + +if(GIT_FOUND AND EXISTS "${CMAKE_CURRENT_LIST_DIR}/.git") + execute_process(COMMAND ${GIT_EXECUTABLE} rev-parse HEAD + OUTPUT_VARIABLE GIT_HASH + OUTPUT_STRIP_TRAILING_WHITESPACE + COMMAND_ERROR_IS_FATAL ANY) +endif() + +message("Git Hash: ${GIT_HASH}") + +file(WRITE ${CMAKE_BINARY_DIR}/git_hash.h "#pragma once\n#define GIT_HASH \"${GIT_HASH}\"\n") diff --git a/src/build/build_options.c b/src/build/build_options.c index 0e1ded8b8..e8becfdd5 100644 --- a/src/build/build_options.c +++ b/src/build/build_options.c @@ -5,6 +5,7 @@ #include "../utils/whereami.h" #include "build.h" #include "build_internal.h" +#include "git_hash.h" extern int llvm_version_major; bool silence_deprecation; @@ -482,9 +483,7 @@ static void print_version(void) PRINTF("C3 Compiler Version: %s", COMPILER_VERSION); #endif PRINTF("Installed directory: %s", find_executable_path()); -#ifdef GIT_HASH PRINTF("Git Hash: %s", GIT_HASH); -#endif PRINTF("LLVM version: %s", llvm_version); PRINTF("LLVM default target: %s", llvm_target); }