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 # Only generate the loader.rc file with CMake if BUILD_DLL_VERSIONINFO was set. 36 # This feature is for the Vulkan Runtime build 37 # Otherwise rely on the checked in loader.rc from the python script 38 # ~~~ 39 if (NOT "$CACHE{BUILD_DLL_VERSIONINFO}" STREQUAL "") 40 string(TIMESTAMP CURRENT_YEAR "%Y") 41 set(LOADER_CUR_COPYRIGHT_YEAR "${CURRENT_YEAR}") 42 set(LOADER_RC_VERSION "$CACHE{BUILD_DLL_VERSIONINFO}") 43 set(LOADER_VER_FILE_VERSION_STR "\"${LOADER_RC_VERSION}\"") 44 set(LOADER_VER_FILE_DESCRIPTION_STR "\"Vulkan Loader\"") 45 46 # RC file wants the value of FILEVERSION to separated by commas 47 string(REPLACE "." ", " LOADER_VER_FILE_VERSION "${LOADER_RC_VERSION}") 48 49 # Configure the file to include the versioning info 50 # Place it in the build directory - the GN build will use the checked in file 51 configure_file(loader.rc.in ${CMAKE_CURRENT_BINARY_DIR}/loader.rc) 52 endif() 53else() 54 # Used to make alloca() and secure_getenv() available 55 target_compile_definitions(loader_specific_options INTERFACE _GNU_SOURCE) 56 if(CMAKE_SYSTEM_NAME MATCHES "FreeBSD") 57 target_compile_definitions(loader_specific_options INTERFACE __BSD_VISIBLE=1) 58 endif() 59 check_include_file("alloca.h" HAVE_ALLOCA_H) 60 if(HAVE_ALLOCA_H) 61 target_compile_definitions(loader_specific_options INTERFACE HAVE_ALLOCA_H) 62 endif() 63 64 set(THREADS_PREFER_PTHREAD_FLAG ON) 65 find_package(Threads REQUIRED) 66endif() 67 68set(NORMAL_LOADER_SRCS 69 allocation.c 70 allocation.h 71 cJSON.c 72 cJSON.h 73 debug_utils.c 74 debug_utils.h 75 extension_manual.c 76 extension_manual.h 77 loader_environment.c 78 loader_environment.h 79 gpa_helper.c 80 gpa_helper.h 81 loader.c 82 loader.h 83 log.c 84 log.h 85 loader_json.c 86 loader_json.h 87 settings.c 88 settings.h 89 terminator.c 90 trampoline.c 91 unknown_function_handling.c 92 unknown_function_handling.h 93 wsi.c 94 wsi.h 95 ) 96 97if(WIN32) 98 list(APPEND NORMAL_LOADER_SRCS loader_windows.c dirent_on_windows.c) 99elseif(CMAKE_SYSTEM_NAME MATCHES "Linux|BSD|DragonFly|GNU") 100 list(APPEND NORMAL_LOADER_SRCS loader_linux.c) 101 target_compile_definitions(loader_specific_options INTERFACE LOADER_ENABLE_LINUX_SORT) 102endif() 103 104if ("${CMAKE_OSX_ARCHITECTURES}" MATCHES ";") 105 set(APPLE_UNIVERSAL_BINARY ON) 106 107 # When building a universal binary we cannot enable USE_GAS 108 # Since USE_GAS assumes only 1 architecture (arm64, x64, etc). 109 set(USE_GAS OFF) 110endif() 111 112set(OPT_LOADER_SRCS dev_ext_trampoline.c phys_dev_ext.c) 113 114set(ASM_FAILURE_MSG "Support for unknown physical device and device functions is disabled due to missing the required assembly support code. \ 115To support unknown functions, assembly must be added for the platform.\n") 116set(ARMASM_CMAKE_FAILURE_MSG "Support for unknown physical device and device functions is disabled due to the CMake version ${CMAKE_VERSION} \ 117being older than 3.26. Please update CMake to version 3.26 or newer.\n") 118 119# Check for assembler support 120if(WIN32 AND NOT USE_GAS) 121 option(USE_MASM "Use MASM" ON) 122 if(USE_MASM AND MINGW) 123 find_program(JWASM_FOUND NAMES jwasm uasm) 124 if (JWASM_FOUND) 125 set(CMAKE_ASM_MASM_COMPILER ${JWASM_FOUND}) 126 execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpmachine OUTPUT_VARIABLE COMPILER_VERSION_OUTPUT) 127 if (COMPILER_VERSION_OUTPUT) 128 if (COMPILER_VERSION_OUTPUT MATCHES "x86_64") 129 set(JWASM_FLAGS -win64) 130 else() 131 # jwasm requires setting the cpu to at least 386 for setting a flat model 132 set(JWASM_FLAGS -3 -coff) 133 endif() 134 endif() 135 endif() 136 endif() 137 if (USE_MASM) 138 if(SYSTEM_PROCESSOR MATCHES "arm") 139 if(CMAKE_VERSION VERSION_LESS "3.26.0") 140 set(ASM_FAILURE_MSG ${ARMASM_CMAKE_FAILURE_MSG}) 141 else() 142 enable_language(ASM_MARMASM) 143 set(LOADER_ASM_DIALECT "MARMASM") 144 endif() 145 else() 146 enable_language(ASM_MASM) 147 set(LOADER_ASM_DIALECT "MASM") 148 endif() 149 endif() 150 151 # Test if the detected compiler actually works. 152 # Unfortunately, CMake's detection of ASM_MASM is not reliable, so we need to do this ourselves. 153 if(SYSTEM_PROCESSOR MATCHES "arm") 154 if (CMAKE_SIZEOF_VOID_P EQUAL 4) 155 file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/masm_check.asm [=[ 156test_func FUNCTION 157 mov r0, #0 158 bx lr 159 ENDFUNC 160 END 161]=]) 162 else() 163 file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/masm_check.asm [=[ 164test_func FUNCTION 165 mov x1, 26 166 ldr x0, [x0, x1] 167 ENDFUNC 168 END 169]=]) 170 endif() 171 else() 172 if (CMAKE_SIZEOF_VOID_P EQUAL 4) 173 file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/masm_check.asm [=[ 174.model flat 175.code 176extrn _start:near 177 xor eax, eax 178 ret 179end 180]=]) 181 else() 182 file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/masm_check.asm [=[ 183.code 184extrn start:near 185 xor rax, rax 186 ret 187end 188]=]) 189 endif() 190 endif () 191 192 if(MINGW) 193 set(CMAKE_ASM_MASM_FLAGS ${CMAKE_ASM_MASM_FLAGS} ${JWASM_FLAGS}) 194 set(CMAKE_ASM_MARMASM_FLAGS ${CMAKE_ASM_MARMASM_FLAGS} ${JWASM_FLAGS}) 195 elseif(NOT CMAKE_CL_64 AND NOT JWASM_FOUND AND CMAKE_SIZEOF_VOID_P EQUAL 4) 196 set(CMAKE_ASM_MASM_FLAGS ${CMAKE_ASM_MASM_FLAGS} /safeseh) # /safeseh is only needed in x86 197 endif() 198 199 # try_compile does not work here due to the same reasons as static above. 200 if(SYSTEM_PROCESSOR MATCHES "arm") 201 execute_process(COMMAND ${CMAKE_ASM_MARMASM_COMPILER} ${CMAKE_ASM_MARMASM_FLAGS} ${CMAKE_CURRENT_BINARY_DIR}/masm_check.asm 202 RESULT_VARIABLE ASM_COMPILER_WORKS 203 OUTPUT_QUIET ERROR_QUIET) 204 else() 205 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 206 RESULT_VARIABLE ASM_COMPILER_WORKS 207 OUTPUT_QUIET ERROR_QUIET) 208 endif() 209 210 # Convert the return code to a boolean 211 if(ASM_COMPILER_WORKS EQUAL 0) 212 set(ASM_COMPILER_WORKS true) 213 else() 214 set(ASM_COMPILER_WORKS false) 215 endif() 216 217 if(ASM_COMPILER_WORKS) 218 add_executable(asm_offset asm_offset.c) 219 target_link_libraries(asm_offset PRIVATE loader_specific_options) 220 # If am emulator is provided (Like Wine), or running on native, run asm_offset to generate gen_defines.asm 221 if (CMAKE_CROSSCOMPILING_EMULATOR OR NOT CMAKE_CROSSCOMPILING) 222 add_custom_command(OUTPUT gen_defines.asm DEPENDS asm_offset COMMAND asm_offset ${LOADER_ASM_DIALECT}) 223 else() 224 # Forces compiler to write the intermediate asm file, needed so that we can get sizeof/offset of info out of it. 225 target_compile_options(asm_offset PRIVATE "/Fa$<TARGET_FILE_DIR:asm_offset>/asm_offset.asm" /FA) 226 # Force off optimization so that the output assembly includes all the necessary info - optimizer would get rid of it otherwise. 227 target_compile_options(asm_offset PRIVATE /Od) 228 229 find_package(Python3 REQUIRED QUIET) 230 # Run parse_asm_values.py on asm_offset's assembly file to generate the gen_defines.asm, which the asm code depends on 231 add_custom_command(TARGET asm_offset POST_BUILD 232 COMMAND Python3::Interpreter ${PROJECT_SOURCE_DIR}/scripts/parse_asm_values.py "${CMAKE_CURRENT_BINARY_DIR}/gen_defines.asm" 233 "$<TARGET_FILE_DIR:asm_offset>/asm_offset.asm" "${LOADER_ASM_DIALECT}" "${CMAKE_C_COMPILER_ID}" "${SYSTEM_PROCESSOR}" 234 BYPRODUCTS gen_defines.asm 235 ) 236 endif() 237 add_custom_target(loader_asm_gen_files DEPENDS gen_defines.asm) 238 set_target_properties(loader_asm_gen_files PROPERTIES FOLDER ${LOADER_HELPER_FOLDER}) 239 240 if(SYSTEM_PROCESSOR MATCHES "arm") 241 list(APPEND OPT_LOADER_SRCS unknown_ext_chain_marmasm.asm) 242 else() 243 list(APPEND OPT_LOADER_SRCS unknown_ext_chain_masm.asm) 244 endif() 245 set(UNKNOWN_FUNCTIONS_SUPPORTED ON) 246 else() 247 message(WARNING "Could not find working ${} assembler\n${ASM_FAILURE_MSG}") 248 endif() 249elseif(UNIX OR MINGW OR (WIN32 AND USE_GAS)) # i.e.: Linux & Apple & MinGW & Windows using Clang-CL 250 251 option(USE_GAS "Use GAS" ON) 252 if(USE_GAS) 253 if (APPLE_UNIVERSAL_BINARY) 254 message(FATAL_ERROR "USE_GAS cannot be used when compiling a universal binary!") 255 endif() 256 257 enable_language(ASM) 258 259 set(CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS}") 260 set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) 261 262 if(WIN32 AND ${SYSTEM_PROCESSOR} MATCHES "arm64") 263 # In this particular case, we are using the same approach as for NASM 264 # This specifically avoids CMake issue #18889 265 execute_process(COMMAND ${CMAKE_ASM_COMPILER} ${CMAKE_ASM_FLAGS} -c -o ${CMAKE_CURRENT_BINARY_DIR}/asm_test_aarch64.obj ${CMAKE_CURRENT_SOURCE_DIR}/asm_test_aarch64.S 266 RESULT_VARIABLE WIN_ARM64_ASSEMBLER_WORKS 267 OUTPUT_QUIET ERROR_QUIET) 268 if(WIN_ARM64_ASSEMBLER_WORKS EQUAL 0) 269 set(ASSEMBLER_WORKS true) 270 endif() 271 272 if(ASSEMBLER_WORKS) 273 list(APPEND OPT_LOADER_SRCS unknown_ext_chain_gas_aarch.S) 274 endif() 275 elseif (${SYSTEM_PROCESSOR} MATCHES "aarch64|arm64") 276 try_compile(ASSEMBLER_WORKS ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/asm_test_aarch64.S OUTPUT_VARIABLE TRY_COMPILE_OUTPUT) 277 if(ASSEMBLER_WORKS) 278 list(APPEND OPT_LOADER_SRCS unknown_ext_chain_gas_aarch.S) 279 endif() 280 elseif (${SYSTEM_PROCESSOR} MATCHES "aarch32|armhf|armv7l|armv8l") 281 try_compile(ASSEMBLER_WORKS ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/asm_test_aarch32.S OUTPUT_VARIABLE TRY_COMPILE_OUTPUT) 282 if(ASSEMBLER_WORKS) 283 list(APPEND OPT_LOADER_SRCS unknown_ext_chain_gas_aarch.S) 284 endif() 285 # Covers x86_64, amd64, x86, i386, i686, I386, I686 286 elseif(${SYSTEM_PROCESSOR} MATCHES "amd64|86") 287 check_include_file("cet.h" HAVE_CET_H) 288 if(HAVE_CET_H) 289 target_compile_definitions(loader_specific_options INTERFACE HAVE_CET_H) 290 endif() 291 292 try_compile(ASSEMBLER_WORKS ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/asm_test_x86.S) 293 if(ASSEMBLER_WORKS) 294 list(APPEND OPT_LOADER_SRCS unknown_ext_chain_gas_x86.S) 295 endif() 296 endif() 297 endif() 298 299 # When compiling for x86 on x64, we can't use CMAKE_SYSTEM_PROCESSOR to determine which architecture to use, 300 # Instead, check the size of void* and if its 4, set ASM_OFFSET_SYSTEM_PROCESSOR to x86 if we aren't on arm 301 if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8") 302 set(ASM_OFFSET_SYSTEM_PROCESSOR ${SYSTEM_PROCESSOR}) # x86_64 or aarch64/arm64 303 string(REPLACE amd64 x86_64 ASM_OFFSET_SYSTEM_PROCESSOR "${ASM_OFFSET_SYSTEM_PROCESSOR}") 304 else() 305 if(${SYSTEM_PROCESSOR} MATCHES "86") 306 set(ASM_OFFSET_SYSTEM_PROCESSOR "x86") 307 else() 308 set(ASM_OFFSET_SYSTEM_PROCESSOR ${SYSTEM_PROCESSOR}) 309 endif() 310 endif() 311 312 if(ASSEMBLER_WORKS) 313 add_executable(asm_offset asm_offset.c) 314 target_link_libraries(asm_offset loader_specific_options) 315 # If not cross compiling, run asm_offset to generage gen_defines.asm 316 if (NOT CMAKE_CROSSCOMPILING) 317 add_custom_command(OUTPUT gen_defines.asm DEPENDS asm_offset COMMAND asm_offset GAS) 318 else() 319 # Forces compiler to write the intermediate asm file, needed so that we can get sizeof/offset of info out of it. 320 # If with lto, compiler will output IR instead of asm, so we need to explicitly disable lto here. 321 if(CMAKE_C_COMPILER_ID STREQUAL "GNU") 322 target_compile_options(asm_offset PRIVATE -save-temps=obj -fno-lto) 323 elseif(CMAKE_C_COMPILER_ID STREQUAL "Clang" OR CMAKE_C_COMPILER_ID STREQUAL "AppleClang") 324 target_compile_options(asm_offset PRIVATE -save-temps=obj -fno-lto -fno-whole-program-vtables -fno-virtual-function-elimination) 325 else() 326 target_compile_options(asm_offset PRIVATE -save-temps=obj) 327 endif() 328 if(CMAKE_C_COMPILER_ID STREQUAL "GNU") 329 set(ASM_OFFSET_EXECUTABLE_LOCATION "$<TARGET_FILE_DIR:asm_offset>/gen_defines.asm") 330 set(ASM_OFFSET_INTERMEDIATE_LOCATION "$<TARGET_FILE_DIR:asm_offset>/CMakeFiles/asm_offset.dir/asm_offset.c.s") 331 elseif(CMAKE_C_COMPILER_ID STREQUAL "Clang") 332 set(ASM_OFFSET_EXECUTABLE_LOCATION "$<TARGET_FILE_DIR:asm_offset>/gen_defines.asm") 333 set(ASM_OFFSET_INTERMEDIATE_LOCATION "$<TARGET_FILE_DIR:asm_offset>/CMakeFiles/asm_offset.dir/asm_offset.s") 334 elseif(CMAKE_C_COMPILER_ID STREQUAL "AppleClang") 335 # Need to use the current binary dir since the asm_offset.s file is in that folder rather than the bundle 336 set(ASM_OFFSET_EXECUTABLE_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/gen_defines.asm") 337 set(ASM_OFFSET_INTERMEDIATE_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/asm_offset.dir/asm_offset.s") 338 else() 339 message(FATAL_ERROR "C_COMPILER_ID not supported!") 340 endif() 341 message(STATUS "CMAKE_CROSSCOMPILING FALSE") 342 343 find_package(Python3 REQUIRED QUIET) 344 # Run parse_asm_values.py on asm_offset's assembly file to generate the gen_defines.asm, which the asm code depends on 345 add_custom_command(TARGET asm_offset POST_BUILD 346 COMMAND Python3::Interpreter ${PROJECT_SOURCE_DIR}/scripts/parse_asm_values.py "${ASM_OFFSET_EXECUTABLE_LOCATION}" 347 "${ASM_OFFSET_INTERMEDIATE_LOCATION}" "GAS" "${CMAKE_C_COMPILER_ID}" "${ASM_OFFSET_SYSTEM_PROCESSOR}" 348 BYPRODUCTS gen_defines.asm 349 ) 350 endif() 351 add_custom_target(loader_asm_gen_files DEPENDS gen_defines.asm) 352 353 if (APPLE) 354 set(MODIFY_UNKNOWN_FUNCTION_DECLS ON) 355 endif() 356 set(UNKNOWN_FUNCTIONS_SUPPORTED ON) 357 else() 358 if(USE_GAS) 359 message(WARNING "Could not find working ${ASM_OFFSET_SYSTEM_PROCESSOR} GAS assembler\n${ASM_FAILURE_MSG}") 360 else() 361 message(WARNING "Assembly sources have been disabled\n${ASM_FAILURE_MSG}") 362 endif() 363 endif() 364endif() 365 366if(UNKNOWN_FUNCTIONS_SUPPORTED) 367 list(APPEND NORMAL_LOADER_SRCS ${OPT_LOADER_SRCS}) 368endif() 369 370if(WIN32) 371 # If BUILD_DLL_VERSIONINFO was set, use the loader.rc in the build dir, otherwise use the checked in file 372 set(RC_FILE_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/loader.rc) 373 if (NOT "$CACHE{BUILD_DLL_VERSIONINFO}" STREQUAL "") 374 set(RC_FILE_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/loader.rc) 375 endif() 376 377 add_library(vulkan 378 SHARED 379 ${NORMAL_LOADER_SRCS} 380 ${CMAKE_CURRENT_SOURCE_DIR}/${API_TYPE}-1.def 381 ${RC_FILE_LOCATION}) 382 383 target_link_libraries(vulkan PRIVATE loader_specific_options) 384 385 # when adding the suffix the import and runtime library names must be consistent 386 # mingw: libvulkan-1.dll.a / vulkan-1.dll 387 # msvc: vulkan-1.lib / vulkan-1.dll 388 set_target_properties(vulkan 389 PROPERTIES 390 OUTPUT_NAME ${API_TYPE}-1) 391 if(MINGW) 392 # generate the same DLL with mingw 393 set_target_properties(vulkan 394 PROPERTIES 395 PREFIX "") 396 endif() 397 398 if(MSVC AND ENABLE_WIN10_ONECORE) 399 target_link_libraries(vulkan PRIVATE OneCoreUAP.lib LIBCMT.LIB LIBCMTD.LIB LIBVCRUNTIME.LIB LIBUCRT.LIB) 400 set_target_properties(vulkan PROPERTIES LINK_FLAGS "/NODEFAULTLIB") 401 else() 402 target_link_libraries(vulkan PRIVATE cfgmgr32) 403 endif() 404 405else() 406 if(APPLE) 407 option(APPLE_STATIC_LOADER "Build a loader that can be statically linked. Intended for Chromium usage/testing.") 408 mark_as_advanced(APPLE_STATIC_LOADER) 409 endif() 410 411 if(APPLE_STATIC_LOADER) 412 add_library(vulkan STATIC) 413 target_compile_definitions(vulkan PRIVATE APPLE_STATIC_LOADER) 414 415 message(WARNING "The APPLE_STATIC_LOADER option has been set. Note that this will only work on MacOS and is not supported " 416 "or tested as part of the loader. Use it at your own risk.") 417 else() 418 add_library(vulkan SHARED) 419 endif() 420 421 target_sources(vulkan PRIVATE ${NORMAL_LOADER_SRCS}) 422 423 set_target_properties(vulkan PROPERTIES 424 SOVERSION "1" 425 VERSION "${VULKAN_LOADER_VERSION}" 426 ) 427 428 target_link_libraries(vulkan PRIVATE ${CMAKE_DL_LIBS} m Threads::Threads) 429 430 set_target_properties(vulkan PROPERTIES OUTPUT_NAME ${API_TYPE}) 431 432 if (LOADER_ENABLE_ADDRESS_SANITIZER) 433 target_compile_options(vulkan PUBLIC -fsanitize=address) 434 target_link_options(vulkan PUBLIC -fsanitize=address) 435 endif() 436 if (LOADER_ENABLE_THREAD_SANITIZER) 437 target_compile_options(vulkan PUBLIC -fsanitize=thread) 438 target_link_options(vulkan PUBLIC -fsanitize=thread) 439 endif() 440 if (LOADER_ENABLE_UNDEFINED_BEHAVIOR_SANITIZER) 441 target_compile_options(vulkan PUBLIC -fsanitize=undefined) 442 target_link_options(vulkan PUBLIC -fsanitize=undefined) 443 endif() 444 445 if(APPLE) 446 find_library(COREFOUNDATION_LIBRARY NAMES CoreFoundation) 447 target_link_libraries(vulkan PRIVATE "-framework CoreFoundation") 448 449 # Build vulkan.framework 450 # Use GLOB_RECURSE to find all the header files and populate the vulkan.framework headers with them 451 # Use CONFIGURE_DEPENDS to ensure that if the header files are updated, this list is also updated 452 get_target_property(VulkanHeaders_INCLUDE_DIRS Vulkan::Headers INTERFACE_INCLUDE_DIRECTORIES) 453 file(GLOB_RECURSE CONFIGURE_DEPENDS FRAMEWORK_HEADERS ${VulkanHeaders_INCLUDE_DIRS}) 454 455 add_library(vulkan-framework SHARED) 456 target_sources(vulkan-framework PRIVATE ${NORMAL_LOADER_SRCS} ${FRAMEWORK_HEADERS}) 457 458 if (UNKNOWN_FUNCTIONS_SUPPORTED) 459 add_dependencies(vulkan-framework loader_asm_gen_files) 460 endif() 461 462 target_link_libraries(vulkan-framework ${CMAKE_DL_LIBS} Threads::Threads -lm "-framework CoreFoundation") 463 target_link_libraries(vulkan-framework loader_specific_options) 464 465 if (MODIFY_UNKNOWN_FUNCTION_DECLS) 466 # Modifies the names of functions as they appearin the assembly code so that the 467 # unknown function handling will work 468 target_compile_definitions(vulkan PRIVATE MODIFY_UNKNOWN_FUNCTION_DECLS) 469 target_compile_definitions(vulkan-framework PRIVATE MODIFY_UNKNOWN_FUNCTION_DECLS) 470 endif() 471 472 # The FRAMEWORK_VERSION needs to be "A" here so that Xcode code-signing works when a user adds their framework to an Xcode 473 # project and does "Sign on Copy". It would have been nicer to use "1" to denote Vulkan 1. Although Apple docs say that a 474 # framework version does not have to be "A", this part of the Apple toolchain expects it. 475 # https://forums.developer.apple.com/thread/65963 476 477 set_target_properties(vulkan-framework PROPERTIES 478 OUTPUT_NAME vulkan 479 FRAMEWORK TRUE 480 FRAMEWORK_VERSION A 481 VERSION "${VULKAN_LOADER_VERSION}" 482 MACOSX_FRAMEWORK_BUNDLE_VERSION "${VULKAN_LOADER_VERSION}" 483 MACOSX_FRAMEWORK_SHORT_VERSION_STRING "${VULKAN_LOADER_VERSION}" 484 SOVERSION "1.0.0" 485 MACOSX_FRAMEWORK_IDENTIFIER com.lunarg.vulkanFramework 486 PUBLIC_HEADER "${FRAMEWORK_HEADERS}" 487 ) 488 489 # Workaround linker warning: https://github.com/KhronosGroup/Vulkan-Loader/issues/1332 490 # 491 # MACHO_CURRENT_VERSION specifically applies to the -current_version linker option which is the 492 # linker warning we are trying to address. 493 set(APPLE_VULKAN_LOADER_VERSION "${VULKAN_LOADER_VERSION_MAJOR}.${VULKAN_LOADER_VERSION_MINOR}.0") 494 set_target_properties(vulkan PROPERTIES MACHO_CURRENT_VERSION "${APPLE_VULKAN_LOADER_VERSION}") 495 set_target_properties(vulkan-framework PROPERTIES MACHO_CURRENT_VERSION "${APPLE_VULKAN_LOADER_VERSION}") 496 497 install(TARGETS vulkan-framework 498 PUBLIC_HEADER DESTINATION vulkan 499 FRAMEWORK DESTINATION loader 500 ) 501 endif() 502endif() 503 504option(LOADER_USE_UNSAFE_FILE_SEARCH "Allows the loader to search in unsafe locations") 505if (LOADER_USE_UNSAFE_FILE_SEARCH) 506 target_compile_definitions(vulkan PRIVATE LOADER_USE_UNSAFE_FILE_SEARCH) 507endif() 508 509# common attributes of the vulkan library 510target_link_libraries(vulkan PRIVATE loader_specific_options) 511 512target_link_libraries(vulkan PRIVATE Vulkan::Headers) 513add_library(Vulkan::Loader ALIAS vulkan) 514 515if (UNKNOWN_FUNCTIONS_SUPPORTED) 516 target_compile_definitions(vulkan PRIVATE UNKNOWN_FUNCTIONS_SUPPORTED) 517 add_dependencies(vulkan loader_asm_gen_files) 518endif() 519 520if (BUILD_TESTS) 521 target_compile_definitions(vulkan PRIVATE SHOULD_EXPORT_TEST_FUNCTIONS) 522endif() 523 524if (APPLE_STATIC_LOADER) 525 # TLDR: This feature only exists at the request of Google for Chromium. No other project should use this! 526 message(NOTICE "Apple STATIC lib: it will be built but not installed, and vulkan.pc and VulkanLoaderConfig.cmake won't be generated!") 527 return() 528endif() 529 530# Generate CMake Configuration File (IE: VulkanLoaderConfig.cmake) 531install(TARGETS vulkan EXPORT VulkanLoaderConfig) 532set_target_properties(vulkan PROPERTIES EXPORT_NAME "Loader") 533install(EXPORT VulkanLoaderConfig DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/VulkanLoader NAMESPACE Vulkan::) 534 535# Generate CMake Version File (IE: VulkanLoaderConfigVersion.cmake) 536include(CMakePackageConfigHelpers) 537 538set(version_config "${CMAKE_CURRENT_BINARY_DIR}/generated/VulkanLoaderConfigVersion.cmake") 539write_basic_package_version_file("${version_config}" COMPATIBILITY SameMajorVersion) 540install(FILES "${version_config}" DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/VulkanLoader) 541 542# Generate PkgConfig File (IE: vulkan.pc) 543# NOTE: Hopefully in the future CMake can generate .pc files natively. 544# https://gitlab.kitware.com/cmake/cmake/-/issues/22621 545find_package(PkgConfig) 546if (PKG_CONFIG_FOUND) 547 if(WIN32) 548 if(MINGW) 549 set(VULKAN_LIB_SUFFIX "-1.dll") 550 else() 551 set(VULKAN_LIB_SUFFIX "-1") 552 endif() 553 endif() 554 555 # BUG: The following code will NOT work well with `cmake --install ... --prefix <dir>` 556 # due to this code relying on CMAKE_INSTALL_PREFIX being defined at configure time. 557 # 558 # NOTE: vulkan.pc essentially cover both Vulkan-Loader and Vulkan-Headers for legacy reasons. 559 if ("${CMAKE_INSTALL_PREFIX}" STREQUAL "") 560 set(CMAKE_INSTALL_LIBDIR_PC ${CMAKE_INSTALL_FULL_LIBDIR}) 561 set(CMAKE_INSTALL_INCLUDEDIR_PC ${CMAKE_INSTALL_FULL_INCLUDEDIR}) 562 else() 563 file(RELATIVE_PATH CMAKE_INSTALL_LIBDIR_PC ${CMAKE_INSTALL_PREFIX} ${CMAKE_INSTALL_FULL_LIBDIR}) 564 file(RELATIVE_PATH CMAKE_INSTALL_INCLUDEDIR_PC ${CMAKE_INSTALL_PREFIX} ${CMAKE_INSTALL_FULL_INCLUDEDIR}) 565 endif() 566 configure_file("vulkan.pc.in" "vulkan.pc" @ONLY) 567 install(FILES "${CMAKE_CURRENT_BINARY_DIR}/vulkan.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig" RENAME "${API_TYPE}.pc") 568endif() 569 570if (CODE_COVERAGE) 571 target_code_coverage(vulkan AUTO ALL) 572endif() 573