summaryrefslogtreecommitdiffstats
path: root/packaging/cmake/Modules/NetdataProtobuf.cmake
diff options
context:
space:
mode:
Diffstat (limited to 'packaging/cmake/Modules/NetdataProtobuf.cmake')
-rw-r--r--packaging/cmake/Modules/NetdataProtobuf.cmake225
1 files changed, 225 insertions, 0 deletions
diff --git a/packaging/cmake/Modules/NetdataProtobuf.cmake b/packaging/cmake/Modules/NetdataProtobuf.cmake
new file mode 100644
index 000000000..d4ae3aec6
--- /dev/null
+++ b/packaging/cmake/Modules/NetdataProtobuf.cmake
@@ -0,0 +1,225 @@
+# Macros and functions for handling of Protobuf
+#
+# Copyright (c) 2024 Netdata Inc.
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+macro(netdata_protobuf_21_tags)
+ set(PROTOBUF_TAG f0dc78d7e6e331b8c6bb2d5283e06aa26883ca7c) # v21.12
+ set(NEED_ABSL False)
+endmacro()
+
+macro(netdata_protobuf_25_tags)
+ set(PROTOBUF_TAG 4a2aef570deb2bfb8927426558701e8bfc26f2a4) # v25.3
+ set(NEED_ABSL True)
+ set(ABSL_TAG 2f9e432cce407ce0ae50676696666f33a77d42ac) # 20240116.1
+endmacro()
+
+# Determine what version of protobuf and abseil to bundle.
+#
+# This is unfortunately very complicated because we support systems
+# older than what Google officially supports for C++.
+macro(netdata_set_bundled_protobuf_tags)
+ netdata_protobuf_21_tags()
+
+ if(NOT USE_CXX_11)
+ if(CMAKE_CXX_COMPILER_ID STREQUAL GNU)
+ if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 7.3.1)
+ netdata_protobuf_25_tags()
+ endif()
+ elseif(CMAKE_CXX_COMPILER_ID STREQUAL Clang)
+ if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 7.0.0)
+ netdata_protobuf_25_tags()
+ endif()
+ elseif(CMAKE_CXX_COMPILER_ID STREQUAL AppleClang)
+ if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 12)
+ netdata_protobuf_25_tags()
+ endif()
+ endif()
+ endif()
+endmacro()
+
+# Prepare a vendored copy of Protobuf for use with Netdata.
+function(netdata_bundle_protobuf)
+ include(FetchContent)
+ include(NetdataFetchContentExtra)
+
+ netdata_set_bundled_protobuf_tags()
+
+ set(FETCHCONTENT_TRY_FIND_PACKAGE_MODE NEVER)
+
+ string(REPLACE "-fsanitize=address" "" CMAKE_C_FLAGS ${CMAKE_C_FLAGS})
+ string(REPLACE "-fsanitize=address" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
+
+ # ignore debhelper
+ set(FETCHCONTENT_FULLY_DISCONNECTED Off)
+
+ if(NEED_ABSL)
+ set(ABSL_PROPAGATE_CXX_STD On)
+ set(ABSL_ENABLE_INSTALL Off)
+
+ message(STATUS "Preparing bundled Abseil (required by bundled Protobuf)")
+ FetchContent_Declare(absl
+ GIT_REPOSITORY https://github.com/abseil/abseil-cpp
+ GIT_TAG ${ABSL_TAG}
+ )
+ FetchContent_MakeAvailable_NoInstall(absl)
+ message(STATUS "Finished preparing bundled Abseil")
+ endif()
+
+ set(protobuf_INSTALL Off)
+ set(protobuf_BUILD_LIBPROTOC Off)
+ set(protobuf_BUILD_TESTS Off)
+ set(protobuf_BUILD_SHARED_LIBS Off)
+
+ message(STATUS "Preparing bundled Protobuf")
+ FetchContent_Declare(protobuf
+ GIT_REPOSITORY https://github.com/protocolbuffers/protobuf.git
+ GIT_TAG ${PROTOBUF_TAG}
+ )
+ FetchContent_MakeAvailable_NoInstall(protobuf)
+ message(STATUS "Finished preparing bundled Protobuf.")
+
+ set(BUNDLED_PROTOBUF True PARENT_SCOPE)
+endfunction()
+
+# Handle detection of Protobuf
+macro(netdata_detect_protobuf)
+ if(NOT ENABLE_BUNDLED_PROTOBUF)
+ if (NOT BUILD_SHARED_LIBS)
+ set(Protobuf_USE_STATIC_LIBS On)
+ endif()
+
+ # The FindProtobuf CMake module shipped by upstream CMake is
+ # broken for Protobuf version 22.0 and newer because it does
+ # not correctly pull in the new Abseil dependencies. Protobuf
+ # itself sometimes ships a CMake Package Configuration module
+ # that _does_ work correctly, so use that in preference to the
+ # Find module shipped with CMake.
+ #
+ # The code below works by first attempting to use find_package
+ # in config mode, and then checking for the existence of the
+ # target we actually use that gets defined by the protobuf
+ # CMake Package Configuration Module to determine if that
+ # worked. A bit of extra logic is required in the case of the
+ # config mode working, because some systems ship compatibility
+ # logic for the old FindProtobuf module while others do not.
+ #
+ # Upstream bug reference: https://gitlab.kitware.com/cmake/cmake/-/issues/24321
+ find_package(Protobuf CONFIG)
+
+ if(NOT TARGET protobuf::libprotobuf)
+ message(STATUS "Could not find Protobuf using Config mode, falling back to Module mode")
+ find_package(Protobuf REQUIRED)
+ endif()
+ endif()
+
+ if(TARGET protobuf::libprotobuf)
+ if(NOT Protobuf_PROTOC_EXECUTABLE AND TARGET protobuf::protoc)
+ get_target_property(Protobuf_PROTOC_EXECUTABLE protobuf::protoc
+ IMPORTED_LOCATION_RELEASE)
+ if(NOT EXISTS "${Protobuf_PROTOC_EXECUTABLE}")
+ get_target_property(Protobuf_PROTOC_EXECUTABLE protobuf::protoc
+ IMPORTED_LOCATION_RELWITHDEBINFO)
+ endif()
+ if(NOT EXISTS "${Protobuf_PROTOC_EXECUTABLE}")
+ get_target_property(Protobuf_PROTOC_EXECUTABLE protobuf::protoc
+ IMPORTED_LOCATION_MINSIZEREL)
+ endif()
+ if(NOT EXISTS "${Protobuf_PROTOC_EXECUTABLE}")
+ get_target_property(Protobuf_PROTOC_EXECUTABLE protobuf::protoc
+ IMPORTED_LOCATION_DEBUG)
+ endif()
+ if(NOT EXISTS "${Protobuf_PROTOC_EXECUTABLE}")
+ get_target_property(Protobuf_PROTOC_EXECUTABLE protobuf::protoc
+ IMPORTED_LOCATION_NOCONFIG)
+ endif()
+ if(NOT Protobuf_PROTOC_EXECUTABLE)
+ set(Protobuf_PROTOC_EXECUTABLE protobuf::protoc)
+ endif()
+ endif()
+
+ # It is technically possible that this may still not
+ # be set by this point, so we need to check it and
+ # fail noisily if it isn't because the build won't
+ # work without it.
+ if(NOT Protobuf_PROTOC_EXECUTABLE)
+ message(FATAL_ERROR "Could not determine the location of the protobuf compiler for the detected version of protobuf.")
+ endif()
+
+ set(NETDATA_PROTOBUF_PROTOC_EXECUTABLE ${Protobuf_PROTOC_EXECUTABLE})
+ set(NETDATA_PROTOBUF_LIBS protobuf::libprotobuf)
+ get_target_property(NETDATA_PROTOBUF_CFLAGS_OTHER
+ protobuf::libprotobuf
+ INTERFACE_COMPILE_DEFINITIONS)
+ get_target_property(NETDATA_PROTOBUF_INCLUDE_DIRS
+ protobuf::libprotobuf
+ INTERFACE_INCLUDE_DIRECTORIES)
+
+ if(NETDATA_PROTOBUF_CFLAGS_OTHER STREQUAL NETDATA_PROTOBUF_CFLAGS_OTHER-NOTFOUND)
+ set(NETDATA_PROTOBUF_CFLAGS_OTHER "")
+ endif()
+
+ if(NETDATA_PROTOBUF_INCLUDE_DIRS STREQUAL NETDATA_PROTOBUF_INCLUDE_DIRS-NOTFOUND)
+ set(NETDATA_PROTOBUF_INCLUDE_DIRS "")
+ endif()
+ else()
+ set(NETDATA_PROTOBUF_PROTOC_EXECUTABLE ${PROTOBUF_PROTOC_EXECUTABLE})
+ set(NETDATA_PROTOBUF_CFLAGS_OTHER ${PROTOBUF_CFLAGS_OTHER})
+ set(NETDATA_PROTOBUF_INCLUDE_DIRS ${PROTOBUF_INCLUDE_DIRS})
+ set(NETDATA_PROTOBUF_LIBS ${PROTOBUF_LIBRARIES})
+ endif()
+
+ set(ENABLE_PROTOBUF True)
+ set(HAVE_PROTOBUF True)
+endmacro()
+
+# Helper function to compile protocol definitions into C++ code.
+function(netdata_protoc_generate_cpp INC_DIR OUT_DIR SRCS HDRS)
+ if(NOT ARGN)
+ message(SEND_ERROR "Error: protoc_generate_cpp() called without any proto files")
+ return()
+ endif()
+
+ set(${INC_DIR})
+ set(${OUT_DIR})
+ set(${SRCS})
+ set(${HDRS})
+
+ foreach(FIL ${ARGN})
+ get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
+ get_filename_component(DIR ${ABS_FIL} DIRECTORY)
+ get_filename_component(FIL_WE ${FIL} NAME_WE)
+
+ set(GENERATED_PB_CC "${DIR}/${FIL_WE}.pb.cc")
+ list(APPEND ${SRCS} ${GENERATED_PB_CC})
+
+ set(GENERATED_PB_H "${DIR}/${FIL_WE}.pb.h")
+ list(APPEND ${HDRS} ${GENERATED_PB_H})
+
+ list(APPEND _PROTOC_INCLUDE_DIRS ${INC_DIR})
+
+ if(ENABLE_BUNDLED_PROTOBUF)
+ list(APPEND _PROTOC_INCLUDE_DIRS ${CMAKE_BINARY_DIR}/_deps/protobuf-src/src/)
+ endif()
+
+ add_custom_command(OUTPUT ${GENERATED_PB_CC} ${GENERATED_PB_H}
+ COMMAND ${NETDATA_PROTOBUF_PROTOC_EXECUTABLE}
+ ARGS "-I$<JOIN:${_PROTOC_INCLUDE_DIRS},;-I>" --cpp_out=${OUT_DIR} ${ABS_FIL}
+ DEPENDS ${ABS_FIL} ${NETDATA_PROTOBUF_PROTOC_EXECUTABLE}
+ COMMENT "Running C++ protocol buffer compiler on ${FIL}"
+ COMMAND_EXPAND_LISTS)
+ endforeach()
+
+ set_source_files_properties(${${SRCS}} ${${HDRS}} PROPERTIES GENERATED TRUE)
+ set_source_files_properties(${${SRCS}} ${${HDRS}} PROPERTIES COMPILE_OPTIONS -Wno-deprecated-declarations)
+
+ set(${SRCS} ${${SRCS}} PARENT_SCOPE)
+ set(${HDRS} ${${HDRS}} PARENT_SCOPE)
+endfunction()
+
+# Add protobuf to a specified target.
+function(netdata_add_protobuf _target)
+ target_compile_definitions(${_target} PRIVATE ${NETDATA_PROTOBUF_CFLAGS_OTHER})
+ target_include_directories(${_target} PRIVATE ${NETDATA_PROTOBUF_INCLUDE_DIRS})
+ target_link_libraries(${_target} PRIVATE ${NETDATA_PROTOBUF_LIBS})
+endfunction()