435 lines
14 KiB
CMake
435 lines
14 KiB
CMake
# -- Project Setup ------------------------------------------------------------
|
|
|
|
cmake_minimum_required(VERSION 3.15 FATAL_ERROR)
|
|
project(broker C CXX)
|
|
|
|
include(CMakePackageConfigHelpers)
|
|
include(GNUInstallDirs)
|
|
include(cmake/CommonCMakeConfig.cmake)
|
|
include(cmake/ZeekBundle.cmake)
|
|
|
|
set(BROKER_TEST_TIMEOUT 60)
|
|
|
|
get_directory_property(parent_dir PARENT_DIRECTORY)
|
|
if(parent_dir)
|
|
set(broker_is_subproject ON)
|
|
else()
|
|
set(broker_is_subproject OFF)
|
|
endif()
|
|
unset(parent_dir)
|
|
|
|
if ( MSVC )
|
|
message(STATUS "Broker currently only supports static bulids on Windows")
|
|
message(STATUS "Note: continue with ENABLE_STATIC_ONLY")
|
|
set(ENABLE_STATIC_ONLY ON)
|
|
endif ()
|
|
|
|
# Check the thread library info early as setting compiler flags seems to
|
|
# interfere with the detection and causes CMAKE_THREAD_LIBS_INIT to not
|
|
# include -lpthread when it should.
|
|
if (NOT TARGET Threads::Threads)
|
|
find_package(Threads REQUIRED)
|
|
endif ()
|
|
set(LINK_LIBS ${LINK_LIBS} Threads::Threads)
|
|
|
|
# Leave most compiler flags alone when building as subdirectory.
|
|
if (NOT broker_is_subproject)
|
|
|
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin)
|
|
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/lib)
|
|
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/lib)
|
|
|
|
if ( ENABLE_CCACHE )
|
|
find_program(CCACHE_PROGRAM ccache)
|
|
|
|
if ( NOT CCACHE_PROGRAM )
|
|
message(FATAL_ERROR "ccache not found")
|
|
endif ()
|
|
|
|
message(STATUS "Using ccache: ${CCACHE_PROGRAM}")
|
|
set(CMAKE_C_COMPILER_LAUNCHER ${CCACHE_PROGRAM})
|
|
set(CMAKE_CXX_COMPILER_LAUNCHER ${CCACHE_PROGRAM})
|
|
endif ()
|
|
|
|
if ( BROKER_SANITIZERS )
|
|
set(_sanitizer_flags "-fsanitize=${BROKER_SANITIZERS}")
|
|
set(_sanitizer_flags "${_sanitizer_flags} -fno-omit-frame-pointer")
|
|
set(_sanitizer_flags "${_sanitizer_flags} -fno-optimize-sibling-calls")
|
|
|
|
# Technically, then we also need to use the compiler to drive linking and
|
|
# give the sanitizer flags there, too. However, CMake, by default, uses
|
|
# the compiler for linking and so the flags automatically get used. See
|
|
# https://cmake.org/pipermail/cmake/2014-August/058268.html
|
|
set(CAF_EXTRA_FLAGS "${_sanitizer_flags}")
|
|
|
|
# Set EXTRA_FLAGS if broker isn't being built as part of a Zeek build.
|
|
# The Zeek build sets it otherwise.
|
|
if ( NOT ZEEK_SANITIZERS )
|
|
set(EXTRA_FLAGS "${EXTRA_FLAGS} ${_sanitizer_flags}")
|
|
endif ()
|
|
endif()
|
|
|
|
endif()
|
|
|
|
if ( MSVC )
|
|
# Allow more sections in object files, otherwise Broker fails to compile.
|
|
set(EXTRA_FLAGS "${EXTRA_FLAGS} /bigobj")
|
|
# Similar to -funsigned-char on other platforms.
|
|
set(EXTRA_FLAGS "${EXTRA_FLAGS} /J")
|
|
else ()
|
|
# Increase warnings.
|
|
set(EXTRA_FLAGS "${EXTRA_FLAGS} -Wall -Wno-unused -pedantic")
|
|
# Increase maximum number of instantiations.
|
|
set(EXTRA_FLAGS "${EXTRA_FLAGS} -ftemplate-depth=512")
|
|
# Make sure to get the full context on template errors.
|
|
set(EXTRA_FLAGS "${EXTRA_FLAGS} -ftemplate-backtrace-limit=0")
|
|
endif ()
|
|
|
|
# Append our extra flags to the existing value of CXXFLAGS.
|
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_FLAGS}")
|
|
|
|
include(RequireCXX17)
|
|
include(CheckCXXSourceCompiles)
|
|
|
|
# Unfortunately, std::filesystem is a mess. The feature checks at compile time
|
|
# via __has_include(<filesystem>) or __cpp_lib_filesystem only tell half of the
|
|
# story. On some older Clang releases, one also needs to additional link to
|
|
# -lc++fs. On some older GCC releases, -lstdc++-fs is required. We do have a
|
|
# fallback for pre-std-filesystem on POSIX systems. So, instead of doing all the
|
|
# flag guessing, we simply check once whether code using <filesystem> compiles,
|
|
# links and runs. Otherwise, we fall back to our pre-std-filesystem
|
|
# implementation - or raise an error when building on Windows (since we don't
|
|
# have a fallback on this platform).
|
|
check_cxx_source_compiles("
|
|
#include <cstdlib>
|
|
#include <filesystem>
|
|
int main(int, char**) {
|
|
auto cwd = std::filesystem::current_path();
|
|
auto str = cwd.string();
|
|
return str.empty() ? EXIT_FAILURE : EXIT_SUCCESS;
|
|
}
|
|
"
|
|
BROKER_HAS_STD_FILESYSTEM)
|
|
|
|
if (MSVC)
|
|
|
|
if (NOT BROKER_HAS_STD_FILESYSTEM)
|
|
message(FATAL_ERROR "No std::filesystem support! Required on MSVC.")
|
|
endif ()
|
|
|
|
set(BROKER_USE_SSE2 OFF)
|
|
|
|
elseif (NOT BROKER_DISABLE_SSE2_CHECK)
|
|
|
|
include(CheckIncludeFiles)
|
|
set(CMAKE_REQUIRED_FLAGS -msse2)
|
|
check_include_files(emmintrin.h BROKER_USE_SSE2)
|
|
set(CMAKE_REQUIRED_FLAGS)
|
|
|
|
if (BROKER_USE_SSE2)
|
|
add_definitions(-msse2)
|
|
endif ()
|
|
|
|
endif ()
|
|
|
|
if (NOT BROKER_DISABLE_ATOMICS_CHECK)
|
|
|
|
set(atomic_64bit_ops_test "
|
|
#include <atomic>
|
|
struct s64 { char a, b, c, d, e, f, g, h; };
|
|
int main() { std::atomic<s64> x; x.store({}); x.load(); return 0; }
|
|
")
|
|
check_cxx_source_compiles("${atomic_64bit_ops_test}" atomic64_builtin)
|
|
|
|
if ( NOT atomic64_builtin )
|
|
set(CMAKE_REQUIRED_LIBRARIES atomic)
|
|
check_cxx_source_compiles("${atomic_64bit_ops_test}" atomic64_with_lib)
|
|
set(CMAKE_REQUIRED_LIBRARIES)
|
|
|
|
if ( atomic64_with_lib )
|
|
set(LINK_LIBS ${LINK_LIBS} atomic)
|
|
else ()
|
|
# Guess we'll find out for sure when we compile/link.
|
|
message(WARNING "build may fail due to missing 64-bit atomic support")
|
|
endif ()
|
|
endif ()
|
|
|
|
endif ()
|
|
|
|
# -- Platform Setup ----------------------------------------------------------
|
|
|
|
if (APPLE)
|
|
set(BROKER_APPLE true)
|
|
elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
|
set(BROKER_LINUX true)
|
|
elseif(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
|
|
set(BROKER_FREEBSD true)
|
|
elseif(WIN32)
|
|
set(BROKER_WINDOWS true)
|
|
endif ()
|
|
|
|
include(TestBigEndian)
|
|
test_big_endian(BROKER_BIG_ENDIAN)
|
|
|
|
# -- Dependencies -------------------------------------------------------------
|
|
|
|
if (WIN32)
|
|
set(LINK_LIBS ${LINK_LIBS} ws2_32 iphlpapi crypt32)
|
|
endif ()
|
|
|
|
# Search for OpenSSL if not already provided by parent project
|
|
if (NOT OPENSSL_LIBRARIES)
|
|
find_package(OpenSSL REQUIRED)
|
|
include_directories(BEFORE ${OPENSSL_INCLUDE_DIR})
|
|
endif()
|
|
set(LINK_LIBS ${LINK_LIBS} OpenSSL::SSL OpenSSL::Crypto)
|
|
|
|
function(add_bundled_caf)
|
|
# Disable unnecessary features and make sure CAF builds static libraries.
|
|
set(CAF_ENABLE_EXAMPLES OFF)
|
|
set(CAF_ENABLE_TESTING OFF)
|
|
set(CAF_ENABLE_TOOLS OFF)
|
|
set(BUILD_SHARED_LIBS OFF)
|
|
if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.24")
|
|
add_subdirectory(caf EXCLUDE_FROM_ALL SYSTEM)
|
|
else()
|
|
add_subdirectory(caf EXCLUDE_FROM_ALL)
|
|
endif()
|
|
# Disable a few false positives / irrelevant warnings while building CAF.
|
|
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
|
target_compile_options(caf_internal INTERFACE -Wno-invalid-offsetof -Wno-documentation)
|
|
endif ()
|
|
endfunction()
|
|
|
|
# Bundle prometheus-cpp. This approach is currently experimental.
|
|
if (CMAKE_MSVC_RUNTIME_LIBRARY)
|
|
set(msvc_zeekbundle_args
|
|
CMAKE_MSVC_RUNTIME_LIBRARY=${CMAKE_MSVC_RUNTIME_LIBRARY}
|
|
CMAKE_MSVC_RUNTIME_LIBRARY_FLAG=${CMAKE_MSVC_RUNTIME_LIBRARY_FLAG})
|
|
endif ()
|
|
ZeekBundle_Add(
|
|
NAME prometheus-cpp
|
|
FETCH
|
|
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/auxil/prometheus-cpp
|
|
CONFIGURE
|
|
${msvc_zeekbundle_args}
|
|
ENABLE_COMPRESSION=OFF
|
|
ENABLE_PUSH=OFF)
|
|
unset(msvc_zeekbundle_args)
|
|
|
|
# Bundle all prometheus-cpp libraries that we need as single interface library.
|
|
add_library(broker-prometheus-cpp INTERFACE)
|
|
target_link_libraries(
|
|
broker-prometheus-cpp
|
|
INTERFACE
|
|
$<BUILD_INTERFACE:prometheus-cpp::core>
|
|
$<BUILD_INTERFACE:prometheus-cpp::pull>)
|
|
# Prometheus-cpp sets C++ 11 via CMake property, but we need C++ 17.
|
|
target_compile_features(broker-prometheus-cpp INTERFACE cxx_std_17)
|
|
# Must be exported to keep CMake happy, even though we only need it internally.
|
|
install(TARGETS broker-prometheus-cpp
|
|
EXPORT BrokerTargets
|
|
DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
|
|
|
# NOTE: building and linking against an external CAF version is NOT supported!
|
|
# This variable is FOR DEVELOPMENT ONLY. The only officially supported CAF
|
|
# version is the bundled version!
|
|
if (CAF_ROOT)
|
|
message(STATUS "Using system CAF version ${CAF_VERSION}")
|
|
find_package(CAF REQUIRED COMPONENTS test io core net)
|
|
list(APPEND LINK_LIBS CAF::core CAF::io CAF::net)
|
|
set(BROKER_USE_EXTERNAL_CAF ON)
|
|
else ()
|
|
# Note: we use the object libraries here to avoid having dependencies on the
|
|
# actual CAF targets that would force consumers of Broker to have CMake being
|
|
# able to find a CAF installation.
|
|
message(STATUS "Using bundled CAF")
|
|
add_bundled_caf()
|
|
set(BROKER_USE_EXTERNAL_CAF OFF)
|
|
endif ()
|
|
|
|
if ( NOT BROKER_DISABLE_TESTS )
|
|
enable_testing()
|
|
endif()
|
|
|
|
# -- libroker -----------------------------------------------------------------
|
|
|
|
file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" BROKER_VERSION LIMIT_COUNT 1)
|
|
string(REPLACE "." " " _version_numbers ${BROKER_VERSION})
|
|
separate_arguments(_version_numbers)
|
|
list(GET _version_numbers 0 BROKER_VERSION_MAJOR)
|
|
list(GET _version_numbers 1 BROKER_VERSION_MINOR)
|
|
|
|
# The SO number shall increase only if binary interface changes.
|
|
set(BROKER_SOVERSION 4)
|
|
set(ENABLE_SHARED true)
|
|
|
|
if (ENABLE_STATIC_ONLY)
|
|
set(ENABLE_STATIC true)
|
|
set(ENABLE_SHARED false)
|
|
endif ()
|
|
|
|
# Make sure there are no old header versions on disk.
|
|
install(
|
|
CODE "MESSAGE(STATUS \"Removing: ${CMAKE_INSTALL_PREFIX}/include/broker\")"
|
|
CODE "file(REMOVE_RECURSE \"${CMAKE_INSTALL_PREFIX}/include/broker\")")
|
|
|
|
# Install all headers except the files from broker/internal.
|
|
install(DIRECTORY libbroker/broker
|
|
DESTINATION include
|
|
FILES_MATCHING PATTERN "*.hh"
|
|
PATTERN "libbroker/broker/internal" EXCLUDE
|
|
PATTERN "*.test.hh" EXCLUDE)
|
|
|
|
if (NOT BROKER_EXTERNAL_SQLITE_TARGET)
|
|
include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty)
|
|
set_source_files_properties(3rdparty/sqlite3.c PROPERTIES COMPILE_FLAGS
|
|
-DSQLITE_OMIT_LOAD_EXTENSION)
|
|
list(APPEND OPTIONAL_SRC ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/sqlite3.c)
|
|
else()
|
|
list(APPEND LINK_LIBS ${BROKER_EXTERNAL_SQLITE_TARGET})
|
|
endif()
|
|
|
|
add_subdirectory(libbroker)
|
|
|
|
set(tidyCfgFile "${CMAKE_SOURCE_DIR}/.clang-tidy")
|
|
if (BROKER_ENABLE_TIDY)
|
|
# Create a preprocessor definition that depends on .clang-tidy content so
|
|
# the compile command will change when .clang-tidy changes. This ensures
|
|
# that a subsequent build re-runs clang-tidy on all sources even if they
|
|
# do not otherwise need to be recompiled.
|
|
file(SHA1 ${CMAKE_CURRENT_SOURCE_DIR}/.clang-tidy clang_tidy_sha1)
|
|
set(BROKER_CLANG_TIDY_DEF "CLANG_TIDY_SHA1=${clang_tidy_sha1}")
|
|
unset(clang_tidy_sha1)
|
|
add_custom_target(clang_tidy_dummy DEPENDS ${tidyCfgFile})
|
|
set_target_properties(${BROKER_LIBRARY} PROPERTIES
|
|
CXX_CLANG_TIDY "clang-tidy;--config-file=${tidyCfgFile}")
|
|
target_compile_definitions(${BROKER_LIBRARY} PRIVATE ${BROKER_CLANG_TIDY_DEF})
|
|
configure_file(.clang-tidy .clang-tidy COPYONLY)
|
|
endif ()
|
|
|
|
|
|
# -- Tools and benchmarks -----------------------------------------------------
|
|
|
|
if (NOT broker_is_subproject)
|
|
add_subdirectory(broker-node)
|
|
add_subdirectory(broker-pipe)
|
|
add_subdirectory(broker-throughput)
|
|
endif ()
|
|
|
|
# -- Bindings -----------------------------------------------------------------
|
|
|
|
if(NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/bindings/python/3rdparty/pybind11/CMakeLists.txt")
|
|
message(WARNING "Skipping Python bindings: pybind11 submodule not available")
|
|
set(DISABLE_PYTHON_BINDINGS true)
|
|
endif ()
|
|
|
|
if (NOT DISABLE_PYTHON_BINDINGS)
|
|
set(Python_ADDITIONAL_VERSIONS 3)
|
|
find_package(Python 3.9 COMPONENTS Interpreter Development)
|
|
|
|
if (NOT Python_FOUND)
|
|
message(STATUS "Skipping Python bindings: Python interpreter not found")
|
|
else ()
|
|
set (BROKER_PYTHON_BINDINGS true)
|
|
set (BROKER_PYTHON_STAGING_DIR ${CMAKE_CURRENT_BINARY_DIR}/python)
|
|
add_subdirectory(bindings/python)
|
|
endif ()
|
|
endif ()
|
|
|
|
# -- Zeek ---------------------------------------------------------------------
|
|
|
|
if (NOT "${ZEEK_EXECUTABLE}" STREQUAL "")
|
|
set(ZEEK_FOUND true)
|
|
set(ZEEK_FOUND_MSG "${ZEEK_EXECUTABLE}")
|
|
else ()
|
|
set(ZEEK_FOUND false)
|
|
find_file(ZEEK_PATH_DEV zeek-path-dev.sh PATHS ${CMAKE_CURRENT_BINARY_DIR}/../../../build NO_DEFAULT_PATH)
|
|
if (EXISTS ${ZEEK_PATH_DEV})
|
|
set(ZEEK_FOUND true)
|
|
set(ZEEK_FOUND_MSG "${ZEEK_PATH_DEV}")
|
|
endif ()
|
|
endif ()
|
|
|
|
# -- Unit Tests ---------------------------------------------------------------
|
|
|
|
if ( NOT BROKER_DISABLE_TESTS )
|
|
add_subdirectory(tests)
|
|
endif ()
|
|
|
|
# -- Documentation ------------------------------------------------------------
|
|
|
|
if (NOT WIN32 AND NOT BROKER_DISABLE_DOCS)
|
|
add_subdirectory(doc)
|
|
endif ()
|
|
|
|
# -- CMake package install ----------------------------------------------------
|
|
|
|
export(EXPORT BrokerTargets FILE BrokerTargets.cmake)
|
|
|
|
install(
|
|
EXPORT BrokerTargets
|
|
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/Broker")
|
|
|
|
configure_package_config_file(
|
|
"${CMAKE_CURRENT_SOURCE_DIR}/libbroker/BrokerConfig.cmake.in"
|
|
"${CMAKE_CURRENT_BINARY_DIR}/BrokerConfig.cmake"
|
|
INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/Broker")
|
|
|
|
write_basic_package_version_file(
|
|
"${CMAKE_CURRENT_BINARY_DIR}/BrokerConfigVersion.cmake"
|
|
VERSION ${BROKER_VERSION}
|
|
COMPATIBILITY ExactVersion)
|
|
|
|
install(
|
|
FILES
|
|
"${CMAKE_CURRENT_BINARY_DIR}/BrokerConfig.cmake"
|
|
"${CMAKE_CURRENT_BINARY_DIR}/BrokerConfigVersion.cmake"
|
|
DESTINATION
|
|
"${CMAKE_INSTALL_LIBDIR}/cmake/Broker")
|
|
|
|
# -- Build Summary ------------------------------------------------------------
|
|
|
|
if (CMAKE_BUILD_TYPE)
|
|
string(TOUPPER ${CMAKE_BUILD_TYPE} BuildType)
|
|
endif ()
|
|
|
|
macro(display test desc summary)
|
|
if ( ${test} )
|
|
set(${summary} ${desc})
|
|
else ()
|
|
set(${summary} no)
|
|
endif()
|
|
endmacro()
|
|
|
|
display(ENABLE_SHARED yes shared_summary)
|
|
display(ENABLE_STATIC yes static_summary)
|
|
display(BROKER_PYTHON_BINDINGS yes python_summary)
|
|
display(ZEEK_FOUND "${ZEEK_FOUND_MSG}" zeek_summary)
|
|
|
|
set(summary
|
|
"==================| Broker Config Summary |===================="
|
|
"\nVersion: ${BROKER_VERSION}"
|
|
"\nSO version: ${BROKER_SOVERSION}"
|
|
"\n"
|
|
"\nBuild Type: ${CMAKE_BUILD_TYPE}"
|
|
"\nInstall prefix: ${CMAKE_INSTALL_PREFIX}"
|
|
"\nLibrary prefix: ${CMAKE_INSTALL_LIBDIR}"
|
|
"\nShared libs: ${shared_summary}"
|
|
"\nStatic libs: ${static_summary}"
|
|
"\n"
|
|
"\nCC: ${CMAKE_C_COMPILER}"
|
|
"\nCFLAGS: ${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_${BuildType}}"
|
|
"\nCXX: ${CMAKE_CXX_COMPILER}"
|
|
"\nCXXFLAGS: ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${BuildType}}"
|
|
"\n"
|
|
"\nCAF: ${CAF_VERSION}"
|
|
"\nPython bindings: ${python_summary}"
|
|
"\nZeek: ${zeek_summary}"
|
|
"\n=================================================================")
|
|
|
|
message("\n" ${summary} "\n")
|
|
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/config.summary ${summary})
|
|
|
|
include(UserChangedWarning)
|