Cleanup CMake finding of Vulkan & installation code

Adds extensive integration tests that exercise the various ways of finding
the Vulkan-Headers.

vk-bootstrap should now use the Vulkan-Headers or Vulkan::Headers targets if
they were already defined (such as is the case of FetchContent), and will
look for the VulkanHeaders package and Vulkan package as a fallback, and will
FetchContent Vulkan-Headers directly if that fails.

This should make integration seamless with the various ways vulkan-headers
is acquired.

The vk-bootstrap-vulkan-headers target was dropped in favor of directly
linking to Vulkan-Headers (creating a target by that name if none exists).
This commit is contained in:
Charles Giessen 2023-11-30 13:43:00 -07:00 committed by Charles Giessen
parent 34be5eb2c5
commit f223c8d5ae
7 changed files with 222 additions and 47 deletions

View File

@ -1,39 +1,57 @@
cmake_minimum_required(VERSION 3.15 FATAL_ERROR)
cmake_minimum_required(VERSION 3.15)
include(gen/CurrentBuildVulkanVersion.cmake)
project(VulkanBootstrap
LANGUAGES CXX
DESCRIPTION "A Vulkan utility library to ease the initialization steps in Vulkan")
DESCRIPTION "A Vulkan utility library to ease the initialization steps in Vulkan"
VERSION ${VK_BOOTSTRAP_SOURCE_HEADER_VERSION})
option(VK_BOOTSTRAP_DISABLE_WARNINGS "Disable warnings during compilation" OFF)
option(VK_BOOTSTRAP_WERROR "Enable warnings as errors during compilation" OFF)
add_library(vk-bootstrap-vulkan-headers INTERFACE)
if (CMAKE_VERSION VERSION_LESS "3.21")
# By default, only build tests & install if this repo is standalone, but still allow configuration by the user
string(COMPARE EQUAL ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_SOURCE_DIR} PROJECT_IS_TOP_LEVEL)
endif()
set(VK_BOOTSTRAP_VULKAN_HEADER_DIR "" CACHE STRING "Specify the location of the Vulkan-Headers include directory.")
option(VK_BOOTSTRAP_TEST "Test Vk-Bootstrap using Catch2 as well as build examples" ${PROJECT_IS_TOP_LEVEL})
option(VK_BOOTSTRAP_INSTALL "Enable warnings as errors during compilation" ${PROJECT_IS_TOP_LEVEL})
set(VK_BOOTSTRAP_VULKAN_HEADER_DIR "" CACHE FILEPATH "Specify the location of the Vulkan-Headers include directory.")
mark_as_advanced(VK_BOOTSTRAP_VULKAN_HEADER_DIR)
include(gen/CurrentBuildVulkanVersion.cmake)
# Check if the user has set this variable explicitly
if(IS_DIRECTORY ${VK_BOOTSTRAP_VULKAN_HEADER_DIR})
add_library(Vulkan-Headers INTERFACE)
add_library(Vulkan::Headers ALIAS Vulkan-Headers)
target_include_directories(Vulkan-Headers INTERFACE $<BUILD_INTERFACE:${VK_BOOTSTRAP_VULKAN_HEADER_DIR}>)
if(NOT "${VK_BOOTSTRAP_VULKAN_HEADER_DIR}" STREQUAL "")
target_include_directories(vk-bootstrap-vulkan-headers INTERFACE $<BUILD_INTERFACE:${VK_BOOTSTRAP_VULKAN_HEADER_DIR}>)
else ()
find_package(Vulkan QUIET)
if(${Vulkan_INCLUDE_DIR} STREQUAL "Vulkan_INCLUDE_DIR-NOTFOUND")
include(FetchContent)
FetchContent_Declare(
VulkanHeaders
GIT_REPOSITORY https://github.com/KhronosGroup/Vulkan-Headers
GIT_TAG ${VK_BOOTSTRAP_SOURCE_HEADER_VERSION_GIT_TAG}
)
FetchContent_MakeAvailable(VulkanHeaders)
target_link_libraries(vk-bootstrap-vulkan-headers INTERFACE Vulkan::Headers)
else()
set_target_properties(vk-bootstrap-vulkan-headers PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${Vulkan_INCLUDE_DIR})
# Check if the target is already defined
elseif(NOT TARGET Vulkan::Headers)
# Try looking for the VulkanHeaders package directly
find_package(VulkanHeaders CONFIG QUIET)
if (NOT VulkanHeaders_FOUND)
# Try looking using the CMake built in Vulkan support
find_package(Vulkan QUIET)
if(NOT Vulkan_FOUND)
# Lastly just grab Vulkan-Headers directly using FetchContent
include(FetchContent)
FetchContent_Declare(
Vulkan-Headers-for-vk-bootstrap
GIT_REPOSITORY https://github.com/KhronosGroup/Vulkan-Headers
GIT_TAG ${VK_BOOTSTRAP_SOURCE_HEADER_VERSION_GIT_TAG}
)
FetchContent_MakeAvailable(Vulkan-Headers-for-vk-bootstrap)
# If we had to use FetchContent to get the headers, disable installing
set(VK_BOOTSTRAP_INSTALL OFF)
endif()
endif()
endif()
add_library(vk-bootstrap STATIC src/VkBootstrap.h src/VkBootstrap.cpp src/VkBootstrapDispatch.h)
add_library(vk-bootstrap::vk-bootstrap ALIAS vk-bootstrap)
if(NOT TARGET Vulkan::Headers)
message(FATAL_ERROR "Unable to locate required dependency Vulkan::Headers!")
endif()
add_library(vk-bootstrap-compiler-warnings INTERFACE)
@ -68,36 +86,73 @@ if(NOT VK_BOOTSTRAP_DISABLE_WARNINGS)
endif()
endif()
add_library(vk-bootstrap STATIC src/VkBootstrap.h src/VkBootstrap.cpp src/VkBootstrapDispatch.h)
add_library(vk-bootstrap::vk-bootstrap ALIAS vk-bootstrap)
target_include_directories(vk-bootstrap PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
$<INSTALL_INTERFACE:include>)
target_link_libraries(vk-bootstrap
PUBLIC
Vulkan::Headers
PRIVATE
vk-bootstrap-compiler-warnings
vk-bootstrap-vulkan-headers
${CMAKE_DL_LIBS})
target_compile_features(vk-bootstrap PUBLIC cxx_std_17)
include(GNUInstallDirs)
install(FILES src/VkBootstrap.h src/VkBootstrapDispatch.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
install(TARGETS
vk-bootstrap
vk-bootstrap-compiler-warnings
vk-bootstrap-vulkan-headers
EXPORT
vk-bootstrap-targets)
# By default, we want to only build tests if this repo is built standalone, but still should be configurable by the user
if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
set(VK_BOOTSTRAP_TEST_DEFAULT_VALUE ON)
else()
set(VK_BOOTSTRAP_TEST_DEFAULT_VALUE OFF)
endif()
option(VK_BOOTSTRAP_TEST "Test Vk-Bootstrap with glfw and Catch2" ${VK_BOOTSTRAP_TEST_DEFAULT_VALUE})
if(VK_BOOTSTRAP_TEST)
enable_testing()
add_subdirectory(ext)
add_subdirectory(tests)
add_subdirectory(example)
endif ()
if (VK_BOOTSTRAP_INSTALL)
include(GNUInstallDirs)
include(CMakePackageConfigHelpers)
install(FILES src/VkBootstrap.h src/VkBootstrapDispatch.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
install(
TARGETS vk-bootstrap vk-bootstrap-compiler-warnings
EXPORT vk-bootstrap-targets
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)
install(
EXPORT vk-bootstrap-targets
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/vk-bootstrap
NAMESPACE vk-bootstrap::
)
# Create vk-bootstrap-config.cmake
set(VK_BOOTSTRAP_EXPORT_TARGETS ${CMAKE_INSTALL_LIBDIR}/cmake/vk-bootstrap/vk-bootstrap-targets.cmake)
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/vk-bootstrap-config.cmake.in" [=[
@PACKAGE_INIT@
# Try to find Vulkan-Headers using find_package. Assume the package is available through either Vulkan-Headers or the older Vulkan
# Package managers should have Vulkan-Headers be a dependency of this repo.
find_package(VulkanHeaders CONFIG)
if (NOT VulkanHeaders_FOUND)
find_package(Vulkan)
if (NOT Vulkan_FOUND)
message(FATAL_ERROR "Unable to locate required dependency Vulkan::Headers!")
endif()
endif()
include(@PACKAGE_VK_BOOTSTRAP_EXPORT_TARGETS@)
]=])
configure_package_config_file(
${CMAKE_CURRENT_BINARY_DIR}/vk-bootstrap-config.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/vk-bootstrap-config.cmake
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/vk-bootstrap
PATH_VARS VK_BOOTSTRAP_EXPORT_TARGETS
NO_SET_AND_CHECK_MACRO
NO_CHECK_REQUIRED_COMPONENTS_MACRO
)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/vk-bootstrap-config.cmake
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/vk-bootstrap
)
endif()

View File

@ -4,7 +4,7 @@ target_link_libraries(vk-bootstrap-triangle
glfw
vk-bootstrap
vk-bootstrap-compiler-warnings
vk-bootstrap-vulkan-headers)
Vulkan::Headers)
target_include_directories(vk-bootstrap-triangle PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) # path to build directory for shaders
add_custom_command(

View File

@ -7,7 +7,7 @@ option(CATCH_BUILD_TESTING "" OFF)
option(CATCH_ENABLE_WERROR "" OFF)
option(CATCH_INSTALL_DOCS "" OFF)
option(CATCH_INSTALL_HELPERS "" OFF)
option(CATCH_INSTALL_EXTRAS "" ON)
option(CATCH_INSTALL_EXTRAS "" OFF)
include(FetchContent)
FetchContent_Declare(

View File

@ -7,11 +7,12 @@ else()
endif()
target_link_libraries(VulkanMock
PUBLIC
vk-bootstrap-vulkan-headers
Vulkan::Headers
PRIVATE
vk-bootstrap-compiler-warnings
)
target_compile_features(VulkanMock PUBLIC cxx_std_17)
target_compile_definitions(VulkanMock PUBLIC VK_NO_PROTOTYPES)
add_executable(vk-bootstrap-test
vulkan_library_loader.hpp
@ -24,7 +25,7 @@ add_executable(vk-bootstrap-test
target_link_libraries(vk-bootstrap-test
PRIVATE
vk-bootstrap
vk-bootstrap-vulkan-headers
Vulkan::Headers
vk-bootstrap-compiler-warnings
VulkanMock
Catch2::Catch2WithMain
@ -37,6 +38,79 @@ elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
endif()
list(APPEND CMAKE_MODULE_PATH ${Catch2_SOURCE_DIR}/extras)
include(CTest)
include(Catch)
catch_discover_tests(vk-bootstrap-test)
# Test add_subdirectory suppport using fetch content vulkan headers
add_test(NAME integration.add_subdirectory.fetch_content_vulkan_headers
COMMAND ${CMAKE_CTEST_COMMAND}
--build-and-test ${CMAKE_CURRENT_LIST_DIR}/integration
${CMAKE_CURRENT_BINARY_DIR}/add_subdirectory/fetch_content_vulkan_headers
--build-generator ${CMAKE_GENERATOR}
--build-options -DADD_SUBDIRECTORY_TESTING=ON -DVULKAN_HEADER_VERSION_GIT_TAG=${VK_BOOTSTRAP_SOURCE_HEADER_VERSION_GIT_TAG}
)
get_target_property(vulkan_headers_include_dir Vulkan::Headers INTERFACE_INCLUDE_DIRECTORIES)
# Test add_subdirectory suppport by setting VK_BOOTSTRAP_VULKAN_HEADER_DIR to the include directory of the Vulkan::Headers
add_test(NAME integration.add_subdirectory.vulkan_header_dir
COMMAND ${CMAKE_CTEST_COMMAND}
--build-and-test ${CMAKE_CURRENT_LIST_DIR}/integration
${CMAKE_CURRENT_BINARY_DIR}/add_subdirectory/vulkan_header_dir
--build-generator ${CMAKE_GENERATOR}
--build-options -DADD_SUBDIRECTORY_TESTING=ON -DVK_BOOTSTRAP_VULKAN_HEADER_DIR=${vulkan_headers_include_dir}
)
set(test_install_dir "${CMAKE_CURRENT_BINARY_DIR}/install")
add_test(NAME integration.install
COMMAND ${CMAKE_COMMAND} --install ${CMAKE_BINARY_DIR} --prefix ${test_install_dir} --config $<CONFIG>
)
find_package(VulkanHeaders CONFIG)
if (VulkanHeaders_FOUND)
set(vulkan_headers_package_location ${VulkanHeaders_DIR})
# Test add_subdirectory suppport using find_package(VulkanHeaders)
add_test(NAME integration.add_subdirectory.find_package_vulkan_headers
COMMAND ${CMAKE_CTEST_COMMAND}
--build-and-test ${CMAKE_CURRENT_LIST_DIR}/integration
${CMAKE_CURRENT_BINARY_DIR}/add_subdirectory/find_package_vulkan_headers
--build-generator ${CMAKE_GENERATOR}
--build-options -DADD_SUBDIRECTORY_TESTING=ON -DCMAKE_PREFIX_PATH=${vulkan_headers_install_dir}
)
# Test find_package suppport using find_package(VulkanHeaders)
add_test(NAME integration.find_package.find_package_vulkan_headers
COMMAND ${CMAKE_CTEST_COMMAND}
--build-and-test ${CMAKE_CURRENT_LIST_DIR}/integration
${CMAKE_CURRENT_BINARY_DIR}/find_package/find_package_vulkan_headers
--build-generator ${CMAKE_GENERATOR}
--build-options -DFIND_PACKAGE_TESTING=ON "-DCMAKE_PREFIX_PATH=${vulkan_headers_install_dir};${test_install_dir}"
)
set_tests_properties(integration.find_package.find_package_vulkan_headers PROPERTIES DEPENDS integration.install)
endif()
find_package(Vulkan)
if (Vulkan_FOUND)
# Test add_subdirectory suppport using find_package(Vulkan)
add_test(NAME integration.add_subdirectory.find_package_vulkan
COMMAND ${CMAKE_CTEST_COMMAND}
--build-and-test ${CMAKE_CURRENT_LIST_DIR}/integration
${CMAKE_CURRENT_BINARY_DIR}/add_subdirectory/find_package_vulkan
--build-generator ${CMAKE_GENERATOR}
--build-options -DADD_SUBDIRECTORY_TESTING=ON -DFIND_PACKAGE_VULKAN=ON
)
# Test find_package suppport using find_package(Vulkan)
add_test(NAME integration.find_package.find_package_vulkan
COMMAND ${CMAKE_CTEST_COMMAND}
--build-and-test ${CMAKE_CURRENT_LIST_DIR}/integration
${CMAKE_CURRENT_BINARY_DIR}/find_package/find_package_vulkan
--build-generator ${CMAKE_GENERATOR}
--build-options -DFIND_PACKAGE_TESTING=ON -DCMAKE_PREFIX_PATH=${test_install_dir} -DFIND_PACKAGE_VULKAN=ON
)
set_tests_properties(integration.find_package.find_package_vulkan PROPERTIES DEPENDS integration.install)
endif()

View File

@ -0,0 +1,41 @@
cmake_minimum_required(VERSION 3.14.2)
project(IntegrationTests LANGUAGES CXX)
if (VULKAN_HEADER_VERSION_GIT_TAG)
include(FetchContent)
FetchContent_Declare(
VulkanHeadersIntegrationTest
GIT_REPOSITORY https://github.com/KhronosGroup/Vulkan-Headers
GIT_TAG ${VULKAN_HEADER_VERSION_GIT_TAG}
)
FetchContent_MakeAvailable(VulkanHeadersIntegrationTest)
if (NOT TARGET Vulkan::Headers)
message(FATAL_ERROR "Vulkan::Headers target not defined")
endif()
endif()
if (FIND_PACKAGE_VULKAN_HEADERS)
find_package(VulkanHeaders REQUIRED)
endif()
if (FIND_PACKAGE_VULKAN)
find_package(Vulkan REQUIRED)
endif()
if (ADD_SUBDIRECTORY_TESTING)
add_subdirectory(../.. ${CMAKE_CURRENT_BINARY_DIR}/vk-bootstrap)
endif()
if (FIND_PACKAGE_TESTING)
find_package(vk-bootstrap CONFIG REQUIRED)
endif()
if (NOT TARGET vk-bootstrap::vk-bootstrap)
message(FATAL_ERROR "vk-bootstrap::vk-bootstrap target not defined")
endif()
add_executable(integration_test integration_test.cpp)
target_link_libraries(integration_test vk-bootstrap::vk-bootstrap)

View File

@ -0,0 +1,6 @@
#include "VkBootstrap.h"
int main() {
[[maybe_unused]] vkb::InstanceBuilder builder{};
return 0;
}

View File

@ -8,7 +8,6 @@
#include <string>
#include <vector>
#define VK_NO_PROTOTYPES
#include <vulkan/vulkan.h>
// Helper function to get the size of a struct given a VkStructureType