# CMake dependencies. include(FetchContent) # Users may override this path to place the compiled packages elsewhere. set(ZEEK_BUNDLE_PREFIX "${PROJECT_BINARY_DIR}/zeek-bundle" CACHE STRING "Path to the Zeek packages cache directory") # Opt-in to changed CMake behavior for fetching ZIP files. if (POLICY CMP0135) cmake_policy(SET CMP0135 NEW) endif () # Tries to find a package in the Zeek package cache. function (ZeekBundle_Find name) find_package(${name} CONFIG QUIET NO_DEFAULT_PATH HINTS ${ZEEK_BUNDLE_PREFIX}) if (${name}_FOUND) set(ZeekBundle_FOUND ON PARENT_SCOPE) else () set(ZeekBundle_FOUND OFF PARENT_SCOPE) endif () endfunction () # Runs the build and install steps for an external project. function (ZeekBundle_BuildStep name type binDir) # Build the external project. message(STATUS "Building bundled project: ${name} as ${type}") execute_process( COMMAND "${CMAKE_COMMAND}" --build "${binDir}" --config ${type} OUTPUT_FILE "${binDir}/build${type}.out" ERROR_FILE "${binDir}/build${type}.err" RESULT_VARIABLE buildResult) if (NOT buildResult EQUAL 0) file(READ "${binDir}/build${type}.err" cmakeErr) message(FATAL_ERROR "Failed to build ${name}:\n\n${cmakeErr}") endif () # Install the external project. message(STATUS "Installing bundled project: ${name} as ${type}") execute_process( COMMAND "${CMAKE_COMMAND}" --build "${binDir}" --config ${type} --target install OUTPUT_FILE "${binDir}/install${type}.out" ERROR_FILE "${binDir}/install${type}.err" RESULT_VARIABLE installResult) if (NOT installResult EQUAL 0) file(READ "${binDir}/install${type}.err" cmakeErr) message(FATAL_ERROR "Failed to install ${name}:\n\n${cmakeErr}") endif () endfunction () # Builds an external project at configure time. function (ZeekBundle_Build name srcDir binDir) # Extra arguments are passed as CMake options to the external project. set(cmakeArgs "") foreach (arg IN LISTS ARGN) list(APPEND cmakeArgs "-D${arg}") endforeach () # Make sure we can build debug and release versions of the project separately. list(APPEND cmakeArgs "-DCMAKE_DEBUG_POSTFIX=d") # Run CMake for the external project. message(STATUS "Configuring bundled project: ${name}") execute_process( COMMAND "${CMAKE_COMMAND}" -G "${CMAKE_GENERATOR}" ${cmakeArgs} -DBUILD_SHARED_LIBS=OFF -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DENABLE_TESTING=OFF "-DCMAKE_INSTALL_PREFIX=${ZEEK_BUNDLE_PREFIX}" "${srcDir}" WORKING_DIRECTORY "${binDir}" OUTPUT_FILE "${binDir}/cmake.out" ERROR_FILE "${binDir}/cmake.err" RESULT_VARIABLE cmakeResult) if (NOT cmakeResult EQUAL 0) file(READ "${binDir}/cmake.err" cmakeErr) message(FATAL_ERROR "Failed to configure external project ${name}:\n\n${cmakeErr}") endif () get_property(isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) if (isMultiConfig) zeekbundle_buildstep(${name} Debug ${binDir}) zeekbundle_buildstep(${name} Release ${binDir}) else () # On Windows, we cannot mix debug and release libraries. if (WIN32) zeekbundle_buildstep(${name} ${CMAKE_BUILD_TYPE} ${binDir}) else () zeekbundle_buildstep(${name} Release ${binDir}) endif () endif () endfunction () # Adds a bundled package to Zeek. # # Usage: # ZeekBundle_Add( # NAME # FETCH (URL | GIT_REPOSITORY GIT_TAG | SOURCE_DIR ) # [CONFIGURE ] # ) function (ZeekBundle_Add) # Parse the function arguments. cmake_parse_arguments(arg "" "NAME" "FETCH;CONFIGURE" ${ARGN}) if (NOT arg_NAME) message(FATAL_ERROR "ZeekBundle_Add: mandatory argument NAME is missing!") endif () if (NOT arg_FETCH) message(FATAL_ERROR "ZeekBundle_Add: mandatory argument FETCH is missing!") endif () # Use find_package if the user explicitly requested the package. if (DEFINED ${arg_NAME}_ROOT) message(STATUS "ZeekBundle: use system library for ${arg_NAME}") find_package( ${arg_NAME} CONFIG QUIET REQUIRED NO_DEFAULT_PATH PATHS ${${arg_NAME}_ROOT}) return() endif () # Check if we already have the package. zeekbundle_find(${arg_NAME}) if (ZeekBundle_FOUND) return() endif () # Fetch the package by delegating to FetchContent. FetchContent_Declare(dl_${arg_NAME} ${arg_FETCH}) string(TOLOWER "dl_${arg_NAME}" internalName) FetchContent_Populate(${internalName} SOURCE_DIR ${arg_FETCH}) file(MAKE_DIRECTORY "${${internalName}_BINARY_DIR}") # Build the package and verify that it was found. zeekbundle_build(${arg_NAME} "${${internalName}_SOURCE_DIR}" "${${internalName}_BINARY_DIR}" ${arg_CONFIGURE}) find_package( ${arg_NAME} CONFIG QUIET REQUIRED NO_DEFAULT_PATH PATHS ${ZEEK_BUNDLE_PREFIX}) endfunction ()