cmvr-es/cmake/FindMsQuic.cmake

185 lines
7.0 KiB
CMake
Raw Normal View History

# Locate the deterministic MsQuic runtime used by cmvr-es.
#
# Default package layout:
# dependency/<arch>/third_party/msquic/v<CMVR_MSQUIC_VERSION>/
#
# An explicit CMVR_MSQUIC_ROOT may point at another installation prefix.
# System search paths are deliberately disabled unless
# CMVR_ALLOW_SYSTEM_MSQUIC=ON, so two developer machines cannot silently link
# different MsQuic versions.
#
# Result:
# MsQuic_FOUND
# MsQuic_VERSION
# MsQuic_INCLUDE_DIR
# MsQuic_LIBRARY
# MsQuic_ROOT (empty for the opt-in system fallback)
# MsQuic::msquic
include_guard(GLOBAL)
set(CMVR_MSQUIC_VERSION "2.5.9" CACHE STRING
"Exact MsQuic version expected by cmvr-es")
set(CMVR_MSQUIC_ROOT "" CACHE PATH
"Explicit MsQuic installation prefix")
option(CMVR_ALLOW_SYSTEM_MSQUIC
"Allow MsQuic discovery outside the repository or CMVR_MSQUIC_ROOT"
OFF)
option(CMVR_REQUIRE_MSQUIC
"Fail configuration when the requested MsQuic backend is unavailable"
OFF)
if(CMVR_MSQUIC_VERSION STREQUAL "")
message(FATAL_ERROR "CMVR_MSQUIC_VERSION must not be empty")
endif()
set(_cmvr_msquic_roots)
if(CMVR_MSQUIC_ROOT)
list(APPEND _cmvr_msquic_roots "${CMVR_MSQUIC_ROOT}")
elseif(DEFINED PROJECT_SOURCE_DIR AND DEFINED ARCH)
list(APPEND _cmvr_msquic_roots
"${PROJECT_SOURCE_DIR}/dependency/${ARCH}/third_party/msquic/v${CMVR_MSQUIC_VERSION}")
endif()
# Do not share find_path/find_library cache entries between the deterministic
# root lookup and the explicitly enabled system fallback. Every configure
# checks the selected files again, so adding/removing a repository package in
# an existing build directory cannot leave a stale system result behind.
unset(MsQuic_INCLUDE_DIR CACHE)
unset(MsQuic_LIBRARY CACHE)
set(MsQuic_INCLUDE_DIR "")
set(MsQuic_LIBRARY "")
set(MsQuic_ROOT "")
set(_cmvr_msquic_selected_root "")
foreach(_cmvr_msquic_root IN LISTS _cmvr_msquic_roots)
unset(_cmvr_msquic_root_include)
unset(_cmvr_msquic_root_library)
find_path(_cmvr_msquic_root_include
NAMES msquic.h
PATHS "${_cmvr_msquic_root}"
PATH_SUFFIXES include
NO_DEFAULT_PATH
NO_CACHE)
find_library(_cmvr_msquic_root_library
NAMES msquic libmsquic
PATHS "${_cmvr_msquic_root}"
PATH_SUFFIXES lib lib64 bin
NO_DEFAULT_PATH
NO_CACHE)
if(_cmvr_msquic_root_include AND _cmvr_msquic_root_library)
file(REAL_PATH "${_cmvr_msquic_root}" _cmvr_msquic_root_real)
file(REAL_PATH "${_cmvr_msquic_root_include}/msquic.h"
_cmvr_msquic_header_real)
file(REAL_PATH "${_cmvr_msquic_root_library}"
_cmvr_msquic_library_real)
string(FIND "${_cmvr_msquic_header_real}"
"${_cmvr_msquic_root_real}/"
_cmvr_msquic_header_index)
string(FIND "${_cmvr_msquic_library_real}"
"${_cmvr_msquic_root_real}/"
_cmvr_msquic_library_index)
if(_cmvr_msquic_header_index EQUAL 0 AND
_cmvr_msquic_library_index EQUAL 0)
set(MsQuic_INCLUDE_DIR "${_cmvr_msquic_root_include}")
set(MsQuic_LIBRARY "${_cmvr_msquic_root_library}")
set(MsQuic_ROOT "${_cmvr_msquic_root_real}")
set(_cmvr_msquic_selected_root "${_cmvr_msquic_root_real}")
break()
endif()
endif()
endforeach()
set(_cmvr_msquic_selected_system FALSE)
if(NOT _cmvr_msquic_selected_root AND CMVR_ALLOW_SYSTEM_MSQUIC)
unset(_cmvr_msquic_system_include)
unset(_cmvr_msquic_system_library)
find_path(_cmvr_msquic_system_include
NAMES msquic.h
NO_CACHE)
find_library(_cmvr_msquic_system_library
NAMES msquic libmsquic
NO_CACHE)
if(_cmvr_msquic_system_include AND _cmvr_msquic_system_library)
file(REAL_PATH "${_cmvr_msquic_system_include}/msquic.h"
_cmvr_msquic_header_real)
file(REAL_PATH "${_cmvr_msquic_system_library}"
_cmvr_msquic_library_real)
string(REGEX REPLACE "/include(/.*)?$" ""
_cmvr_msquic_system_include_prefix
"${_cmvr_msquic_header_real}")
string(REGEX REPLACE "/lib(64)?(/.*)?$" ""
_cmvr_msquic_system_library_prefix
"${_cmvr_msquic_library_real}")
if(NOT "${_cmvr_msquic_system_include_prefix}" STREQUAL
"${_cmvr_msquic_header_real}" AND
NOT "${_cmvr_msquic_system_library_prefix}" STREQUAL
"${_cmvr_msquic_library_real}" AND
"${_cmvr_msquic_system_include_prefix}" STREQUAL
"${_cmvr_msquic_system_library_prefix}")
set(MsQuic_INCLUDE_DIR "${_cmvr_msquic_system_include}")
set(MsQuic_LIBRARY "${_cmvr_msquic_system_library}")
set(_cmvr_msquic_selected_system TRUE)
endif()
endif()
endif()
set(_cmvr_msquic_version_valid FALSE)
set(MsQuic_VERSION "")
if(MsQuic_INCLUDE_DIR AND MsQuic_LIBRARY)
if(_cmvr_msquic_selected_root)
set(_cmvr_msquic_build_info
"${_cmvr_msquic_selected_root}/BUILD-INFO.txt")
if(EXISTS "${_cmvr_msquic_build_info}")
file(STRINGS "${_cmvr_msquic_build_info}"
_cmvr_msquic_version_line
REGEX "^msquic_version="
LIMIT_COUNT 1)
string(REGEX REPLACE "^msquic_version=" ""
MsQuic_VERSION "${_cmvr_msquic_version_line}")
file(STRINGS "${_cmvr_msquic_build_info}"
_cmvr_msquic_arch_line
REGEX "^dependency_arch="
LIMIT_COUNT 1)
string(REGEX REPLACE "^dependency_arch=" ""
_cmvr_msquic_detected_arch
"${_cmvr_msquic_arch_line}")
if("${MsQuic_VERSION}" STREQUAL "${CMVR_MSQUIC_VERSION}" AND
(NOT DEFINED ARCH OR
"${_cmvr_msquic_detected_arch}" STREQUAL "${ARCH}"))
set(_cmvr_msquic_version_valid TRUE)
endif()
endif()
elseif(_cmvr_msquic_selected_system)
# Runtime version verification is intentionally unavailable in this
# opt-in, non-reproducible fallback mode.
set(MsQuic_VERSION "system-unverified")
set(_cmvr_msquic_version_valid TRUE)
endif()
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(MsQuic
REQUIRED_VARS
MsQuic_INCLUDE_DIR
MsQuic_LIBRARY
_cmvr_msquic_version_valid
VERSION_VAR MsQuic_VERSION)
if(CMVR_REQUIRE_MSQUIC AND NOT MsQuic_FOUND)
string(JOIN "\n " _cmvr_msquic_expected_roots
${_cmvr_msquic_roots})
message(FATAL_ERROR
"MsQuic v${CMVR_MSQUIC_VERSION} is required but was not found.\n"
"Expected one of:\n ${_cmvr_msquic_expected_roots}\n"
"Build it with script/build_msquic.sh before configuring cmvr-es.")
endif()
if(MsQuic_FOUND AND NOT TARGET MsQuic::msquic)
add_library(MsQuic::msquic UNKNOWN IMPORTED)
set_target_properties(MsQuic::msquic PROPERTIES
IMPORTED_LOCATION "${MsQuic_LIBRARY}"
INTERFACE_INCLUDE_DIRECTORIES "${MsQuic_INCLUDE_DIR}")
endif()
mark_as_advanced(MsQuic_INCLUDE_DIR MsQuic_LIBRARY)