NetdataProtobuf.cmake 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. # Macros and functions for handling of Protobuf
  2. #
  3. # Copyright (c) 2024 Netdata Inc.
  4. # SPDX-License-Identifier: GPL-3.0-or-later
  5. macro(netdata_protobuf_21_tags)
  6. set(PROTOBUF_TAG f0dc78d7e6e331b8c6bb2d5283e06aa26883ca7c) # v21.12
  7. set(NEED_ABSL False)
  8. endmacro()
  9. macro(netdata_protobuf_25_tags)
  10. set(PROTOBUF_TAG 4a2aef570deb2bfb8927426558701e8bfc26f2a4) # v25.3
  11. set(NEED_ABSL True)
  12. set(ABSL_TAG 2f9e432cce407ce0ae50676696666f33a77d42ac) # 20240116.1
  13. endmacro()
  14. # Determine what version of protobuf and abseil to bundle.
  15. #
  16. # This is unfortunately very complicated because we support systems
  17. # older than what Google officially supports for C++.
  18. macro(netdata_set_bundled_protobuf_tags)
  19. netdata_protobuf_21_tags()
  20. if(NOT USE_CXX_11)
  21. if(CMAKE_CXX_COMPILER_ID STREQUAL GNU)
  22. if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 7.3.1)
  23. netdata_protobuf_25_tags()
  24. endif()
  25. elseif(CMAKE_CXX_COMPILER_ID STREQUAL Clang)
  26. if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 7.0.0)
  27. netdata_protobuf_25_tags()
  28. endif()
  29. elseif(CMAKE_CXX_COMPILER_ID STREQUAL AppleClang)
  30. if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 12)
  31. netdata_protobuf_25_tags()
  32. endif()
  33. endif()
  34. endif()
  35. endmacro()
  36. # Prepare a vendored copy of Protobuf for use with Netdata.
  37. function(netdata_bundle_protobuf)
  38. include(FetchContent)
  39. include(NetdataFetchContentExtra)
  40. netdata_set_bundled_protobuf_tags()
  41. set(FETCHCONTENT_TRY_FIND_PACKAGE_MODE NEVER)
  42. string(REPLACE "-fsanitize=address" "" CMAKE_C_FLAGS ${CMAKE_C_FLAGS})
  43. string(REPLACE "-fsanitize=address" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
  44. # ignore debhelper
  45. set(FETCHCONTENT_FULLY_DISCONNECTED Off)
  46. if(NEED_ABSL)
  47. set(ABSL_PROPAGATE_CXX_STD On)
  48. set(ABSL_ENABLE_INSTALL Off)
  49. message(STATUS "Preparing bundled Abseil (required by bundled Protobuf)")
  50. FetchContent_Declare(absl
  51. GIT_REPOSITORY https://github.com/abseil/abseil-cpp
  52. GIT_TAG ${ABSL_TAG}
  53. )
  54. FetchContent_MakeAvailable_NoInstall(absl)
  55. message(STATUS "Finished preparing bundled Abseil")
  56. endif()
  57. set(protobuf_INSTALL Off)
  58. set(protobuf_BUILD_LIBPROTOC Off)
  59. set(protobuf_BUILD_TESTS Off)
  60. set(protobuf_BUILD_SHARED_LIBS Off)
  61. message(STATUS "Preparing bundled Protobuf")
  62. FetchContent_Declare(protobuf
  63. GIT_REPOSITORY https://github.com/protocolbuffers/protobuf.git
  64. GIT_TAG ${PROTOBUF_TAG}
  65. )
  66. FetchContent_MakeAvailable_NoInstall(protobuf)
  67. message(STATUS "Finished preparing bundled Protobuf.")
  68. set(BUNDLED_PROTOBUF True PARENT_SCOPE)
  69. endfunction()
  70. # Handle detection of Protobuf
  71. macro(netdata_detect_protobuf)
  72. if(NOT ENABLE_BUNDLED_PROTOBUF)
  73. if (NOT BUILD_SHARED_LIBS)
  74. set(Protobuf_USE_STATIC_LIBS On)
  75. endif()
  76. # The FindProtobuf CMake module shipped by upstream CMake is
  77. # broken for Protobuf version 22.0 and newer because it does
  78. # not correctly pull in the new Abseil dependencies. Protobuf
  79. # itself sometimes ships a CMake Package Configuration module
  80. # that _does_ work correctly, so use that in preference to the
  81. # Find module shipped with CMake.
  82. #
  83. # The code below works by first attempting to use find_package
  84. # in config mode, and then checking for the existence of the
  85. # target we actually use that gets defined by the protobuf
  86. # CMake Package Configuration Module to determine if that
  87. # worked. A bit of extra logic is required in the case of the
  88. # config mode working, because some systems ship compatibility
  89. # logic for the old FindProtobuf module while others do not.
  90. #
  91. # Upstream bug reference: https://gitlab.kitware.com/cmake/cmake/-/issues/24321
  92. # find_package(Protobuf CONFIG)
  93. if(NOT TARGET protobuf::libprotobuf)
  94. message(STATUS "Could not find Protobuf using Config mode, falling back to Module mode")
  95. # find_package(Protobuf REQUIRED)
  96. endif()
  97. endif()
  98. if(TARGET protobuf::libprotobuf)
  99. if(NOT Protobuf_PROTOC_EXECUTABLE AND TARGET protobuf::protoc)
  100. get_target_property(Protobuf_PROTOC_EXECUTABLE protobuf::protoc
  101. IMPORTED_LOCATION_RELEASE)
  102. if(NOT EXISTS "${Protobuf_PROTOC_EXECUTABLE}")
  103. get_target_property(Protobuf_PROTOC_EXECUTABLE protobuf::protoc
  104. IMPORTED_LOCATION_RELWITHDEBINFO)
  105. endif()
  106. if(NOT EXISTS "${Protobuf_PROTOC_EXECUTABLE}")
  107. get_target_property(Protobuf_PROTOC_EXECUTABLE protobuf::protoc
  108. IMPORTED_LOCATION_MINSIZEREL)
  109. endif()
  110. if(NOT EXISTS "${Protobuf_PROTOC_EXECUTABLE}")
  111. get_target_property(Protobuf_PROTOC_EXECUTABLE protobuf::protoc
  112. IMPORTED_LOCATION_DEBUG)
  113. endif()
  114. if(NOT EXISTS "${Protobuf_PROTOC_EXECUTABLE}")
  115. get_target_property(Protobuf_PROTOC_EXECUTABLE protobuf::protoc
  116. IMPORTED_LOCATION_NOCONFIG)
  117. endif()
  118. if(NOT Protobuf_PROTOC_EXECUTABLE)
  119. set(Protobuf_PROTOC_EXECUTABLE protobuf::protoc)
  120. endif()
  121. endif()
  122. # It is technically possible that this may still not
  123. # be set by this point, so we need to check it and
  124. # fail noisily if it isn't because the build won't
  125. # work without it.
  126. if(NOT Protobuf_PROTOC_EXECUTABLE)
  127. message(FATAL_ERROR "Could not determine the location of the protobuf compiler for the detected version of protobuf.")
  128. endif()
  129. set(NETDATA_PROTOBUF_PROTOC_EXECUTABLE ${Protobuf_PROTOC_EXECUTABLE})
  130. set(NETDATA_PROTOBUF_LIBS protobuf::libprotobuf)
  131. get_target_property(NETDATA_PROTOBUF_CFLAGS_OTHER
  132. protobuf::libprotobuf
  133. INTERFACE_COMPILE_DEFINITIONS)
  134. get_target_property(NETDATA_PROTOBUF_INCLUDE_DIRS
  135. protobuf::libprotobuf
  136. INTERFACE_INCLUDE_DIRECTORIES)
  137. if(NETDATA_PROTOBUF_CFLAGS_OTHER STREQUAL NETDATA_PROTOBUF_CFLAGS_OTHER-NOTFOUND)
  138. set(NETDATA_PROTOBUF_CFLAGS_OTHER "")
  139. endif()
  140. if(NETDATA_PROTOBUF_INCLUDE_DIRS STREQUAL NETDATA_PROTOBUF_INCLUDE_DIRS-NOTFOUND)
  141. set(NETDATA_PROTOBUF_INCLUDE_DIRS "")
  142. endif()
  143. else()
  144. # set(NETDATA_PROTOBUF_PROTOC_EXECUTABLE ${PROTOBUF_PROTOC_EXECUTABLE})
  145. # set(NETDATA_PROTOBUF_CFLAGS_OTHER ${PROTOBUF_CFLAGS_OTHER})
  146. # set(NETDATA_PROTOBUF_INCLUDE_DIRS ${PROTOBUF_INCLUDE_DIRS})
  147. # set(NETDATA_PROTOBUF_LIBS ${PROTOBUF_LIBRARIES})
  148. set(NETDATA_PROTOBUF_PROTOC_EXECUTABLE "/bin/protoc")
  149. set(NETDATA_PROTOBUF_CFLAGS_OTHER "")
  150. set(NETDATA_PROTOBUF_INCLUDE_DIRS "")
  151. set(NETDATA_PROTOBUF_LIBS "-lprotobuf")
  152. endif()
  153. set(ENABLE_PROTOBUF True)
  154. set(HAVE_PROTOBUF True)
  155. endmacro()
  156. # Helper function to compile protocol definitions into C++ code.
  157. function(netdata_protoc_generate_cpp INC_DIR OUT_DIR SRCS HDRS)
  158. if(NOT ARGN)
  159. message(SEND_ERROR "Error: protoc_generate_cpp() called without any proto files")
  160. return()
  161. endif()
  162. set(${INC_DIR})
  163. set(${OUT_DIR})
  164. set(${SRCS})
  165. set(${HDRS})
  166. foreach(FIL ${ARGN})
  167. get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
  168. get_filename_component(DIR ${ABS_FIL} DIRECTORY)
  169. get_filename_component(FIL_WE ${FIL} NAME_WE)
  170. set(GENERATED_PB_CC "${DIR}/${FIL_WE}.pb.cc")
  171. list(APPEND ${SRCS} ${GENERATED_PB_CC})
  172. set(GENERATED_PB_H "${DIR}/${FIL_WE}.pb.h")
  173. list(APPEND ${HDRS} ${GENERATED_PB_H})
  174. list(APPEND _PROTOC_INCLUDE_DIRS ${INC_DIR})
  175. if(ENABLE_BUNDLED_PROTOBUF)
  176. list(APPEND _PROTOC_INCLUDE_DIRS ${CMAKE_BINARY_DIR}/_deps/protobuf-src/src/)
  177. endif()
  178. add_custom_command(OUTPUT ${GENERATED_PB_CC} ${GENERATED_PB_H}
  179. COMMAND ${NETDATA_PROTOBUF_PROTOC_EXECUTABLE}
  180. ARGS "-I$<JOIN:${_PROTOC_INCLUDE_DIRS},;-I>" --cpp_out=${OUT_DIR} ${ABS_FIL}
  181. DEPENDS ${ABS_FIL} ${NETDATA_PROTOBUF_PROTOC_EXECUTABLE}
  182. COMMENT "Running C++ protocol buffer compiler on ${FIL}"
  183. COMMAND_EXPAND_LISTS)
  184. endforeach()
  185. set_source_files_properties(${${SRCS}} ${${HDRS}} PROPERTIES GENERATED TRUE)
  186. set_source_files_properties(${${SRCS}} ${${HDRS}} PROPERTIES COMPILE_OPTIONS -Wno-deprecated-declarations)
  187. set(${SRCS} ${${SRCS}} PARENT_SCOPE)
  188. set(${HDRS} ${${HDRS}} PARENT_SCOPE)
  189. endfunction()
  190. # Add protobuf to a specified target.
  191. function(netdata_add_protobuf _target)
  192. target_compile_definitions(${_target} PRIVATE ${NETDATA_PROTOBUF_CFLAGS_OTHER})
  193. target_include_directories(${_target} PRIVATE ${NETDATA_PROTOBUF_INCLUDE_DIRS})
  194. target_link_libraries(${_target} PRIVATE ${NETDATA_PROTOBUF_LIBS})
  195. endfunction()