zeek/auxil/binpac/cmake/FindSpicy.cmake
Patrick Kelley 8fd444092b initial
2025-05-07 15:35:15 -04:00

184 lines
7.4 KiB
CMake

# Copyright (c) 2020-2021 by the Zeek Project. See LICENSE for details.
#
# CMake helpers to find Spicy and build Spicy code.
#
# To have this find the Spicy toolchain, either set PATH to contain
# spicy-config, set SPICY_ROOT_DIR to the Spicy installation, or set
# SPICY_CONFIG to the binary.
#
# Output:
# SPICY_FOUND true if Spicy has been found
#
# If SPICY_FOUND is true:
#
# SPICYC full path to spicyc
# SPICY_BUILD_MODE Spicy's debug/release build mode
# SPICY_INCLUDE_DIRS_RUNTIME Spicy C++ include directories for the runtime
# SPICY_INCLUDE_DIRS_TOOLCHAIN Spicy C++ include directories for the toolchain
# SPICY_CXX_LIBRARY_DIRS_TOOLCHAIN Spicy C++ library directories
# SPICY_CXX_LIBRARY_DIRS_RUNTIME Spicy C++ library directories
# SPICY_CXX_FLAGS Spicy C++ flags with include directories
# SPICY_PREFIX Spicy installation prefix
# SPICY_VERSION Spicy version as a string
# SPICY_VERSION_NUMBER Spicy version as a numerical value
# SPICY_CMAKE_PATH Spicy cmake directory
# SPICY_HAVE_TOOLCHAIN True if the compiler is available
### Functions
# Configure build against Spicy.
macro (configure)
### Find spicy-config
if (NOT SPICY_CONFIG)
set(SPICY_CONFIG "$ENV{SPICY_CONFIG}")
endif ()
if (SPICY_CONFIG)
if (EXISTS "${SPICY_CONFIG}")
set(spicy_config "${SPICY_CONFIG}")
else ()
message(STATUS "'${SPICY_CONFIG}' does not exist")
endif ()
else ()
# Attempt to find `spicy-config` only with configured paths.
find_program(
spicy_config spicy-config
HINTS ${SPICY_ROOT_DIR}/bin
${SPICY_ROOT_DIR}/build/bin
$ENV{SPICY_ROOT_DIR}/bin
$ENV{SPICY_ROOT_DIR}/build/bin
# Try build directory of Spicy distribution we may be part of.
${PROJECT_SOURCE_DIR}/../../build/bin
NO_DEFAULT_PATH)
# If above search was not successful attempt to find the program in
# builtin search paths. CMake's `find_program` will only execute a new
# search if the output variable `spicy-config` is unset.
find_program(spicy_config spicy-config)
endif ()
if (NOT spicy_config)
message(STATUS "cannot determine location of Spicy installation")
set(HAVE_SPICY no)
else ()
message(STATUS "Found spicy-config: ${spicy_config}")
set(HAVE_SPICY yes)
set(SPICY_CONFIG "${spicy_config}" CACHE FILEPATH "")
### Determine properties.
run_spicy_config(SPICYC "--spicyc")
run_spicy_config(SPICY_BUILD_MODE "--build")
run_spicy_config(SPICY_PREFIX "--prefix")
run_spicy_config(SPICY_VERSION "--version")
run_spicy_config(SPICY_VERSION_NUMBER "--version-number")
run_spicy_config(SPICY_CMAKE_PATH "--cmake-path")
run_spicy_config(SPICY_HAVE_TOOLCHAIN "--have-toolchain")
run_spicy_config(SPICY_INCLUDE_DIRS_RUNTIME --include-dirs)
string(REPLACE " " ";" SPICY_INCLUDE_DIRS_RUNTIME "${SPICY_INCLUDE_DIRS_RUNTIME}")
run_spicy_config(SPICY_LIBRARY_DIRS_RUNTIME --libdirs-cxx-runtime)
string(REPLACE " " ";" SPICY_LIBRARY_DIRS_RUNTIME "${SPICY_LIBRARY_DIRS_RUNTIME}")
run_spicy_config(SPICY_INCLUDE_DIRS_TOOLCHAIN --include-dirs-toolchain)
string(REPLACE " " ";" SPICY_INCLUDE_DIRS_TOOLCHAIN "${SPICY_INCLUDE_DIRS_TOOLCHAIN}")
run_spicy_config(SPICY_LIBRARY_DIRS_TOOLCHAIN --libdirs-cxx-toolchain)
string(REPLACE " " ";" SPICY_LIBRARY_DIRS_TOOLCHAIN "${SPICY_LIBRARY_DIRS_TOOLCHAIN}")
find_library(
HILTI_LIBRARY
NAMES hilti
NO_DEFAULT_PATH
HINTS "${SPICY_LIBRARY_DIRS_TOOLCHAIN}" "${SPICY_LIBRARY_DIRS_RUNTIME}")
find_library(
SPICY_LIBRARY
NAMES spicy
NO_DEFAULT_PATH
HINTS "${SPICY_LIBRARY_DIRS_TOOLCHAIN}" "${SPICY_LIBRARY_DIRS_RUNTIME}")
add_library(hilti SHARED IMPORTED GLOBAL)
set_target_properties(hilti PROPERTIES IMPORTED_LOCATION "${HILTI_LIBRARY}")
target_include_directories(hilti BEFORE INTERFACE ${HILTI_INCLUDE_DIRS_TOOLCHAIN}
${HILTI_INCLUDE_DIRS_RUNTIME})
add_library(spicy SHARED IMPORTED GLOBAL)
set_target_properties(spicy PROPERTIES IMPORTED_LOCATION "${SPICY_LIBRARY}")
target_include_directories(spicy BEFORE INTERFACE ${SPICY_INCLUDE_DIRS_TOOLCHAIN}
${SPICY_INCLUDE_DIRS_RUNTIME})
endif ()
endmacro ()
# Checks that the Spicy version it at least the given version.
function (spicy_require_version version)
string(REGEX MATCH "([0-9]*)\.([0-9]*)\.([0-9]*).*" _ ${version})
math(EXPR version_number "${CMAKE_MATCH_1} * 10000 + ${CMAKE_MATCH_2} * 100 + ${CMAKE_MATCH_3}")
if ("${SPICY_VERSION_NUMBER}" LESS "${version_number}")
message(
FATAL_ERROR "Package requires at least Spicy version ${version}, have ${SPICY_VERSION}")
endif ()
endfunction ()
# Helper to link with `--whole-archive/-force-load`.
#
# This is adapted from https://github.com/horance-liu/flink.cmake
#
# With CMake >= 3.24, we could instead use LINK_LIBRARY, see
# https://cmake.org/cmake/help/v3.24/manual/cmake-generator-expressions.7.html#genex:LINK_LIBRARY
macro (spicy_get_runtime_libraries out debug)
if (debug)
set(hilti_rt ${HILTI_LIBRARY_RT_DEBUG})
set(spicy_rt ${SPICY_LIBRARY_RT_DEBUG})
else ()
set(hilti_rt ${HILTI_LIBRARY_RT})
set(spicy_rt ${SPICY_LIBRARY_RT})
endif ()
if (MSVC)
set(${out} "/WHOLEARCHIVE:${hilti_rt};/WHOLEARCHIVE:${spicy_rt}")
elseif (APPLE)
set(${out} "-Wl,-force_load;${hilti_rt};-Wl,-force_load;${spicy_rt}")
else ()
set(${out} "-Wl,--whole-archive;${hilti_rt};${spicy_rt};-Wl,--no-whole-archive")
endif ()
endmacro ()
# Runs `spicy-config` and stores its result in the given output variable.
function (run_spicy_config output)
execute_process(COMMAND "${spicy_config}" ${ARGN} OUTPUT_VARIABLE output_
OUTPUT_STRIP_TRAILING_WHITESPACE)
string(STRIP "${output_}" output_)
set(${output} "${output_}" PARENT_SCOPE)
endfunction ()
# Prints a summary of detected Spicy.
function (spicy_print_summary)
message("\n====================| Spicy Installation Summary |====================" "\n"
"\nFound Spicy: ${HAVE_SPICY}")
if (HAVE_SPICY)
message(
"\nVersion: ${SPICY_VERSION} (${SPICY_VERSION_NUMBER})"
"\nPrefix: ${SPICY_PREFIX}"
"\nBuild type: ${SPICY_BUILD_MODE}"
"\nHave toolchain: ${SPICY_HAVE_TOOLCHAIN}"
"\nSpicy compiler: ${SPICYC}")
else ()
message(
"\n Make sure spicy-config is in your PATH, or set SPICY_CONFIG to its location.")
endif ()
message("\n========================================================================\n")
endfunction ()
### Main
if (NOT HAVE_SPICY)
configure()
endif ()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Spicy DEFAULT_MSG HAVE_SPICY SPICY_CONFIG)