# Locate the deterministic MsQuic runtime used by cmvr-es. # # Default package layout: # dependency//third_party/msquic/v/ # # 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)