# Copyright 2019-2021 Collabora, Ltd. # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) # SPDX-License-Identifier: BSL-1.0 # # Original Author: # 2019-2021 Ryan Pavlik #.rst: # FindOpenXR # ---------- # # Find various parts of OpenXR 1.0. # # COMPONENTS # ^^^^^^^^^^ # # This module respects several COMPONENTS: ``headers``, ``loader``, ``registry``, ``specscripts``, and # ``sdkscripts``. If no components are specified, ``headers`` and ``loader`` are assumed. # # Targets # ^^^^^^^ # If the corresponding files are available and components are specified, the following imported targets # are created: # # ``OpenXR::openxr_loader`` # Link against to get the loader and headers. (Deprecated alias is ``OpenXR::Loader``) # # ``OpenXR::headers`` # Link against to get only the headers. (Deprecated alias is ``OpenXR::Headers``) # # ``OpenXR::headers_no_prototypes`` # Link against to get only the headers, plus the define to disable the prototypes. (Deprecated alias is ``OpenXR::HeadersNoPrototypes``) # # Cache variables # ^^^^^^^^^^^^^^^ # # The following cache variables may also be set to assist/control the operation of this module: # # Related to the ``OpenXR-SDK`` repo (this is the repo with pre-built headers), # the ``OpenXR-SDK-Source`` repo , or the internal Khronos GitLab ``openxr`` repo: # # ``OPENXR_SDK_SRC_DIR`` # Path to the root of the ``openxr``, ``OpenXR-SDK``, or ``OpenXR-SDK-Source`` repo source. # ``OPENXR_SDK_BUILD_DIR`` # Path to the root of the build directory corresponding to the ``openxr``, ``OpenXR-SDK``, or ``OpenXR-SDK-Source`` repo. # # Stolen from https://github.com/KhronosGroup/OpenXR-Hpp/blob/master/cmake/FindOpenXR.cmake at 6fcea9e472622c9c7f4df0b5f0bfe7ff5d8553f7 / Jun 22, 2021 # Normalize paths foreach(PATHVAR OPENXR_SDK_SRC_DIR OPENXR_SDK_BUILD_DIR) if(${${PATHVAR}}) file(TO_CMAKE_PATH ${${PATHVAR}} ${PATHVAR}) endif() endforeach() # Set up cache variables set(OPENXR_SDK_SRC_DIR "${OPENXR_SDK_SRC_DIR}" CACHE PATH "The root of your OpenXR-SDK, OpenXR-SDK-Source, or GitLab openxr source directory - see https://github.com/KhronosGroup/OpenXR-SDK" ) set(OPENXR_SDK_BUILD_DIR "${OPENXR_SDK_BUILD_DIR}" CACHE PATH "The root of your OpenXR-SDK, OpenXR-SDK-Source, or GitLab openxr build directory." ) # Currently only explicitly supporting 1.0 set(OPENXR_MAJOR_VER 1) set(OPENXR_MINOR_VER 0) set(OPENXR_OUT_DIR ${OPENXR_MAJOR_VER}.${OPENXR_MINOR_VER}) if(WIN32) set(OPENXR_STATIC ON) else() set(OPENXR_STATIC OFF) endif() find_package(PkgConfig QUIET) if(PKG_CONFIG_FOUND) pkg_check_modules(PC_OPENXR QUIET openxr) endif() ### # Assemble lists of places to look ### set(_oxr_include_search_dirs) set(_oxr_loader_search_dirs) set(_oxr_specscripts_search_dirs) set(_oxr_sdkscripts_search_dirs) set(_oxr_registry_search_dirs) find_package(OpenXR CONFIG) if(OpenXR_INCLUDE_DIR) list(APPEND _oxr_include_search_dirs ${OpenXR_INCLUDE_DIR}) endif() # These are macros to avoid a new variable scope. # Macro to extend search locations given a source dir. macro(_oxr_handle_potential_root_src_dir _dir) list(APPEND _oxr_include_search_dirs "${_dir}/include" "${_dir}/specification/out/${OPENXR_OUT_DIR}") list(APPEND _oxr_registry_search_dirs "${_dir}/specification/registry/") list(APPEND _oxr_specscripts_search_dirs "${_dir}/specification/scripts/") list(APPEND _oxr_sdkscripts_search_dirs "${_dir}/src/scripts/") endmacro() # Macro to extend search locations given a build dir. macro(_oxr_handle_potential_root_build_dir _dir) list(APPEND _oxr_include_search_dirs "${_dir}/include") list(APPEND _oxr_loader_search_dirs "${_dir}/src/loader") endmacro() if(PC_OPENXR_FOUND) list(APPEND _oxr_include_search_dirs ${PC_OPENXR_INCLUDE_DIRS}) list(APPEND _oxr_loader_search_dirs ${PC_OPENXR_LIBRARY_DIRS}) endif() set(_oxr_lib_path_suffixes) if(WIN32) unset(_UWP_SUFFIX) if(CMAKE_SYSTEM_NAME STREQUAL "WindowsStore") set(_UWP_SUFFIX _uwp) endif() if(CMAKE_GENERATOR_PLATFORM_UPPER MATCHES "ARM.*") if(CMAKE_SIZEOF_VOID_P EQUAL 8) set(_PLATFORM ARM64) else() set(_PLATFORM ARM) endif() else() if(CMAKE_SIZEOF_VOID_P EQUAL 8) set(_PLATFORM x64) else() set(_PLATFORM Win32) endif() endif() list(APPEND _oxr_lib_path_suffixes ${_PLATFORM}${_UWP_SUFFIX}/lib) # old builds if(MSVC_VERSION GREATER 1919) list(APPEND _oxr_lib_path_suffixes msvs2019_static/lib) endif() endif() # User-supplied directories if(OPENXR_SDK_SRC_DIR) _oxr_handle_potential_root_src_dir(${OPENXR_SDK_SRC_DIR}) endif() if(OPENXR_SDK_BUILD_DIR) _oxr_handle_potential_root_build_dir(${OPENXR_SDK_BUILD_DIR}) endif() # Guessed build dir based on src dir if(OPENXR_SDK_SRC_DIR) _oxr_handle_potential_root_build_dir("${OPENXR_SDK_SRC_DIR}/build") endif() # Guesses of sibling directories by name - last resort. foreach(_dir "${CMAKE_SOURCE_DIR}/../OpenXR-SDK" "${CMAKE_SOURCE_DIR}/../OpenXR-SDK-Source" "${CMAKE_SOURCE_DIR}/../openxr") _oxr_handle_potential_root_src_dir(${_dir}) _oxr_handle_potential_root_build_dir(${_dir}/build) endforeach() ### # Search for includes ### # This must also contain openxr/openxr_platform.h find_path( OPENXR_OPENXR_INCLUDE_DIR NAMES openxr/openxr.h PATHS ${_oxr_include_search_dirs}) find_path( OPENXR_PLATFORM_DEFINES_INCLUDE_DIR NAMES openxr/openxr_platform_defines.h PATHS ${_oxr_include_search_dirs}) ### # Search for other parts ### find_library( OPENXR_loader_LIBRARY NAMES libopenxr_loader openxr_loader openxr_loader-${OPENXR_MAJOR_VER}_${OPENXR_MINOR_VER} PATHS ${_oxr_loader_search_dirs} PATH_SUFFIXES ${_oxr_lib_path_suffixes}) find_path( OPENXR_SPECSCRIPTS_DIR NAMES reg.py PATHS ${_oxr_specscripts_search_dirs}) find_path( OPENXR_SDKSCRIPTS_DIR NAMES automatic_source_generator.py PATHS ${_oxr_sdkscripts_search_dirs}) find_file( OPENXR_REGISTRY NAMES xr.xml PATHS ${_oxr_registry_search_dirs}) ### # Fix up list of requested components ### if(NOT OpenXR_FIND_COMPONENTS) # Default to headers and loader set(OpenXR_FIND_COMPONENTS headers loader) endif() if("${OpenXR_FIND_COMPONENTS}" MATCHES "scripts" AND NOT "${OpenXR_FIND_COMPONENTS}" MATCHES "registry") # scripts depend on registry (mostly). list(APPEND OpenXR_FIND_COMPONENTS registry) endif() if("${OpenXR_FIND_COMPONENTS}" MATCHES "loader" AND NOT "${OpenXR_FIND_COMPONENTS}" MATCHES "headers") # loader depends on headers. list(APPEND OpenXR_FIND_COMPONENTS headers) endif() if("${OpenXR_FIND_COMPONENTS}" MATCHES "sdkscripts" AND NOT "${OpenXR_FIND_COMPONENTS}" MATCHES "specscripts") # source scripts depend on spec scripts. list(APPEND OpenXR_FIND_COMPONENTS specscripts) endif() ### # Determine if the various requested components are found. ### set(_oxr_component_required_vars) foreach(_comp IN LISTS OpenXR_FIND_COMPONENTS) if(${_comp} STREQUAL "headers") if(TARGET OpenXR::headers) set(OpenXR_headers_FOUND TRUE) mark_as_advanced(OPENXR_OPENXR_INCLUDE_DIR OPENXR_PLATFORM_DEFINES_INCLUDE_DIR) else() list(APPEND _oxr_component_required_vars OPENXR_OPENXR_INCLUDE_DIR OPENXR_PLATFORM_DEFINES_INCLUDE_DIR) if(EXISTS "${OPENXR_OPENXR_INCLUDE_DIR}/openxr/openxr.h" AND EXISTS "${OPENXR_OPENXR_INCLUDE_DIR}/openxr/openxr_platform.h" AND EXISTS "${OPENXR_OPENXR_INCLUDE_DIR}/openxr/openxr_reflection.h" AND EXISTS "${OPENXR_PLATFORM_DEFINES_INCLUDE_DIR}/openxr/openxr_platform_defines.h" ) set(OpenXR_headers_FOUND TRUE) mark_as_advanced(OPENXR_OPENXR_INCLUDE_DIR OPENXR_PLATFORM_DEFINES_INCLUDE_DIR) else() set(OpenXR_headers_FOUND FALSE) endif() endif() elseif(${_comp} STREQUAL "loader") if(TARGET OpenXR::openxr_loader) set(OpenXR_loader_FOUND TRUE) mark_as_advanced(OPENXR_loader_LIBRARY) set(OPENXR_loader_LIBRARY OpenXR::openxr_loader) else() list(APPEND _oxr_component_required_vars OPENXR_loader_LIBRARY) if(EXISTS "${OPENXR_loader_LIBRARY}") set(OpenXR_loader_FOUND TRUE) mark_as_advanced(OPENXR_loader_LIBRARY) else() set(OpenXR_loader_FOUND FALSE) endif() endif() elseif(${_comp} STREQUAL "registry") list(APPEND _oxr_component_required_vars OPENXR_REGISTRY) if(EXISTS "${OPENXR_REGISTRY}") set(OpenXR_registry_FOUND TRUE) mark_as_advanced(OPENXR_REGISTRY) else() set(OpenXR_registry_FOUND FALSE) endif() elseif(${_comp} STREQUAL "specscripts") list(APPEND _oxr_component_required_vars OPENXR_SPECSCRIPTS_DIR) if(EXISTS "${OPENXR_SPECSCRIPTS_DIR}/generator.py" AND EXISTS "${OPENXR_SPECSCRIPTS_DIR}/reg.py" AND EXISTS "${OPENXR_SPECSCRIPTS_DIR}/genxr.py") set(OpenXR_specscripts_FOUND TRUE) mark_as_advanced(OPENXR_SPECSCRIPTS_DIR) else() set(OpenXR_specscripts_FOUND FALSE) endif() elseif(${_comp} STREQUAL "sdkscripts") list(APPEND _oxr_component_required_vars OPENXR_SDKSCRIPTS_DIR) if(EXISTS "${OPENXR_SDKSCRIPTS_DIR}/automatic_source_generator.py" AND EXISTS "${OPENXR_SDKSCRIPTS_DIR}/src_genxr.py") set(OpenXR_sdkscripts_FOUND TRUE) mark_as_advanced(OPENXR_SDKSCRIPTS_DIR) else() set(OpenXR_sdkscripts_FOUND FALSE) endif() else() message(WARNING "${_comp} is not a recognized OpenXR component") set(OpenXR_${_comp}_FOUND FALSE) endif() endforeach() unset(_comp) ### # FPHSA call ### include(FindPackageHandleStandardArgs) find_package_handle_standard_args( OpenXR REQUIRED_VARS ${_oxr_component_required_vars} HANDLE_COMPONENTS FAIL_MESSAGE "Could NOT find the requested OpenXR components, try setting OPENXR_SDK_SRC_DIR and/or OPENXR_SDK_BUILD_DIR" ) ### # If found, set variables and create targets ### # Component: headers if(OpenXR_headers_FOUND AND NOT TARGET OpenXR::headers) set(OPENXR_INCLUDE_DIRS ${OPENXR_OPENXR_INCLUDE_DIR} ${OPENXR_PLATFORM_DEFINES_INCLUDE_DIR}) list(REMOVE_DUPLICATES OPENXR_INCLUDE_DIRS) # This target just provides the headers with prototypes. # You may have linker errors if you try using this # without linking to the loader add_library(OpenXR::headers INTERFACE IMPORTED) # This is not duplication: interface system dirs just marks as system. set_target_properties( OpenXR::headers PROPERTIES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "${OPENXR_INCLUDE_DIRS}" INTERFACE_INCLUDE_DIRECTORIES "${OPENXR_INCLUDE_DIRS}") endif() # Back-compat if(TARGET OpenXR::headers AND NOT TARGET OpenXR::Headers) add_library(OpenXR::Headers INTERFACE IMPORTED) set_target_properties(OpenXR::Headers PROPERTIES INTERFACE_LINK_LIBRARIES "OpenXR::headers") endif() # This target just provides the headers, without any prototypes. # Finding and loading the loader at runtime is your problem. if(TARGET OpenXR::headers AND NOT TARGET OpenXR::headers_no_prototypes) add_library(OpenXR::headers_no_prototypes INTERFACE IMPORTED) set_target_properties( OpenXR::headers_no_prototypes PROPERTIES INTERFACE_COMPILE_DEFINITIONS "XR_NO_PROTOTYPES" INTERFACE_LINK_LIBRARIES "OpenXR::headers") endif() if(TARGET OpenXR::headers AND NOT TARGET OpenXR::HeadersNoPrototypes) add_library(OpenXR::HeadersNoPrototypes INTERFACE IMPORTED) set_target_properties( OpenXR::HeadersNoPrototypes PROPERTIES INTERFACE_COMPILE_DEFINITIONS "XR_NO_PROTOTYPES" INTERFACE_LINK_LIBRARIES "OpenXR::headers") endif() # Component: loader if(OpenXR_loader_FOUND AND OpenXR_headers_FOUND AND NOT TARGET OpenXR::openxr_loader) set(_oxr_loader_interface_libs OpenXR::headers) # include dl library for statically-linked loader get_filename_component(_oxr_loader_ext ${OPENXR_loader_LIBRARY} EXT) if(_oxr_loader_ext STREQUAL CMAKE_STATIC_LIBRARY_SUFFIX) set(_oxr_loader_lib_type STATIC) list(APPEND _oxr_loader_interface_libs ${CMAKE_DL_LIBS}) else() set(_oxr_loader_lib_type SHARED) endif() add_library(OpenXR::openxr_loader UNKNOWN IMPORTED) set_target_properties( OpenXR::openxr_loader PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES "C" IMPORTED_LOCATION "${OPENXR_loader_LIBRARY}" INTERFACE_LINK_LIBRARIES "${_oxr_loader_interface_libs}") endif() # Back-compat if(TARGET OpenXR::openxr_loader AND NOT TARGET OpenXR::Loader) add_library(OpenXR::Loader INTERFACE IMPORTED) set_target_properties(OpenXR::Loader PROPERTIES INTERFACE_LINK_LIBRARIES "OpenXR::openxr_loader") endif()