master
cmake 286 lines 8.87 KB
Raw
1 # SPDX-License-Identifier: GPL-3.0-or-later
2 # Utility functions used by other modules.
3
4 include_guard()
5
6 # Fix up CMAKE_SYSTEM_PROCESSOR to actually match the build target
7 function(netdata_fixup_system_processor)
8 if(OS_WINDOWS)
9 return()
10 endif()
11
12 if(CMAKE_TOOLCHAIN_FILE)
13 return()
14 endif()
15
16 execute_process(
17 COMMAND ${CMAKE_C_COMPILER} ${CMAKE_C_FLAGS} -dumpmachine
18 COMMAND cut -f 1 -d -
19 RESULT_VARIABLE return_code
20 OUTPUT_VARIABLE output_data
21 )
22
23 if(return_code EQUAL 0)
24 set(CMAKE_SYSTEM_PROCESSOR "${output_data}" PARENT_SCOPE)
25 else()
26 message(WARNING "Failed to detect target processor architecture, using CMake default")
27 endif()
28 endfunction()
29
30 # Determine the version of the host kernel.
31 #
32 # Only works on UNIX-like systems, stores the version in the cache
33 # variable HOST_KERNEL_VERSION.
34 function(netdata_detect_host_kernel_version)
35 if(DEFINED HOST_KERNEL_VERSION)
36 return()
37 endif()
38
39 message(CHECK_START "Determining host kernel version")
40
41 if(NOT CMAKE_CROSSCOMPILING)
42 include(CheckIncludeFile)
43
44 check_include_file("linux/version.h" CAN_USE_VERSION_H)
45
46 if(CAN_USE_VERSION_H)
47 message(CHECK_START "Checking version using linux/version.h")
48 file(WRITE "${CMAKE_BINARY_DIR}/kversion-test.c" "
49 #include <stdio.h>
50 #include <linux/version.h>
51
52 int main() {
53 printf(\"%i.%i.%i\", LINUX_VERSION_MAJOR, LINUX_VERSION_PATCHLEVEL, LINUX_VERSION_SUBLEVEL);
54 }
55 ")
56
57 try_run(_run_success _compile_success
58 ${CMAKE_BINARY_DIR}
59 SOURCES ${CMAKE_BINARY_DIR}/kversion-test.c
60 RUN_OUTPUT_VARIABLE _kversion_output)
61
62 if(_compile_success AND _run_success EQUAL 0)
63 message(CHECK_PASS "success")
64 set(_kversion_value "${_kversion_output}")
65 else()
66 message(CHECK_FAIL "failed")
67 endif()
68 endif()
69 endif()
70
71 if(NOT DEFINED _kversion_value)
72 message(CHECK_START "Checking version using uname")
73 execute_process(COMMAND uname -r
74 RESULT_VARIABLE _uname_result
75 OUTPUT_VARIABLE _uname_output)
76
77 if(NOT _uname_result EQUAL 0)
78 message(CHECK_FAIL "failed")
79 message(CHECK_FAIL "unknown")
80 set(HOST_KERNEL_VERSION "0.0.0" CACHE STRING "Detected host kernel version")
81 return()
82 else()
83 message(CHECK_PASS "success")
84 endif()
85
86 set(_kversion_value "${_uname_output}")
87 endif()
88
89 string(REGEX REPLACE "-.+$" "" _kversion "${_kversion_value}")
90 message(CHECK_PASS "${_kversion}")
91 set(HOST_KERNEL_VERSION "${_kversion}" CACHE STRING "Detected host kernel version")
92 endfunction()
93
94 # Check what libc we're using.
95 #
96 # Sets the specified variable to the name of the libc or "unknown"
97 function(netdata_identify_libc _libc_name)
98 if(NOT DEFINED _ND_DETECTED_LIBC)
99 message(CHECK_START "Detecting libc implementation using ldd")
100
101 execute_process(COMMAND ldd --version
102 COMMAND grep -q -i -E "glibc|gnu libc"
103 RESULT_VARIABLE LDD_RESULT
104 OUTPUT_VARIABLE LDD_OUTPUT
105 ERROR_VARIABLE LDD_OUTPUT)
106
107 if(NOT LDD_RESULT)
108 set(${_libc_name} glibc PARENT_SCOPE)
109 set(_ND_DETECTED_LIBC glibc CACHE INTERNAL "")
110 message(CHECK_PASS "glibc")
111 return()
112 endif()
113
114 execute_process(COMMAND sh -c "ldd --version 2>&1 | grep -q -i 'musl'"
115 RESULT_VARIABLE LDD_RESULT
116 OUTPUT_VARIABLE LDD_OUTPUT
117 ERROR_VARIABLE LDD_OUTPUT)
118
119 if(NOT LDD_RESULT)
120 set(${_libc_name} musl PARENT_SCOPE)
121 set(_ND_DETECTED_LIBC musl CACHE INTERNAL "")
122 message(CHECK_PASS "musl")
123 return()
124 endif()
125
126 message(CHECK_FAIL "unknown")
127
128 message(CHECK_START "Looking for libc.so.6")
129 find_program(LIBC_PATH libc.so.6
130 PATHS /lib /lib64 /usr/lib /usr/lib64
131 NO_DEFAULT_PATH
132 NO_PACKAGE_ROOT_PATH
133 NO_CMAKE_PATH
134 NO_CMAKE_ENVIRONMENT_PATH
135 NO_SYSTEM_ENVIRONMENT_PATH
136 NO_CMAKE_SYSTEM_PATH
137 NO_CMAKE_INSTALL_PREFIX
138 NO_CMAKE_FIND_ROOT_PATH)
139
140 if(NOT "${LIBC_PATH}" EQUAL "LIBC_PATH-NOTFOUND")
141 message(CHECK_PASS "found")
142 message(CHECK_START "Detecting libc implementation using libc.so.6")
143
144 execute_process(COMMAND "${LIBC_PATH}"
145 COMMAND head -n 1
146 COMMAND grep -q -i -E "gnu libc|gnu c library"
147 RESULT_VARIABLE LIBC_RESULT
148 OUTPUT_VARIABLE LIBC_OUTPUT
149 ERROR_VARIABLE LIBC_ERROR)
150
151 if(NOT LIBC_RESULT)
152 set(${_libc_name} glibc PARENT_SCOPE)
153 set(_ND_DETECTED_LIBC glibc CACHE INTERNAL "")
154 message(CHECK_PASS "glibc")
155 return()
156 else()
157 message(CHECK_FAIL "unknown")
158 endif()
159 else()
160 message(CHECK_FAIL "not found")
161 endif()
162
163 set(${_libc_name} unknown PARENT_SCOPE)
164 set(_ND_DETECTED_LIBC unknown CACHE INTERNAL "")
165 else()
166 set(${_libc_name} ${_ND_DETECTED_LIBC} PARENT_SCOPE)
167 endif()
168 endfunction()
169
170 # Extract a tar archive.
171 #
172 # This will use CMake’s native support if available, but will still
173 # fall back cleanly if CMake is too old.
174 function(extract_gzipped_tarball tarball target)
175 if(CMAKE_VERSION VERSION_LESS 3.18)
176 find_program(TAR NAMES tar bsdtar DOC "TAR archive program")
177
178 if(TAR STREQUAL "TAR-NOTFOUND")
179 message(FATAL_ERROR "Unable to find tar command")
180 endif()
181
182 find_program(GZIP NAMES gzip DOC "GZIP compression program")
183
184 if(GZIP STREQUAL "GZIP-NOTFOUND")
185 message(FATAL_ERROR "Unable to find gzip command")
186 endif()
187
188 file(MAKE_DIRECTORY "${target}")
189 execute_process(COMMAND tar -x -z -f "${tarball}" -C "${target}"
190 RESULT_VARIABLE result)
191
192 if(result)
193 message(FATAL_ERROR "Failed to extract ${tarball}")
194 endif()
195 else()
196 file(ARCHIVE_EXTRACT
197 INPUT "${tarball}"
198 DESTINATION "${target}")
199 endif()
200 endfunction()
201
202 # Get a recursive list of all sub-directories of the specified directory,
203 # relative to that directory.
204 function(subdirlist result curdir)
205 file(GLOB_RECURSE children
206 LIST_DIRECTORIES TRUE
207 RELATIVE ${curdir}
208 ${curdir}/*)
209
210 set(dirlist "")
211
212 foreach(child ${children})
213 if(IS_DIRECTORY ${curdir}/${child})
214 list(APPEND dirlist ${child})
215 endif()
216 endforeach()
217
218 set(${result} ${dirlist} PARENT_SCOPE)
219 endfunction()
220
221 # Precompile python code in the specified directory relative to the
222 # CMake install prefix at install time.
223 # This must be called _after_ the install directive for the python code
224 # in the specified directory
225 function(precompile_python dir component)
226 find_package(Python3)
227
228 if(NOT ${Python3_Interpreter_FOUND})
229 message(STATUS "Could not find Python3, skipping precompilation of Python code.")
230 return()
231 endif()
232
233 set(prefix [=[${CMAKE_INSTALL_PREFIX}]=])
234
235 install(
236 CODE "message(STATUS \"Precompiling Python3 code in ${prefix}/${dir}\")"
237 COMPONENT ${component}
238 )
239 install(
240 CODE "execute_process(COMMAND ${Python3_Interpreter} -O -m compileall -j0 -o2 ${prefix}/${dir} WORKING_DIRECTORY ${prefix}/${dir})"
241 COMPONENT ${component}
242 )
243 endfunction()
244
245 # Load the URL and hash for a vendored component
246 function(get_vendored_url_and_hash component prefix)
247 set(url_file "${CMAKE_SOURCE_DIR}/packaging/vendor/${component}.url")
248 set(hash_file "${CMAKE_SOURCE_DIR}/packaging/vendor/${component}.sha256")
249
250 if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.29)
251 if(NOT IS_READABLE ${url_file})
252 message(FATAL_ERROR "Unable to read data from ${url_file}")
253 endif()
254 else()
255 if(NOT EXISTS ${url_file})
256 message(FATAL_ERROR "Unable to read data from ${url_file}")
257 endif()
258 endif()
259
260 file(READ "${url_file}" "url")
261 string(STRIP "${url}" "url")
262
263 if("${url}" STREQUAL "")
264 message(FATAL_ERROR "${url_file} is empty")
265 endif()
266
267 if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.29)
268 if(NOT IS_READABLE ${hash_file})
269 message(FATAL_ERROR "Unable to read data from ${hash_file}")
270 endif()
271 else()
272 if(NOT EXISTS ${hash_file})
273 message(FATAL_ERROR "Unable to read data from ${hash_file}")
274 endif()
275 endif()
276
277 file(READ "${hash_file}" "hash")
278 string(STRIP "${hash}" "hash")
279
280 if("${hash}" STREQUAL "")
281 message(FATAL_ERROR "${hash_file} is empty")
282 endif()
283
284 set("${prefix}_URL" "${url}" PARENT_SCOPE)
285 set("${prefix}_HASH" "${hash}" PARENT_SCOPE)
286 endfunction()