NetdataUtil.cmake 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. # Utility functions used by other modules.
  2. #
  3. # Copyright (c) 2024 Netdata Inc.
  4. # SPDX-License-Identifier: GPL-3.0-or-later
  5. include_guard()
  6. # Determine the version of the host kernel.
  7. #
  8. # Only works on UNIX-like systems, stores the version in the cache
  9. # variable HOST_KERNEL_VERSION.
  10. function(netdata_detect_host_kernel_version)
  11. if(DEFINED HOST_KERNEL_VERSION)
  12. return()
  13. endif()
  14. message(CHECK_START "Determining host kernel version")
  15. if(NOT CMAKE_CROSSCOMPILING)
  16. include(CheckIncludeFile)
  17. check_include_file("linux/version.h" CAN_USE_VERSION_H)
  18. if(CAN_USE_VERSION_H)
  19. message(CHECK_START "Checking version using linux/version.h")
  20. file(WRITE "${CMAKE_BINARY_DIR}/kversion-test.c" "
  21. #include <stdio.h>
  22. #include <linux/version.h>
  23. int main() {
  24. printf(\"%i.%i.%i\", LINUX_VERSION_MAJOR, LINUX_VERSION_PATCHLEVEL, LINUX_VERSION_SUBLEVEL);
  25. }
  26. ")
  27. try_run(_run_success _compile_success
  28. ${CMAKE_BINARY_DIR}
  29. SOURCES ${CMAKE_BINARY_DIR}/kversion-test.c
  30. RUN_OUTPUT_VARIABLE _kversion_output)
  31. if(_compile_success AND _run_success EQUAL 0)
  32. message(CHECK_PASS "success")
  33. set(_kversion_value "${_kversion_output}")
  34. else()
  35. message(CHECK_FAIL "failed")
  36. endif()
  37. endif()
  38. endif()
  39. if(NOT DEFINED _kversion_value)
  40. message(CHECK_START "Checking version using uname")
  41. execute_process(COMMAND uname -r
  42. RESULT_VARIABLE _uname_result
  43. OUTPUT_VARIABLE _uname_output)
  44. if(NOT _uname_result EQUAL 0)
  45. message(CHECK_FAIL "failed")
  46. message(CHECK_FAIL "unknown")
  47. set(HOST_KERNEL_VERSION "0.0.0" CACHE STRING "Detected host kernel version")
  48. return()
  49. else()
  50. message(CHECK_PASS "success")
  51. endif()
  52. set(_kversion_value "${_uname_output}")
  53. endif()
  54. string(REGEX REPLACE "-.+$" "" _kversion "${_kversion_value}")
  55. message(CHECK_PASS "${_kversion}")
  56. set(HOST_KERNEL_VERSION "${_kversion}" CACHE STRING "Detected host kernel version")
  57. endfunction()
  58. # Check what libc we're using.
  59. #
  60. # Sets the specified variable to the name of the libc or "unknown"
  61. function(netdata_identify_libc _libc_name)
  62. if(NOT DEFINED _ND_DETECTED_LIBC)
  63. message(CHECK_START "Detecting libc implementation using ldd")
  64. execute_process(COMMAND ldd --version
  65. COMMAND grep -q -i -E "glibc|gnu libc"
  66. RESULT_VARIABLE LDD_RESULT
  67. OUTPUT_VARIABLE LDD_OUTPUT
  68. ERROR_VARIABLE LDD_OUTPUT)
  69. if(NOT LDD_RESULT)
  70. set(${_libc_name} glibc PARENT_SCOPE)
  71. set(_ND_DETECTED_LIBC glibc CACHE INTERNAL "")
  72. message(CHECK_PASS "glibc")
  73. return()
  74. endif()
  75. execute_process(COMMAND sh -c "ldd --version 2>&1 | grep -q -i 'musl'"
  76. RESULT_VARIABLE LDD_RESULT
  77. OUTPUT_VARIABLE LDD_OUTPUT
  78. ERROR_VARIABLE LDD_OUTPUT)
  79. if(NOT LDD_RESULT)
  80. set(${_libc_name} musl PARENT_SCOPE)
  81. set(_ND_DETECTED_LIBC musl CACHE INTERNAL "")
  82. message(CHECK_PASS "musl")
  83. return()
  84. endif()
  85. message(CHECK_FAIL "unknown")
  86. message(CHECK_START "Looking for libc.so.6")
  87. find_program(LIBC_PATH libc.so.6
  88. PATHS /lib /lib64 /usr/lib /usr/lib64
  89. NO_DEFAULT_PATH
  90. NO_PACKAGE_ROOT_PATH
  91. NO_CMAKE_PATH
  92. NO_CMAKE_ENVIRONMENT_PATH
  93. NO_SYSTEM_ENVIRONMENT_PATH
  94. NO_CMAKE_SYSTEM_PATH
  95. NO_CMAKE_INSTALL_PREFIX
  96. NO_CMAKE_FIND_ROOT_PATH)
  97. if(NOT "${LIBC_PATH}" EQUAL "LIBC_PATH-NOTFOUND")
  98. message(CHECK_PASS "found")
  99. message(CHECK_START "Detecting libc implementation using libc.so.6")
  100. execute_process(COMMAND "${LIBC_PATH}"
  101. COMMAND head -n 1
  102. COMMAND grep -q -i -E "gnu libc|gnu c library"
  103. RESULT_VARIABLE LIBC_RESULT
  104. OUTPUT_VARIABLE LIBC_OUTPUT
  105. ERROR_VARIABLE LIBC_ERROR)
  106. if(NOT LIBC_RESULT)
  107. set(${_libc_name} glibc PARENT_SCOPE)
  108. set(_ND_DETECTED_LIBC glibc CACHE INTERNAL "")
  109. message(CHECK_PASS "glibc")
  110. return()
  111. else()
  112. message(CHECK_FAIL "unknown")
  113. endif()
  114. else()
  115. message(CHECK_FAIL "not found")
  116. endif()
  117. set(${_libc_name} unknown PARENT_SCOPE)
  118. set(_ND_DETECTED_LIBC unknown CACHE INTERNAL "")
  119. else()
  120. set(${_libc_name} ${_ND_DETECTED_LIBC} PARENT_SCOPE)
  121. endif()
  122. endfunction()
  123. # Extract a tar archive.
  124. #
  125. # This will use CMake’s native support if available, but will still
  126. # fall back cleanly if CMake is too old.
  127. function(extract_gzipped_tarball tarball target)
  128. if(CMAKE_VERSION VERSION_LESS 3.18)
  129. find_program(TAR NAMES tar bsdtar DOC "TAR archive program")
  130. if(TAR STREQUAL "TAR-NOTFOUND")
  131. message(FATAL_ERROR "Unable to find tar command")
  132. endif()
  133. find_program(GZIP NAMES gzip DOC "GZIP compression program")
  134. if(GZIP STREQUAL "GZIP-NOTFOUND")
  135. message(FATAL_ERROR "Unable to find gzip command")
  136. endif()
  137. file(MAKE_DIRECTORY "${target}")
  138. execute_process(COMMAND tar -x -z -f "${tarball}" -C "${target}"
  139. RESULT_VARIABLE result)
  140. if(result)
  141. message(FATAL_ERROR "Failed to extract ${tarball}")
  142. endif()
  143. else()
  144. file(ARCHIVE_EXTRACT
  145. INPUT "${tarball}"
  146. DESTINATION "${target}")
  147. endif()
  148. endfunction()
  149. # Get a recursive list of all sub-directories of the specified directory,
  150. # relative to that directory.
  151. function(subdirlist result curdir)
  152. file(GLOB_RECURSE children
  153. LIST_DIRECTORIES TRUE
  154. RELATIVE ${curdir}
  155. ${curdir}/*)
  156. set(dirlist "")
  157. foreach(child ${children})
  158. if(IS_DIRECTORY ${curdir}/${child})
  159. list(APPEND dirlist ${child})
  160. endif()
  161. endforeach()
  162. set(${result} ${dirlist} PARENT_SCOPE)
  163. endfunction()
  164. # Precompile python code in the specified directory relative to the
  165. # CMake install prefix at install time.
  166. # This must be called _after_ the install directive for the python code
  167. # in the specified directory
  168. function(precompile_python dir component)
  169. find_package(Python3)
  170. if(NOT ${Python3_Interpreter_FOUND})
  171. message(STATUS "Could not find Python3, skipping precompilation of Python code.")
  172. return()
  173. endif()
  174. set(prefix [=[${CMAKE_INSTALL_PREFIX}]=])
  175. install(
  176. CODE "message(STATUS \"Precompiling Python3 code in ${prefix}/${dir}\")"
  177. COMPONENT ${component}
  178. )
  179. install(
  180. CODE "execute_process(COMMAND ${Python3_Interpreter} -O -m compileall -j0 -o2 ${prefix}/${dir} WORKING_DIRECTORY ${prefix}/${dir})"
  181. COMPONENT ${component}
  182. )
  183. endfunction()