GenerateBuildInfo.cmake raw
1 # Copyright (c) 2023-present The Limenka 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 unset(INFO)
19 set(BUILD_INFO_HEADER_PATH "/dev/stdout")
20 endif()
21
22 if(DEFINED SOURCE_DIR)
23 if(IS_ABSOLUTE "${SOURCE_DIR}" AND IS_DIRECTORY "${SOURCE_DIR}")
24 set(WORKING_DIR ${SOURCE_DIR})
25 else()
26 fatal_error()
27 endif()
28 else()
29 set(WORKING_DIR ${CMAKE_CURRENT_SOURCE_DIR})
30 endif()
31
32 set(GIT_TAG)
33 set(GIT_COMMIT)
34 if(NOT "$ENV{LIMENKA_GENBUILD_NO_GIT}" STREQUAL "1")
35 find_package(Git QUIET)
36 if(Git_FOUND)
37 execute_process(
38 COMMAND ${GIT_EXECUTABLE} rev-parse --is-inside-work-tree
39 WORKING_DIRECTORY ${WORKING_DIR}
40 OUTPUT_VARIABLE IS_INSIDE_WORK_TREE
41 OUTPUT_STRIP_TRAILING_WHITESPACE
42 ERROR_QUIET
43 )
44 if(IS_INSIDE_WORK_TREE)
45 # This check ensures that we are actually part of the intended git repository, and not just getting info about some unrelated git repository that the code happens to be in a directory under
46 execute_process(
47 COMMAND ${GIT_EXECUTABLE} status --porcelain -uall --ignored cmake/script/GenerateBuildInfo.cmake
48 WORKING_DIRECTORY ${WORKING_DIR}
49 RESULT_VARIABLE SCRIPT_STATUS_EXITCODE
50 OUTPUT_VARIABLE SCRIPT_STATUS
51 OUTPUT_STRIP_TRAILING_WHITESPACE
52 ERROR_QUIET
53 )
54 if(SCRIPT_STATUS_EXITCODE)
55 set(IS_INSIDE_WORK_TREE 0)
56 elseif(SCRIPT_STATUS MATCHES "\\?")
57 set(IS_INSIDE_WORK_TREE 0)
58 endif()
59 endif()
60 if(IS_INSIDE_WORK_TREE)
61 # Clean 'dirty' status of touched files that haven't been modified.
62 execute_process(
63 COMMAND ${GIT_EXECUTABLE} diff
64 WORKING_DIRECTORY ${WORKING_DIR}
65 OUTPUT_QUIET
66 ERROR_QUIET
67 )
68
69 execute_process(
70 COMMAND ${GIT_EXECUTABLE} describe --abbrev=0
71 WORKING_DIRECTORY ${WORKING_DIR}
72 OUTPUT_VARIABLE MOST_RECENT_TAG
73 OUTPUT_STRIP_TRAILING_WHITESPACE
74 ERROR_QUIET
75 )
76
77 execute_process(
78 COMMAND ${GIT_EXECUTABLE} rev-list -1 ${MOST_RECENT_TAG}
79 WORKING_DIRECTORY ${WORKING_DIR}
80 OUTPUT_VARIABLE MOST_RECENT_TAG_COMMIT
81 OUTPUT_STRIP_TRAILING_WHITESPACE
82 ERROR_QUIET
83 )
84
85 execute_process(
86 COMMAND ${GIT_EXECUTABLE} rev-parse HEAD
87 WORKING_DIRECTORY ${WORKING_DIR}
88 OUTPUT_VARIABLE HEAD_COMMIT
89 OUTPUT_STRIP_TRAILING_WHITESPACE
90 ERROR_QUIET
91 )
92
93 execute_process(
94 COMMAND ${GIT_EXECUTABLE} diff-index --quiet HEAD --
95 WORKING_DIRECTORY ${WORKING_DIR}
96 RESULT_VARIABLE IS_DIRTY
97 )
98
99 if(HEAD_COMMIT STREQUAL MOST_RECENT_TAG_COMMIT AND NOT IS_DIRTY)
100 # If latest commit is tagged and not dirty, then use the tag name.
101 set(GIT_TAG ${MOST_RECENT_TAG})
102 else()
103 # Otherwise, generate suffix from git, i.e. string like "0e0a5173fae3-dirty".
104 execute_process(
105 COMMAND ${GIT_EXECUTABLE} rev-parse --short=12 HEAD
106 WORKING_DIRECTORY ${WORKING_DIR}
107 OUTPUT_VARIABLE GIT_COMMIT
108 OUTPUT_STRIP_TRAILING_WHITESPACE
109 ERROR_QUIET
110 )
111 if(IS_DIRTY)
112 string(APPEND GIT_COMMIT "-dirty")
113 endif()
114 endif()
115 endif()
116 endif()
117 endif()
118
119 if(GIT_TAG)
120 set(NEWINFO "#define BUILD_GIT_TAG \"${GIT_TAG}\"")
121 elseif(GIT_COMMIT)
122 set(NEWINFO "#define BUILD_GIT_COMMIT \"${GIT_COMMIT}\"")
123 else()
124 # NOTE: The NEWINFO line below this comment gets replaced by a string-match in contrib/guix/libexec/make_release_tarball.sh
125 # If changing it, update the script too!
126 set(NEWINFO [[// No build information available]])
127 endif()
128
129 # Only update the header if necessary.
130 if(NOT "${INFO}" STREQUAL "${NEWINFO}")
131 file(WRITE ${BUILD_INFO_HEADER_PATH} "${NEWINFO}\n")
132 endif()
133