From f223c8d5aeeec0c7b38656bdefa2f6a9da5a3f7f Mon Sep 17 00:00:00 2001 From: Charles Giessen Date: Thu, 30 Nov 2023 13:43:00 -0700 Subject: [PATCH] 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). --- CMakeLists.txt | 137 +++++++++++++++++-------- example/CMakeLists.txt | 2 +- ext/CMakeLists.txt | 2 +- tests/CMakeLists.txt | 80 ++++++++++++++- tests/integration/CMakeLists.txt | 41 ++++++++ tests/integration/integration_test.cpp | 6 ++ tests/vulkan_mock.hpp | 1 - 7 files changed, 222 insertions(+), 47 deletions(-) create mode 100644 tests/integration/CMakeLists.txt create mode 100644 tests/integration/integration_test.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 90278ad..ed8e088 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 $) -if(NOT "${VK_BOOTSTRAP_VULKAN_HEADER_DIR}" STREQUAL "") - target_include_directories(vk-bootstrap-vulkan-headers INTERFACE $) -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 $ $) 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() diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index 7b21dc2..89d45cc 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -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( diff --git a/ext/CMakeLists.txt b/ext/CMakeLists.txt index c1bbd8a..4dc1655 100644 --- a/ext/CMakeLists.txt +++ b/ext/CMakeLists.txt @@ -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( diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 5122129..21c2038 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -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 $ +) + +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() diff --git a/tests/integration/CMakeLists.txt b/tests/integration/CMakeLists.txt new file mode 100644 index 0000000..5d16d6d --- /dev/null +++ b/tests/integration/CMakeLists.txt @@ -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) + diff --git a/tests/integration/integration_test.cpp b/tests/integration/integration_test.cpp new file mode 100644 index 0000000..1028b1b --- /dev/null +++ b/tests/integration/integration_test.cpp @@ -0,0 +1,6 @@ +#include "VkBootstrap.h" + +int main() { + [[maybe_unused]] vkb::InstanceBuilder builder{}; + return 0; +} diff --git a/tests/vulkan_mock.hpp b/tests/vulkan_mock.hpp index 558b621..d27a724 100644 --- a/tests/vulkan_mock.hpp +++ b/tests/vulkan_mock.hpp @@ -8,7 +8,6 @@ #include #include -#define VK_NO_PROTOTYPES #include // Helper function to get the size of a struct given a VkStructureType