NetdataProtobuf.cmake 8.8 KB

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