1# ~~~ 2# Copyright (c) 2014-2023 The Khronos Group Inc. 3# Copyright (c) 2014-2023 Valve Corporation 4# Copyright (c) 2014-2023 LunarG, Inc. 5# Copyright (c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 6# Copyright (c) 2023-2023 RasterGrid Kft. 7# 8# Licensed under the Apache License, Version 2.0 (the "License"); 9# you may not use this file except in compliance with the License. 10# You may obtain a copy of the License at 11# 12# http://www.apache.org/licenses/LICENSE-2.0 13# 14# Unless required by applicable law or agreed to in writing, software 15# distributed under the License is distributed on an "AS IS" BASIS, 16# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17# See the License for the specific language governing permissions and 18# limitations under the License. 19# ~~~ 20include(CheckIncludeFile) 21 22add_library(loader_specific_options INTERFACE) 23target_link_libraries(loader_specific_options INTERFACE loader_common_options Vulkan::Headers) 24target_include_directories(loader_specific_options INTERFACE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/generated ${CMAKE_CURRENT_BINARY_DIR}) 25 26if(WIN32) 27 28 if(ENABLE_WIN10_ONECORE) 29 # Note: When linking your app or driver to OneCore.lib, be sure to remove any links to non-umbrella libs (such as 30 # kernel32.lib). 31 set(CMAKE_C_STANDARD_LIBRARIES " ") # space is intentional 32 endif() 33 34 # ~~~ 35 # Build dev_ext_trampoline.c and unknown_ext_chain.c with /O2 to allow tail-call optimization. 36 # Setup two CMake targets (loader-norm and loader-opt) for the different compilation flags. 37 # ~~~ 38 set(MODIFIED_C_FLAGS_DEBUG ${CMAKE_C_FLAGS_DEBUG}) 39 40 string(REPLACE "/Od" "/O2" MODIFIED_C_FLAGS_DEBUG ${MODIFIED_C_FLAGS_DEBUG}) 41 string(REPLACE "/Ob0" "/Ob2" MODIFIED_C_FLAGS_DEBUG ${MODIFIED_C_FLAGS_DEBUG}) 42 string(REGEX REPLACE "/RTC." "" MODIFIED_C_FLAGS_DEBUG ${MODIFIED_C_FLAGS_DEBUG}) #remove run-time error checks 43 44 separate_arguments(MODIFIED_C_FLAGS_DEBUG WINDOWS_COMMAND ${MODIFIED_C_FLAGS_DEBUG}) 45 46 # ~~~ 47 # Only generate the loader.rc file with CMake if BUILD_DLL_VERSIONINFO was set. 48 # This feature is for the Vulkan Runtime build 49 # Otherwise rely on the checked in loader.rc from the python script 50 # ~~~ 51 if (NOT "$CACHE{BUILD_DLL_VERSIONINFO}" STREQUAL "") 52 string(TIMESTAMP CURRENT_YEAR "%Y") 53 set(LOADER_CUR_COPYRIGHT_YEAR "${CURRENT_YEAR}") 54 set(LOADER_RC_VERSION "$CACHE{BUILD_DLL_VERSIONINFO}") 55 set(LOADER_VER_FILE_VERSION_STR "\"${LOADER_RC_VERSION}\"") 56 set(LOADER_VER_FILE_DESCRIPTION_STR "\"Vulkan Loader\"") 57 58 # RC file wants the value of FILEVERSION to separated by commas 59 string(REPLACE "." ", " LOADER_VER_FILE_VERSION "${LOADER_RC_VERSION}") 60 61 # Configure the file to include the versioning info 62 # Place it in the build directory - the GN build will use the checked in file 63 configure_file(loader.rc.in ${CMAKE_CURRENT_BINARY_DIR}/loader.rc) 64 endif() 65else() 66 # Used to make alloca() and secure_getenv() available 67 target_compile_definitions(loader_specific_options INTERFACE _GNU_SOURCE) 68 if(CMAKE_SYSTEM_NAME MATCHES "FreeBSD") 69 target_compile_definitions(loader_specific_options INTERFACE __BSD_VISIBLE=1) 70 endif() 71 check_include_file("alloca.h" HAVE_ALLOCA_H) 72 if(HAVE_ALLOCA_H) 73 target_compile_definitions(loader_specific_options INTERFACE HAVE_ALLOCA_H) 74 endif() 75endif() 76 77set(NORMAL_LOADER_SRCS 78 allocation.c 79 allocation.h 80 cJSON.c 81 cJSON.h 82 debug_utils.c 83 debug_utils.h 84 extension_manual.c 85 extension_manual.h 86 loader_environment.c 87 loader_environment.h 88 gpa_helper.c 89 gpa_helper.h 90 loader.c 91 loader.h 92 log.c 93 log.h 94 settings.c 95 settings.h 96 terminator.c 97 trampoline.c 98 unknown_function_handling.c 99 unknown_function_handling.h 100 wsi.c 101 wsi.h 102 ) 103 104if(WIN32) 105 list(APPEND NORMAL_LOADER_SRCS loader_windows.c dirent_on_windows.c) 106elseif(CMAKE_SYSTEM_NAME MATCHES "Linux|BSD|DragonFly|GNU") 107 list(APPEND NORMAL_LOADER_SRCS loader_linux.c) 108 target_compile_definitions(loader_specific_options INTERFACE LOADER_ENABLE_LINUX_SORT) 109endif() 110 111if ("${CMAKE_OSX_ARCHITECTURES}" MATCHES ";") 112 set(APPLE_UNIVERSAL_BINARY ON) 113 114 # When building a universal binary we cannot enable USE_GAS 115 # Since USE_GAS assumes only 1 architecture (arm64, x64, etc). 116 set(USE_GAS OFF) 117endif() 118 119set(OPT_LOADER_SRCS dev_ext_trampoline.c phys_dev_ext.c) 120 121# Check for assembler support 122set(ASM_FAILURE_MSG "The build will fall back on building with C code\n") 123set(ASM_FAILURE_MSG "${ASM_FAILURE_MSG}Note that this may be unsafe, as the C code requires tail-call optimizations to remove") 124set(ASM_FAILURE_MSG "${ASM_FAILURE_MSG} the stack frame for certain calls. If the compiler does not do this, then unknown device") 125set(ASM_FAILURE_MSG "${ASM_FAILURE_MSG} extensions will suffer from a corrupted stack.") 126 127if (APPLE_UNIVERSAL_BINARY) 128 set(USE_ASSEMBLY_FALLBACK ON) 129elseif(WIN32) 130 option(USE_MASM "Use MASM" ON) 131 if(USE_MASM AND MINGW) 132 find_program(JWASM_FOUND NAMES jwasm uasm) 133 if (JWASM_FOUND) 134 set(CMAKE_ASM_MASM_COMPILER ${JWASM_FOUND}) 135 execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpmachine OUTPUT_VARIABLE COMPILER_VERSION_OUTPUT) 136 if (COMPILER_VERSION_OUTPUT) 137 if (COMPILER_VERSION_OUTPUT MATCHES "x86_64") 138 set(JWASM_FLAGS -win64) 139 else() 140 # jwasm requires setting the cpu to at least 386 for setting a flat model 141 set(JWASM_FLAGS -3 -coff) 142 endif() 143 endif() 144 endif() 145 endif() 146 if (USE_MASM) 147 enable_language(ASM_MASM) 148 endif() 149 # Test if the detected compiler actually works. 150 # Unfortunately, CMake's detection of ASM_MASM is not reliable, so we need to do this ourselves. 151 if (CMAKE_SIZEOF_VOID_P EQUAL 4) 152 file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/masm_check.asm [=[ 153.model flat 154.code 155extrn _start:near 156 xor eax, eax 157 ret 158end 159]=]) 160 else() 161 file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/masm_check.asm [=[ 162.code 163extrn start:near 164 xor rax, rax 165 ret 166end 167]=]) 168 endif () 169 if(MINGW) 170 set(CMAKE_ASM_MASM_FLAGS ${CMAKE_ASM_MASM_FLAGS} ${JWASM_FLAGS}) 171 elseif(NOT CMAKE_CL_64 AND NOT JWASM_FOUND) 172 set(CMAKE_ASM_MASM_FLAGS ${CMAKE_ASM_MASM_FLAGS} /safeseh) 173 endif() 174 # try_compile does not work here due to the same reasons as static above. 175 execute_process(COMMAND ${CMAKE_ASM_MASM_COMPILER} ${CMAKE_ASM_MASM_FLAGS} -c -Fo ${CMAKE_CURRENT_BINARY_DIR}/masm_check.obj ${CMAKE_CURRENT_BINARY_DIR}/masm_check.asm 176 RESULT_VARIABLE CMAKE_ASM_MASM_COMPILER_WORKS 177 OUTPUT_QUIET ERROR_QUIET) 178 # Convert the return code to a boolean 179 if(CMAKE_ASM_MASM_COMPILER_WORKS EQUAL 0) 180 set(CMAKE_ASM_MASM_COMPILER_WORKS true) 181 else() 182 set(CMAKE_ASM_MASM_COMPILER_WORKS false) 183 endif() 184 if(CMAKE_ASM_MASM_COMPILER_WORKS) 185 add_executable(asm_offset asm_offset.c) 186 target_link_libraries(asm_offset PRIVATE loader_specific_options) 187 # If am emulator is provided (Like Wine), or running on native, run asm_offset to generate gen_defines.asm 188 if (CMAKE_CROSSCOMPILING_EMULATOR OR NOT CMAKE_CROSSCOMPILING) 189 add_custom_command(OUTPUT gen_defines.asm DEPENDS asm_offset COMMAND asm_offset MASM) 190 else() 191 # Forces compiler to write the intermediate asm file, needed so that we can get sizeof/offset of info out of it. 192 target_compile_options(asm_offset PRIVATE "/Fa$<TARGET_FILE_DIR:asm_offset>/asm_offset.asm" /FA) 193 # Force off optimization so that the output assembly includes all the necessary info - optimizer would get rid of it otherwise. 194 target_compile_options(asm_offset PRIVATE /Od) 195 196 find_package(Python3 REQUIRED QUIET) 197 # Run parse_asm_values.py on asm_offset's assembly file to generate the gen_defines.asm, which the asm code depends on 198 add_custom_command(TARGET asm_offset POST_BUILD 199 COMMAND Python3::Interpreter ${PROJECT_SOURCE_DIR}/scripts/parse_asm_values.py "${CMAKE_CURRENT_BINARY_DIR}/gen_defines.asm" 200 "$<TARGET_FILE_DIR:asm_offset>/asm_offset.asm" "MASM" "${CMAKE_C_COMPILER_ID}" "${CMAKE_SYSTEM_PROCESSOR}" 201 BYPRODUCTS gen_defines.asm 202 ) 203 endif() 204 add_custom_target(loader_asm_gen_files DEPENDS gen_defines.asm) 205 set_target_properties(loader_asm_gen_files PROPERTIES FOLDER ${LOADER_HELPER_FOLDER}) 206 207 add_library(loader-unknown-chain OBJECT unknown_ext_chain_masm.asm) 208 target_link_libraries(loader-unknown-chain Vulkan::Headers) 209 target_include_directories(loader-unknown-chain PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) 210 add_dependencies(loader-unknown-chain loader_asm_gen_files) 211 else() 212 set(USE_ASSEMBLY_FALLBACK ON) 213 message(WARNING "Could not find working MASM assembler\n${ASM_FAILURE_MSG}") 214 endif() 215elseif(UNIX) # i.e.: Linux & Apple 216 217 option(USE_GAS "Use GAS" ON) 218 if(USE_GAS) 219 if (APPLE_UNIVERSAL_BINARY) 220 message(FATAL_ERROR "USE_GAS cannot be used when compiling a universal binary!") 221 endif() 222 223 enable_language(ASM) 224 225 set(CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS}") 226 set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) 227 228 if (${CMAKE_SYSTEM_PROCESSOR} MATCHES "aarch64|arm64") 229 try_compile(ASSEMBLER_WORKS ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/asm_test_aarch64.S) 230 if(ASSEMBLER_WORKS) 231 set(OPT_LOADER_SRCS ${OPT_LOADER_SRCS} unknown_ext_chain_gas_aarch64.S) 232 endif() 233 # Covers x86_64, amd64, x86, i386, i686, I386, I686 234 elseif(${CMAKE_SYSTEM_PROCESSOR} MATCHES "amd64|86") 235 check_include_file("cet.h" HAVE_CET_H) 236 if(HAVE_CET_H) 237 target_compile_definitions(loader_specific_options INTERFACE HAVE_CET_H) 238 endif() 239 240 try_compile(ASSEMBLER_WORKS ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/asm_test_x86.S) 241 if(ASSEMBLER_WORKS) 242 set(OPT_LOADER_SRCS ${OPT_LOADER_SRCS} unknown_ext_chain_gas_x86.S) 243 endif() 244 endif() 245 endif() 246 247 # When compiling for x86 on x64, we can't use CMAKE_SYSTEM_PROCESSOR to determine which architecture to use, 248 # Instead, check the size of void* and if its 4, set ASM_OFFSET_SYSTEM_PROCESSOR to x86 249 # Note - there is no 32 bit arm assembly code, so this only applies to x86 currently. 250 if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8") 251 set(ASM_OFFSET_SYSTEM_PROCESSOR ${CMAKE_SYSTEM_PROCESSOR}) # x86_64 or aarch64/arm64 252 else() 253 set(ASM_OFFSET_SYSTEM_PROCESSOR "x86") 254 endif() 255 256 if(ASSEMBLER_WORKS) 257 add_executable(asm_offset asm_offset.c) 258 target_link_libraries(asm_offset loader_specific_options) 259 # If not cross compiling, run asm_offset to generage gen_defines.asm 260 if (NOT CMAKE_CROSSCOMPILING) 261 add_custom_command(OUTPUT gen_defines.asm DEPENDS asm_offset COMMAND asm_offset GAS) 262 else() 263 # Forces compiler to write the intermediate asm file, needed so that we can get sizeof/offset of info out of it. 264 target_compile_options(asm_offset PRIVATE -save-temps=obj) 265 if(CMAKE_C_COMPILER_ID STREQUAL "GNU") 266 set(ASM_OFFSET_EXECUTABLE_LOCATION "$<TARGET_FILE_DIR:asm_offset>/gen_defines.asm") 267 set(ASM_OFFSET_INTERMEDIATE_LOCATION "$<TARGET_FILE_DIR:asm_offset>/CMakeFiles/asm_offset.dir/asm_offset.c.s") 268 elseif(CMAKE_C_COMPILER_ID STREQUAL "Clang") 269 set(ASM_OFFSET_EXECUTABLE_LOCATION "$<TARGET_FILE_DIR:asm_offset>/gen_defines.asm") 270 set(ASM_OFFSET_INTERMEDIATE_LOCATION "$<TARGET_FILE_DIR:asm_offset>/CMakeFiles/asm_offset.dir/asm_offset.s") 271 elseif(CMAKE_C_COMPILER_ID STREQUAL "AppleClang") 272 # Need to use the current binary dir since the asm_offset.s file is in that folder rather than the bundle 273 set(ASM_OFFSET_EXECUTABLE_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/gen_defines.asm") 274 set(ASM_OFFSET_INTERMEDIATE_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/asm_offset.dir/asm_offset.s") 275 else() 276 message(FATAL_ERROR "C_COMPILER_ID not supported!") 277 endif() 278 279 find_package(Python3 REQUIRED QUIET) 280 # Run parse_asm_values.py on asm_offset's assembly file to generate the gen_defines.asm, which the asm code depends on 281 add_custom_command(TARGET asm_offset POST_BUILD 282 COMMAND Python3::Interpreter ${PROJECT_SOURCE_DIR}/scripts/parse_asm_values.py "${ASM_OFFSET_EXECUTABLE_LOCATION}" 283 "${ASM_OFFSET_INTERMEDIATE_LOCATION}" "GAS" "${CMAKE_C_COMPILER_ID}" "${ASM_OFFSET_SYSTEM_PROCESSOR}" 284 BYPRODUCTS gen_defines.asm 285 ) 286 endif() 287 add_custom_target(loader_asm_gen_files DEPENDS gen_defines.asm) 288 289 if (APPLE) 290 set(MODIFY_UNKNOWN_FUNCTION_DECLS ON) 291 endif() 292 else() 293 set(USE_ASSEMBLY_FALLBACK ON) 294 if(USE_GAS) 295 message(WARNING "Could not find working ${ASM_OFFSET_SYSTEM_PROCESSOR} GAS assembler\n${ASM_FAILURE_MSG}") 296 else() 297 message(WARNING "Assembly sources have been disabled\n${ASM_FAILURE_MSG}") 298 endif() 299 endif() 300endif() 301 302if(USE_ASSEMBLY_FALLBACK) 303 add_custom_target(loader_asm_gen_files) 304 if (MSVC) 305 add_library(loader-unknown-chain OBJECT unknown_ext_chain.c) 306 target_link_libraries(loader-unknown-chain loader_specific_options) 307 set_target_properties(loader-unknown-chain PROPERTIES CMAKE_C_FLAGS_DEBUG "${MODIFIED_C_FLAGS_DEBUG}") 308 else() 309 set(OPT_LOADER_SRCS ${OPT_LOADER_SRCS} unknown_ext_chain.c) 310 set_source_files_properties(${OPT_LOADER_SRCS} PROPERTIES COMPILE_FLAGS -O) 311 endif() 312endif() 313 314if(WIN32) 315 add_library(loader-opt STATIC ${OPT_LOADER_SRCS}) 316 target_link_libraries(loader-opt PUBLIC loader_specific_options) 317 add_dependencies(loader-opt loader_asm_gen_files) 318 set_target_properties(loader-opt PROPERTIES CMAKE_C_FLAGS_DEBUG "${MODIFIED_C_FLAGS_DEBUG}") 319 320 # If BUILD_DLL_VERSIONINFO was set, use the loader.rc in the build dir, otherwise use the checked in file 321 set(RC_FILE_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/loader.rc) 322 if (NOT "$CACHE{BUILD_DLL_VERSIONINFO}" STREQUAL "") 323 set(RC_FILE_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/loader.rc) 324 endif() 325 326 set(LOADER_UNKNOWN_CHAIN_LIBRARY $<$<TARGET_EXISTS:loader-unknown-chain>:$<TARGET_OBJECTS:loader-unknown-chain>>) 327 328 add_library(vulkan 329 SHARED 330 ${NORMAL_LOADER_SRCS} 331 ${LOADER_UNKNOWN_CHAIN_LIBRARY} 332 ${CMAKE_CURRENT_SOURCE_DIR}/${API_TYPE}-1.def 333 ${RC_FILE_LOCATION}) 334 335 target_link_libraries(vulkan PRIVATE loader_specific_options loader-opt) 336 337 # when adding the suffix the import and runtime library names must be consistent 338 # mingw: libvulkan-1.dll.a / vulkan-1.dll 339 # msvc: vulkan-1.lib / vulkan-1.dll 340 set_target_properties(vulkan 341 PROPERTIES 342 OUTPUT_NAME ${API_TYPE}-1) 343 if(MINGW) 344 # generate the same DLL with mingw 345 set_target_properties(vulkan 346 PROPERTIES 347 PREFIX "") 348 endif() 349 350 if(MSVC AND ENABLE_WIN10_ONECORE) 351 target_link_libraries(vulkan PRIVATE OneCoreUAP.lib LIBCMT.LIB LIBCMTD.LIB LIBVCRUNTIME.LIB LIBUCRT.LIB) 352 set_target_properties(vulkan PROPERTIES LINK_FLAGS "/NODEFAULTLIB") 353 else() 354 target_link_libraries(vulkan PRIVATE cfgmgr32) 355 endif() 356 357 add_dependencies(vulkan loader_asm_gen_files) 358 359else() 360 if(APPLE) 361 option(APPLE_STATIC_LOADER "Build a loader that can be statically linked. Intended for Chromium usage/testing.") 362 mark_as_advanced(APPLE_STATIC_LOADER) 363 endif() 364 365 if(APPLE_STATIC_LOADER) 366 add_library(vulkan STATIC) 367 target_compile_definitions(vulkan PRIVATE APPLE_STATIC_LOADER) 368 369 message(WARNING "The APPLE_STATIC_LOADER option has been set. Note that this will only work on MacOS and is not supported " 370 "or tested as part of the loader. Use it at your own risk.") 371 else() 372 add_library(vulkan SHARED) 373 endif() 374 375 target_sources(vulkan PRIVATE ${NORMAL_LOADER_SRCS} ${OPT_LOADER_SRCS}) 376 377 add_dependencies(vulkan loader_asm_gen_files) 378 379 set_target_properties(vulkan PROPERTIES 380 SOVERSION "1" 381 VERSION "${VULKAN_LOADER_VERSION}" 382 ) 383 384 set(THREADS_PREFER_PTHREAD_FLAG ON) 385 find_package(Threads REQUIRED) 386 387 target_link_libraries(vulkan PRIVATE ${CMAKE_DL_LIBS} m Threads::Threads) 388 389 set_target_properties(vulkan PROPERTIES OUTPUT_NAME ${API_TYPE}) 390 391 if (LOADER_ENABLE_ADDRESS_SANITIZER) 392 target_compile_options(vulkan PUBLIC -fsanitize=address) 393 target_link_options(vulkan PUBLIC -fsanitize=address) 394 endif() 395 if (LOADER_ENABLE_THREAD_SANITIZER) 396 target_compile_options(vulkan PUBLIC -fsanitize=thread) 397 target_link_options(vulkan PUBLIC -fsanitize=thread) 398 endif() 399 if (LOADER_ENABLE_UNDEFINED_BEHAVIOR_SANITIZER) 400 target_compile_options(vulkan PUBLIC -fsanitize=undefined) 401 target_link_options(vulkan PUBLIC -fsanitize=undefined) 402 endif() 403 404 if(APPLE) 405 find_library(COREFOUNDATION_LIBRARY NAMES CoreFoundation) 406 target_link_libraries(vulkan PRIVATE "-framework CoreFoundation") 407 408 # Build vulkan.framework 409 # Use GLOB_RECURSE to find all the header files and populate the vulkan.framework headers with them 410 # Use CONFIGURE_DEPENDS to ensure that if the header files are updated, this list is also updated 411 get_target_property(VulkanHeaders_INCLUDE_DIRS Vulkan::Headers INTERFACE_INCLUDE_DIRECTORIES) 412 file(GLOB_RECURSE CONFIGURE_DEPENDS FRAMEWORK_HEADERS ${VulkanHeaders_INCLUDE_DIRS}) 413 414 add_library(vulkan-framework SHARED) 415 target_sources(vulkan-framework PRIVATE ${NORMAL_LOADER_SRCS} ${OPT_LOADER_SRCS} ${FRAMEWORK_HEADERS}) 416 417 add_dependencies(vulkan-framework loader_asm_gen_files) 418 target_link_libraries(vulkan-framework ${CMAKE_DL_LIBS} Threads::Threads -lm "-framework CoreFoundation") 419 target_link_libraries(vulkan-framework loader_specific_options) 420 421 if (MODIFY_UNKNOWN_FUNCTION_DECLS) 422 # Modifies the names of functions as they appearin the assembly code so that the 423 # unknown function handling will work 424 target_compile_definitions(vulkan PRIVATE MODIFY_UNKNOWN_FUNCTION_DECLS) 425 target_compile_definitions(vulkan-framework PRIVATE MODIFY_UNKNOWN_FUNCTION_DECLS) 426 endif() 427 428 # The FRAMEWORK_VERSION needs to be "A" here so that Xcode code-signing works when a user adds their framework to an Xcode 429 # project and does "Sign on Copy". It would have been nicer to use "1" to denote Vulkan 1. Although Apple docs say that a 430 # framework version does not have to be "A", this part of the Apple toolchain expects it. 431 # https://forums.developer.apple.com/thread/65963 432 433 set_target_properties(vulkan-framework PROPERTIES 434 OUTPUT_NAME vulkan 435 FRAMEWORK TRUE 436 FRAMEWORK_VERSION A 437 VERSION "${VULKAN_LOADER_VERSION}" 438 SOVERSION "1.0.0" 439 MACOSX_FRAMEWORK_IDENTIFIER com.lunarg.vulkanFramework 440 PUBLIC_HEADER "${FRAMEWORK_HEADERS}" 441 ) 442 443 # Workaround linker warning: https://github.com/KhronosGroup/Vulkan-Loader/issues/1332 444 # 445 # MACHO_CURRENT_VERSION specifically applies to the -current_version linker option which is the 446 # linker warning we are trying to address. 447 set(APPLE_VULKAN_LOADER_VERSION "${VULKAN_LOADER_VERSION_MAJOR}.${VULKAN_LOADER_VERSION_MINOR}.0") 448 set_target_properties(vulkan PROPERTIES MACHO_CURRENT_VERSION "${APPLE_VULKAN_LOADER_VERSION}") 449 set_target_properties(vulkan-framework PROPERTIES MACHO_CURRENT_VERSION "${APPLE_VULKAN_LOADER_VERSION}") 450 451 install(TARGETS vulkan-framework 452 PUBLIC_HEADER DESTINATION vulkan 453 FRAMEWORK DESTINATION loader 454 ) 455 endif() 456endif() 457 458option(LOADER_USE_UNSAFE_FILE_SEARCH "Allows the loader to search in unsafe locations") 459if (LOADER_USE_UNSAFE_FILE_SEARCH) 460 target_compile_definitions(vulkan PRIVATE LOADER_USE_UNSAFE_FILE_SEARCH) 461endif() 462 463# common attributes of the vulkan library 464target_link_libraries(vulkan PRIVATE loader_specific_options) 465 466target_link_libraries(vulkan PRIVATE Vulkan::Headers) 467add_library(Vulkan::Loader ALIAS vulkan) 468 469if (APPLE_STATIC_LOADER) 470 # TLDR: This feature only exists at the request of Google for Chromium. No other project should use this! 471 message(NOTICE "Apple STATIC lib: it will be built but not installed, and vulkan.pc and VulkanLoaderConfig.cmake won't be generated!") 472 return() 473endif() 474 475# Generate CMake Configuration File (IE: VulkanLoaderConfig.cmake) 476install(TARGETS vulkan EXPORT VulkanLoaderConfig) 477set_target_properties(vulkan PROPERTIES EXPORT_NAME "Loader") 478install(EXPORT VulkanLoaderConfig DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/VulkanLoader NAMESPACE Vulkan::) 479 480# Generate CMake Version File (IE: VulkanLoaderConfigVersion.cmake) 481include(CMakePackageConfigHelpers) 482 483set(version_config "${CMAKE_CURRENT_BINARY_DIR}/generated/VulkanLoaderConfigVersion.cmake") 484write_basic_package_version_file("${version_config}" COMPATIBILITY SameMajorVersion) 485install(FILES "${version_config}" DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/VulkanLoader) 486 487# Generate PkgConfig File (IE: vulkan.pc) 488# NOTE: Hopefully in the future CMake can generate .pc files natively. 489# https://gitlab.kitware.com/cmake/cmake/-/issues/22621 490find_package(PkgConfig) 491if (PKG_CONFIG_FOUND) 492 if(WIN32) 493 if(MINGW) 494 set(VULKAN_LIB_SUFFIX "-1.dll") 495 else() 496 set(VULKAN_LIB_SUFFIX "-1") 497 endif() 498 endif() 499 500 # BUG: The following code will NOT work well with `cmake --install ... --prefix <dir>` 501 # due to this code relying on CMAKE_INSTALL_PREFIX being defined at configure time. 502 # 503 # NOTE: vulkan.pc essentially cover both Vulkan-Loader and Vulkan-Headers for legacy reasons. 504 if ("${CMAKE_INSTALL_PREFIX}" STREQUAL "") 505 set(CMAKE_INSTALL_LIBDIR_PC ${CMAKE_INSTALL_FULL_LIBDIR}) 506 set(CMAKE_INSTALL_INCLUDEDIR_PC ${CMAKE_INSTALL_FULL_INCLUDEDIR}) 507 else() 508 file(RELATIVE_PATH CMAKE_INSTALL_LIBDIR_PC ${CMAKE_INSTALL_PREFIX} ${CMAKE_INSTALL_FULL_LIBDIR}) 509 file(RELATIVE_PATH CMAKE_INSTALL_INCLUDEDIR_PC ${CMAKE_INSTALL_PREFIX} ${CMAKE_INSTALL_FULL_INCLUDEDIR}) 510 endif() 511 configure_file("vulkan.pc.in" "vulkan.pc" @ONLY) 512 install(FILES "${CMAKE_CURRENT_BINARY_DIR}/vulkan.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig" RENAME "${API_TYPE}.pc") 513endif() 514