1# ~~~ 2# Copyright (c) 2014-2021 The Khronos Group Inc. 3# Copyright (c) 2014-2021 Valve Corporation 4# Copyright (c) 2014-2021 LunarG, Inc. 5# Copyright (c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 6# 7# Licensed under the Apache License, Version 2.0 (the "License"); 8# you may not use this file except in compliance with the License. 9# You may obtain a copy of the License at 10# 11# http://www.apache.org/licenses/LICENSE-2.0 12# 13# Unless required by applicable law or agreed to in writing, software 14# distributed under the License is distributed on an "AS IS" BASIS, 15# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16# See the License for the specific language governing permissions and 17# limitations under the License. 18# ~~~ 19 20# Get version of the API the generated code used and put it into a cmake variable LOADER_GENERATED_HEADER_VERSION 21include(generated/loader_generated_header_version.cmake) 22 23add_library(loader_specific_options INTERFACE) 24target_link_libraries(loader_specific_options INTERFACE loader_common_options Vulkan::Headers) 25target_include_directories(loader_specific_options INTERFACE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/generated ${CMAKE_CURRENT_BINARY_DIR}) 26 27if(WIN32) 28 if(MSVC) 29 # Use static MSVCRT libraries 30 foreach(configuration 31 in 32 CMAKE_C_FLAGS_DEBUG 33 CMAKE_C_FLAGS_MINSIZEREL 34 CMAKE_C_FLAGS_RELEASE 35 CMAKE_C_FLAGS_RELWITHDEBINFO 36 CMAKE_CXX_FLAGS_DEBUG 37 CMAKE_CXX_FLAGS_MINSIZEREL 38 CMAKE_CXX_FLAGS_RELEASE 39 CMAKE_CXX_FLAGS_RELWITHDEBINFO) 40 if(${configuration} MATCHES "/MD") 41 string(REGEX 42 REPLACE "/MD" 43 "/MT" 44 ${configuration} 45 "${${configuration}}") 46 endif() 47 endforeach() 48 endif() 49 50 if(ENABLE_WIN10_ONECORE) 51 # Note: When linking your app or driver to OneCore.lib, be sure to remove any links to non-umbrella libs (such as 52 # kernel32.lib). 53 set(CMAKE_CXX_STANDARD_LIBRARIES " ") # space is intentional 54 set(CMAKE_C_STANDARD_LIBRARIES ${CMAKE_CXX_STANDARD_LIBRARIES}) 55 endif() 56 57 target_compile_options(loader_specific_options INTERFACE -D_CRT_SECURE_NO_WARNINGS) 58 # ~~~ 59 # Build dev_ext_trampoline.c and unknown_ext_chain.c with /O2 to allow tail-call optimization. 60 # Setup two CMake targets (loader-norm and loader-opt) for the different compilation flags. 61 # ~~~ 62 set(MODIFIED_C_FLAGS_DEBUG ${CMAKE_C_FLAGS_DEBUG}) 63 64 string(REPLACE "/Od" "/O2" MODIFIED_C_FLAGS_DEBUG ${MODIFIED_C_FLAGS_DEBUG}) 65 string(REPLACE "/Ob0" "/Ob2" MODIFIED_C_FLAGS_DEBUG ${MODIFIED_C_FLAGS_DEBUG}) 66 string(REGEX REPLACE "/RTC." "" MODIFIED_C_FLAGS_DEBUG ${MODIFIED_C_FLAGS_DEBUG}) #remove run-time error checks 67 68 separate_arguments(MODIFIED_C_FLAGS_DEBUG WINDOWS_COMMAND ${MODIFIED_C_FLAGS_DEBUG}) 69 70 # ~~~ 71 # Setup the loader.rc flie to contain the correct info 72 # Optionally uses the BUILD_DLL_VERSIONINFO build option to allow setting the exact build version 73 # Adds "Dev Build" to any build without the BUILD_DLL_VERSIONINFO option set 74 # ~~~ 75 if ("$CACHE{BUILD_DLL_VERSIONINFO}" STREQUAL "") 76 # default case - use 0 as the BUILDNO 77 set(LOADER_RC_VERSION "1.0.1111.2222") 78 set(LOADER_VER_FILE_VERSION_STR "\"${LOADER_RC_VERSION}.Dev Build\"") 79 set(LOADER_VER_FILE_DESCRIPTION_STR "\"Vulkan Loader - Dev Build\"") 80 else() 81 set(LOADER_RC_VERSION "$CACHE{BUILD_DLL_VERSIONINFO}") 82 set(LOADER_VER_FILE_VERSION_STR "\"${LOADER_RC_VERSION}\"") 83 set(LOADER_VER_FILE_DESCRIPTION_STR "\"Vulkan Loader\"") 84 endif() 85 86 # RC file wants the value of FILEVERSION to separated by commas 87 string(REPLACE "." ", " LOADER_VER_FILE_VERSION "${LOADER_RC_VERSION}") 88 89 # Configure the file to include the versioning info 90 # Place it in the current directory for check-in - so the GN build has up to date info 91 configure_file(loader.rc.in ${CMAKE_CURRENT_LIST_DIR}/loader.rc) 92else() 93 # Used to make alloca() and secure_getenv() available 94 target_compile_definitions(loader_specific_options INTERFACE _GNU_SOURCE) 95 if(CMAKE_SYSTEM_NAME MATCHES "FreeBSD") 96 target_compile_definitions(loader_specific_options INTERFACE __BSD_VISIBLE=1) 97 endif() 98 check_include_file("alloca.h" HAVE_ALLOCA_H) 99 if(HAVE_ALLOCA_H) 100 target_compile_definitions(loader_specific_options INTERFACE HAVE_ALLOCA_H) 101 endif() 102endif() 103 104set(NORMAL_LOADER_SRCS 105 allocation.c 106 cJSON.c 107 debug_utils.c 108 extension_manual.c 109 get_environment.c 110 gpa_helper.c 111 loader.c 112 log.c 113 terminator.c 114 trampoline.c 115 unknown_function_handling.c 116 wsi.c 117 ) 118 119if(WIN32) 120 list(APPEND NORMAL_LOADER_SRCS loader_windows.c dirent_on_windows.c) 121elseif(UNIX AND NOT APPLE) # i.e.: Linux 122 list(APPEND NORMAL_LOADER_SRCS loader_linux.c) 123 target_compile_definitions(loader_specific_options INTERFACE LOADER_ENABLE_LINUX_SORT) 124endif() 125 126set(OPT_LOADER_SRCS dev_ext_trampoline.c phys_dev_ext.c) 127 128# Check for assembler support 129set(ASM_FAILURE_MSG "The build will fall back on building with C code\n") 130set(ASM_FAILURE_MSG "${ASM_FAILURE_MSG}Note that this may be unsafe, as the C code requires tail-call optimizations to remove") 131set(ASM_FAILURE_MSG "${ASM_FAILURE_MSG} the stack frame for certain calls. If the compiler does not do this, then unknown device") 132set(ASM_FAILURE_MSG "${ASM_FAILURE_MSG} extensions will suffer from a corrupted stack.") 133if(WIN32) 134 if(MINGW) 135 find_program(JWASM_FOUND jwasm) 136 if (JWASM_FOUND) 137 set(CMAKE_ASM_MASM_COMPILER ${JWASM_FOUND}) 138 execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpmachine OUTPUT_VARIABLE COMPILER_VERSION_OUTPUT) 139 if (COMPILER_VERSION_OUTPUT) 140 if (COMPILER_VERSION_OUTPUT MATCHES "x86_64") 141 set(JWASM_FLAGS -win64) 142 else() 143 set(JWASM_FLAGS -coff) 144 endif() 145 endif() 146 endif() 147 endif() 148 option(USE_MASM "Use MASM" ON) 149 if (USE_MASM) 150 enable_language(ASM_MASM) 151 endif () 152 if(CMAKE_ASM_MASM_COMPILER_WORKS OR JWASM_FOUND) 153 if(MINGW) 154 set(CMAKE_ASM_MASM_FLAGS ${CMAKE_ASM_MASM_FLAGS} ${JWASM_FLAGS}) 155 elseif(NOT CMAKE_CL_64 AND NOT JWASM_FOUND) 156 set(CMAKE_ASM_MASM_FLAGS ${CMAKE_ASM_MASM_FLAGS} /safeseh) 157 endif() 158 159 add_executable(asm_offset asm_offset.c) 160 target_link_libraries(asm_offset loader_specific_options) 161 add_custom_command(OUTPUT gen_defines.asm DEPENDS asm_offset COMMAND asm_offset MASM) 162 add_custom_target(loader_asm_gen_files DEPENDS gen_defines.asm) 163 set_target_properties(loader_asm_gen_files PROPERTIES FOLDER ${LOADER_HELPER_FOLDER}) 164 add_library(loader-unknown-chain OBJECT unknown_ext_chain_masm.asm) 165 target_link_libraries(loader-unknown-chain Vulkan::Headers) 166 target_include_directories(loader-unknown-chain PUBLIC $<TARGET_PROPERTY:loader_asm_gen_files,BINARY_DIR>) 167 add_dependencies(loader-unknown-chain loader_asm_gen_files) 168 else() 169 message(WARNING "Could not find working MASM assembler\n${ASM_FAILURE_MSG}") 170 add_custom_target(loader_asm_gen_files) 171 add_library(loader-unknown-chain OBJECT unknown_ext_chain.c) 172 target_link_libraries(loader-unknown-chain loader_specific_options) 173 set_target_properties(loader-unknown-chain PROPERTIES CMAKE_C_FLAGS_DEBUG "${MODIFIED_C_FLAGS_DEBUG}") 174 endif() 175elseif(APPLE) 176 # For MacOS, use the C code and force the compiler's tail-call optimization instead of using assembly code. 177 set(OPT_LOADER_SRCS ${OPT_LOADER_SRCS} unknown_ext_chain.c) 178 set_source_files_properties(${OPT_LOADER_SRCS} PROPERTIES COMPILE_FLAGS -O) 179 add_custom_target(loader_asm_gen_files) # This causes no assembly files to be generated. 180else() # i.e.: Linux 181 option(USE_GAS "Use GAS" ON) 182 if(USE_GAS) 183 enable_language(ASM) 184 185 set(CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS}") 186 set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) 187 188 if (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "aarch64") 189 try_compile(ASSEMBLER_WORKS ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/asm_test_aarch64.S) 190 if(ASSEMBLER_WORKS) 191 set(OPT_LOADER_SRCS ${OPT_LOADER_SRCS} unknown_ext_chain_gas_aarch64.S) 192 endif() 193 elseif(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "x86_64" OR ${CMAKE_SYSTEM_PROCESSOR} STREQUAL "amd64" OR ${CMAKE_SYSTEM_PROCESSOR} STREQUAL "x86" OR ${CMAKE_SYSTEM_PROCESSOR} MATCHES "^i.86$") 194 check_include_file("cet.h" HAVE_CET_H) 195 if(HAVE_CET_H) 196 target_compile_definitions(loader_specific_options INTERFACE HAVE_CET_H) 197 endif() 198 199 try_compile(ASSEMBLER_WORKS ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/asm_test_x86.S) 200 if(ASSEMBLER_WORKS) 201 set(OPT_LOADER_SRCS ${OPT_LOADER_SRCS} unknown_ext_chain_gas_x86.S) 202 endif() 203 endif() 204 endif() 205 206 if(ASSEMBLER_WORKS) 207 add_executable(asm_offset asm_offset.c) 208 target_link_libraries(asm_offset loader_specific_options) 209 add_custom_command(OUTPUT gen_defines.asm DEPENDS asm_offset COMMAND asm_offset GAS) 210 add_custom_target(loader_asm_gen_files DEPENDS gen_defines.asm) 211 else() 212 if(USE_GAS) 213 message(WARNING "Could not find working ${CMAKE_SYSTEM_PROCESSOR} GAS assembler\n${ASM_FAILURE_MSG}") 214 else() 215 message(WARNING "Assembly sources have been disabled\n${ASM_FAILURE_MSG}") 216 endif() 217 set(OPT_LOADER_SRCS ${OPT_LOADER_SRCS} unknown_ext_chain.c) 218 add_custom_target(loader_asm_gen_files) 219 endif() 220endif() 221 222if(WIN32) 223 add_library(loader-opt STATIC ${OPT_LOADER_SRCS}) 224 target_link_libraries(loader-opt PUBLIC loader_specific_options) 225 add_dependencies(loader-opt loader_asm_gen_files) 226 set_target_properties(loader-opt PROPERTIES CMAKE_C_FLAGS_DEBUG "${MODIFIED_C_FLAGS_DEBUG}") 227 228 add_library(vulkan 229 SHARED 230 ${NORMAL_LOADER_SRCS} 231 $<TARGET_OBJECTS:loader-unknown-chain> 232 ${CMAKE_CURRENT_SOURCE_DIR}/vulkan-1.def 233 ${CMAKE_CURRENT_LIST_DIR}/loader.rc) 234 235 target_link_libraries(vulkan PRIVATE loader_specific_options loader-opt) 236 237 if (UPDATE_DEPS) 238 add_dependencies(vulkan vl_update_deps) 239 endif() 240 241 # when adding the suffix the import and runtime library names must be consistent 242 # mingw: libvulkan-1.dll.a / vulkan-1.dll 243 # msvc: vulkan-1.lib / vulkan-1.dll 244 set_target_properties(vulkan 245 PROPERTIES 246 OUTPUT_NAME vulkan-1) 247 if(MINGW) 248 # generate the same DLL with mingw 249 set_target_properties(vulkan 250 PROPERTIES 251 PREFIX "") 252 endif() 253 254 if(MSVC AND ENABLE_WIN10_ONECORE) 255 target_link_libraries(vulkan PRIVATE OneCoreUAP.lib LIBCMT.LIB LIBCMTD.LIB LIBVCRUNTIME.LIB LIBUCRT.LIB) 256 set_target_properties(vulkan PROPERTIES LINK_FLAGS "/NODEFAULTLIB") 257 else() 258 target_link_libraries(vulkan PRIVATE cfgmgr32) 259 endif() 260 261 add_dependencies(vulkan loader_asm_gen_files) 262 263else() 264 if(APPLE AND BUILD_STATIC_LOADER) 265 add_library(vulkan STATIC ${NORMAL_LOADER_SRCS} ${OPT_LOADER_SRCS}) 266 target_compile_definitions(vulkan PRIVATE BUILD_STATIC_LOADER) 267 else() 268 add_library(vulkan SHARED ${NORMAL_LOADER_SRCS} ${OPT_LOADER_SRCS}) 269 endif() 270 add_dependencies(vulkan loader_asm_gen_files) 271 # set version based on LOADER_GENERATED_HEADER_VERSION used to generate the code 272 set_target_properties(vulkan 273 PROPERTIES SOVERSION "1" 274 VERSION ${LOADER_GENERATED_HEADER_VERSION}) 275 target_link_libraries(vulkan PRIVATE ${CMAKE_DL_LIBS} m) 276 if (NOT ANDROID) 277 target_link_libraries(vulkan PRIVATE Threads::Threads) 278 endif() 279 280 if(APPLE) 281 find_library(COREFOUNDATION_LIBRARY NAMES CoreFoundation) 282 target_link_libraries(vulkan PRIVATE "-framework CoreFoundation") 283 284 # Build vulkan.framework 285 # Use GLOB_RECURSE to find all the header files and populate the vulkan.framework headers with them 286 # Use CONFIGURE_DEPENDS to ensure that if the header files are updated, this list is also updated 287 # Note: CONFIGURE_DEPENDS is a 3.12 feature - gate it for now and remove when CMake minimum version is higher 288 if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.12.0") 289 file(GLOB_RECURSE CONFIGURE_DEPENDS FRAMEWORK_HEADERS ${VulkanHeaders_INCLUDE_DIRS}) 290 else() 291 file(GLOB_RECURSE FRAMEWORK_HEADERS ${VulkanHeaders_INCLUDE_DIRS}) 292 endif() 293 if(BUILD_STATIC_LOADER) 294 add_library(vulkan-framework STATIC ${NORMAL_LOADER_SRCS} ${OPT_LOADER_SRCS} ${FRAMEWORK_HEADERS}) 295 else() 296 add_library(vulkan-framework SHARED ${NORMAL_LOADER_SRCS} ${OPT_LOADER_SRCS} ${FRAMEWORK_HEADERS}) 297 endif() 298 add_dependencies(vulkan-framework loader_asm_gen_files) 299 target_link_libraries(vulkan-framework ${CMAKE_DL_LIBS} Threads::Threads -lm "-framework CoreFoundation") 300 target_link_libraries(vulkan-framework loader_specific_options) 301 302 # The FRAMEWORK_VERSION needs to be "A" here so that Xcode code-signing works when a user adds their framework to an Xcode 303 # project and does "Sign on Copy". It would have been nicer to use "1" to denote Vulkan 1. Although Apple docs say that a 304 # framework version does not have to be "A", this part of the Apple toolchain expects it. 305 # https://forums.developer.apple.com/thread/65963 306 307# cmake-format: off 308 set_target_properties(vulkan-framework PROPERTIES 309 OUTPUT_NAME vulkan 310 FRAMEWORK TRUE 311 FRAMEWORK_VERSION A 312 VERSION "${LOADER_GENERATED_HEADER_VERSION}" # "current version" 313 SOVERSION "1.0.0" # "compatibility version" 314 MACOSX_FRAMEWORK_IDENTIFIER com.lunarg.vulkanFramework 315 PUBLIC_HEADER "${FRAMEWORK_HEADERS}" 316 ) 317 install(TARGETS vulkan-framework 318 PUBLIC_HEADER DESTINATION vulkan 319 FRAMEWORK DESTINATION loader 320 ) 321# cmake-format: on 322 endif() 323endif() 324 325# common attributes of the vulkan library 326target_link_libraries(vulkan PRIVATE loader_specific_options) 327 328set_target_properties(vulkan ${LOADER_STANDARD_C_PROPERTIES}) 329if (TARGET asm_offset) 330 set_target_properties(asm_offset ${LOADER_STANDARD_C_PROPERTIES}) 331endif() 332 333# Generate pkg-config file. 334include(FindPkgConfig QUIET) 335if(PKG_CONFIG_FOUND) 336 set(VK_API_VERSION "${LOADER_GENERATED_HEADER_VERSION}") 337 foreach(LIB ${CMAKE_CXX_IMPLICIT_LINK_LIBRARIES} ${PLATFORM_LIBS}) 338 set(PRIVATE_LIBS "${PRIVATE_LIBS} -l${LIB}") 339 endforeach() 340 if(WIN32) 341 if(MINGW) 342 set(VULKAN_LIB_SUFFIX "-1.dll") 343 else() 344 set(VULKAN_LIB_SUFFIX "-1") 345 endif() 346 # Set libdir path as in cmake's FindVulkan.cmake 347 # https://github.com/KhronosGroup/Vulkan-Loader/issues/668 348 if(CMAKE_SIZEOF_VOID_P EQUAL 8) 349 string(REPLACE "lib" "Lib" CMAKE_INSTALL_FULL_LIBDIR_PC ${CMAKE_INSTALL_FULL_LIBDIR}) 350 else() 351 string(REPLACE "lib" "Lib32" CMAKE_INSTALL_FULL_LIBDIR_PC ${CMAKE_INSTALL_FULL_LIBDIR}) 352 endif() 353 else() 354 set(CMAKE_INSTALL_FULL_LIBDIR_PC ${CMAKE_INSTALL_FULL_LIBDIR}) 355 endif () 356 configure_file("vulkan.pc.in" "vulkan.pc" @ONLY) 357 install(FILES "${CMAKE_CURRENT_BINARY_DIR}/vulkan.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") 358endif() 359 360target_link_libraries(vulkan PRIVATE Vulkan::Headers) 361add_library(Vulkan::Vulkan ALIAS vulkan) 362 363install(TARGETS vulkan 364 LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} 365 ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} 366 RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) 367