cmvr-es/cmake/FindMsQuic.cmake
xtkuang 428ee328de feat: complete QUIC edge integration
Vendor MsQuic with build and install support, add DeviceManager status to configurable heartbeats, and report only enabled devices.

Add the local QUIC gateway, protocol coverage, real MsQuic E2E tests, process smoke tests, and updated integration documentation.
2026-07-24 12:35:04 +08:00

185 lines
7.0 KiB
CMake

# 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)