/ cmake / script / GenerateBuildInfo.cmake
GenerateBuildInfo.cmake
  1  # Copyright (c) 2023-present The Bitcoin Core developers
  2  # Distributed under the MIT software license, see the accompanying
  3  # file COPYING or https://opensource.org/license/mit/.
  4  
  5  macro(fatal_error)
  6    message(FATAL_ERROR "\n"
  7      "Usage:\n"
  8      "  cmake -D BUILD_INFO_HEADER_PATH=<path> [-D SOURCE_DIR=<path>] -P ${CMAKE_CURRENT_LIST_FILE}\n"
  9      "All specified paths must be absolute ones.\n"
 10    )
 11  endmacro()
 12  
 13  if(DEFINED BUILD_INFO_HEADER_PATH AND IS_ABSOLUTE "${BUILD_INFO_HEADER_PATH}")
 14    if(EXISTS "${BUILD_INFO_HEADER_PATH}")
 15      file(STRINGS ${BUILD_INFO_HEADER_PATH} INFO LIMIT_COUNT 1)
 16    endif()
 17  else()
 18    fatal_error()
 19  endif()
 20  
 21  if(DEFINED SOURCE_DIR)
 22    if(IS_ABSOLUTE "${SOURCE_DIR}" AND IS_DIRECTORY "${SOURCE_DIR}")
 23      set(WORKING_DIR ${SOURCE_DIR})
 24    else()
 25      fatal_error()
 26    endif()
 27  else()
 28    set(WORKING_DIR ${CMAKE_CURRENT_SOURCE_DIR})
 29  endif()
 30  
 31  set(GIT_TAG)
 32  set(GIT_COMMIT)
 33  if(NOT "$ENV{BITCOIN_GENBUILD_NO_GIT}" STREQUAL "1")
 34    find_package(Git QUIET)
 35    if(Git_FOUND)
 36      execute_process(
 37        COMMAND ${GIT_EXECUTABLE} rev-parse --is-inside-work-tree
 38        WORKING_DIRECTORY ${WORKING_DIR}
 39        OUTPUT_VARIABLE IS_INSIDE_WORK_TREE
 40        OUTPUT_STRIP_TRAILING_WHITESPACE
 41        ERROR_QUIET
 42      )
 43      if(IS_INSIDE_WORK_TREE)
 44        # Clean 'dirty' status of touched files that haven't been modified.
 45        execute_process(
 46          COMMAND ${GIT_EXECUTABLE} diff
 47          WORKING_DIRECTORY ${WORKING_DIR}
 48          OUTPUT_QUIET
 49          ERROR_QUIET
 50        )
 51  
 52        execute_process(
 53          COMMAND ${GIT_EXECUTABLE} describe --abbrev=0
 54          WORKING_DIRECTORY ${WORKING_DIR}
 55          OUTPUT_VARIABLE MOST_RECENT_TAG
 56          OUTPUT_STRIP_TRAILING_WHITESPACE
 57          ERROR_QUIET
 58        )
 59  
 60        execute_process(
 61          COMMAND ${GIT_EXECUTABLE} rev-list -1 ${MOST_RECENT_TAG}
 62          WORKING_DIRECTORY ${WORKING_DIR}
 63          OUTPUT_VARIABLE MOST_RECENT_TAG_COMMIT
 64          OUTPUT_STRIP_TRAILING_WHITESPACE
 65          ERROR_QUIET
 66        )
 67  
 68        execute_process(
 69          COMMAND ${GIT_EXECUTABLE} rev-parse HEAD
 70          WORKING_DIRECTORY ${WORKING_DIR}
 71          OUTPUT_VARIABLE HEAD_COMMIT
 72          OUTPUT_STRIP_TRAILING_WHITESPACE
 73          ERROR_QUIET
 74        )
 75  
 76        execute_process(
 77          COMMAND ${GIT_EXECUTABLE} diff-index --quiet HEAD --
 78          WORKING_DIRECTORY ${WORKING_DIR}
 79          RESULT_VARIABLE IS_DIRTY
 80        )
 81  
 82        if(HEAD_COMMIT STREQUAL MOST_RECENT_TAG_COMMIT AND NOT IS_DIRTY)
 83          # If latest commit is tagged and not dirty, then use the tag name.
 84          set(GIT_TAG ${MOST_RECENT_TAG})
 85        else()
 86          # Otherwise, generate suffix from git, i.e. string like "0e0a5173fae3-dirty".
 87          execute_process(
 88            COMMAND ${GIT_EXECUTABLE} rev-parse --short=12 HEAD
 89            WORKING_DIRECTORY ${WORKING_DIR}
 90            OUTPUT_VARIABLE GIT_COMMIT
 91            OUTPUT_STRIP_TRAILING_WHITESPACE
 92            ERROR_QUIET
 93          )
 94          if(IS_DIRTY)
 95            string(APPEND GIT_COMMIT "-dirty")
 96          endif()
 97        endif()
 98      endif()
 99    endif()
100  endif()
101  
102  if(GIT_TAG)
103    set(NEWINFO "#define BUILD_GIT_TAG \"${GIT_TAG}\"")
104  elseif(GIT_COMMIT)
105    set(NEWINFO "#define BUILD_GIT_COMMIT \"${GIT_COMMIT}\"")
106  else()
107    set(NEWINFO "// No build information available")
108  endif()
109  
110  # Only update the header if necessary.
111  if(NOT "${INFO}" STREQUAL "${NEWINFO}")
112    file(WRITE ${BUILD_INFO_HEADER_PATH} "${NEWINFO}\n")
113  endif()