Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ZeekBundle for integrating third-party components into our builds #117

Merged
merged 1 commit into from
Jul 11, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
138 changes: 138 additions & 0 deletions ZeekBundle.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
# 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 <name>
# FETCH (URL <url> | GIT_REPOSITORY <repo> GIT_TAG <tag> | SOURCE_DIR <path>)
# [CONFIGURE <args>]
# )
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})
# 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 ()
Loading