GenerateBuildInfo.cmake raw
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 GIT_EXECUTABLE=<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(GIT_EXECUTABLE)
34 execute_process(
35 COMMAND ${GIT_EXECUTABLE} rev-parse --is-inside-work-tree
36 WORKING_DIRECTORY ${WORKING_DIR}
37 OUTPUT_VARIABLE IS_INSIDE_WORK_TREE
38 OUTPUT_STRIP_TRAILING_WHITESPACE
39 ERROR_QUIET
40 )
41 if(IS_INSIDE_WORK_TREE)
42 # Clean 'dirty' status of touched files that haven't been modified.
43 execute_process(
44 COMMAND ${GIT_EXECUTABLE} diff
45 WORKING_DIRECTORY ${WORKING_DIR}
46 OUTPUT_QUIET
47 ERROR_QUIET
48 )
49
50 execute_process(
51 COMMAND ${GIT_EXECUTABLE} describe --abbrev=0
52 WORKING_DIRECTORY ${WORKING_DIR}
53 OUTPUT_VARIABLE MOST_RECENT_TAG
54 OUTPUT_STRIP_TRAILING_WHITESPACE
55 ERROR_QUIET
56 )
57
58 execute_process(
59 COMMAND ${GIT_EXECUTABLE} rev-list -1 ${MOST_RECENT_TAG}
60 WORKING_DIRECTORY ${WORKING_DIR}
61 OUTPUT_VARIABLE MOST_RECENT_TAG_COMMIT
62 OUTPUT_STRIP_TRAILING_WHITESPACE
63 ERROR_QUIET
64 )
65
66 execute_process(
67 COMMAND ${GIT_EXECUTABLE} rev-parse HEAD
68 WORKING_DIRECTORY ${WORKING_DIR}
69 OUTPUT_VARIABLE HEAD_COMMIT
70 OUTPUT_STRIP_TRAILING_WHITESPACE
71 ERROR_QUIET
72 )
73
74 execute_process(
75 COMMAND ${GIT_EXECUTABLE} diff-index --quiet HEAD --
76 WORKING_DIRECTORY ${WORKING_DIR}
77 RESULT_VARIABLE IS_DIRTY
78 )
79
80 if(HEAD_COMMIT STREQUAL MOST_RECENT_TAG_COMMIT AND NOT IS_DIRTY)
81 # If latest commit is tagged and not dirty, then use the tag name.
82 set(GIT_TAG ${MOST_RECENT_TAG})
83 else()
84 # Otherwise, generate suffix from git, i.e. string like "0e0a5173fae3-dirty".
85 execute_process(
86 COMMAND ${GIT_EXECUTABLE} rev-parse --short=12 HEAD
87 WORKING_DIRECTORY ${WORKING_DIR}
88 OUTPUT_VARIABLE GIT_COMMIT
89 OUTPUT_STRIP_TRAILING_WHITESPACE
90 ERROR_QUIET
91 )
92 if(IS_DIRTY)
93 string(APPEND GIT_COMMIT "-dirty")
94 endif()
95 endif()
96 endif()
97 endif()
98
99 if(GIT_TAG)
100 set(NEWINFO "#define BUILD_GIT_TAG \"${GIT_TAG}\"")
101 elseif(GIT_COMMIT)
102 set(NEWINFO "#define BUILD_GIT_COMMIT \"${GIT_COMMIT}\"")
103 else()
104 set(NEWINFO "// No build information available")
105 endif()
106
107 # Only update the header if necessary.
108 if(NOT "${INFO}" STREQUAL "${NEWINFO}")
109 file(WRITE ${BUILD_INFO_HEADER_PATH} "${NEWINFO}\n")
110 endif()
111