1# ~~~ 2# Copyright (c) 2014-2019 Valve Corporation 3# Copyright (c) 2014-2019 LunarG, Inc. 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16# ~~~ 17 18# CMake project initialization --------------------------------------------------------------------------------------------------- 19# This section contains pre-project() initialization, and ends with the project() command. 20 21cmake_minimum_required(VERSION 3.4) 22 23# Apple: Must be set before enable_language() or project() as it may influence configuration of the toolchain and flags. 24set(CMAKE_OSX_DEPLOYMENT_TARGET "10.12" CACHE STRING "Minimum OS X deployment version") 25 26project(Vulkan-ValidationLayers) 27 28# User-interface declarations ---------------------------------------------------------------------------------------------------- 29# This section contains variables that affect development GUIs (e.g. CMake GUI and IDEs), such as option(), folders, and variables 30# with the CACHE property. 31 32# API_NAME allows renaming builds to avoid conflicts with installed SDKs. It is referenced by layers/vk_loader_platform.h 33set(API_NAME "Vulkan" CACHE STRING "API name to use when building") 34string(TOLOWER ${API_NAME} API_LOWERCASE) 35add_definitions(-DAPI_NAME="${API_NAME}") 36 37set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake") 38 39find_package(PythonInterp 3 REQUIRED) 40 41if (TARGET Vulkan::Headers) 42 message(STATUS "Using Vulkan headers from Vulkan::Headers target") 43 get_target_property(VulkanHeaders_INCLUDE_DIRS Vulkan::Headers INTERFACE_INCLUDE_DIRECTORIES) 44 get_target_property(VulkanRegistry_DIR Vulkan::Registry INTERFACE_INCLUDE_DIRECTORIES) 45else() 46 find_package(VulkanHeaders REQUIRED) 47 48 # xxxnsubtil: this should eventually be replaced by exported targets 49 add_library(Vulkan-Headers INTERFACE) 50 target_include_directories(Vulkan-Headers INTERFACE ${VulkanHeaders_INCLUDE_DIRS}) 51 add_library(Vulkan::Headers ALIAS Vulkan-Headers) 52endif() 53 54option(USE_CCACHE "Use ccache" OFF) 55if(USE_CCACHE) 56 find_program(CCACHE_FOUND ccache) 57 if(CCACHE_FOUND) 58 set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache) 59 endif() 60endif() 61 62set(CMAKE_POSITION_INDEPENDENT_CODE ON) 63 64include(GNUInstallDirs) 65 66if(WIN32 AND CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) 67 # Windows: if install locations not set by user, set install prefix to "<build_dir>\install". 68 set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/install" CACHE PATH "default install path" FORCE) 69endif() 70 71if(APPLE) 72 # CMake versions 3 or later need CMAKE_MACOSX_RPATH defined. This avoids the CMP0042 policy message. 73 set(CMAKE_MACOSX_RPATH 1) 74 # The "install" target for MacOS fixes up bundles in place. 75 set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}) 76endif() 77 78# Enable IDE GUI folders 79set_property(GLOBAL PROPERTY USE_FOLDERS ON) 80# "Helper" targets that don't have interesting source code should set their FOLDER property to this 81set(LAYERS_HELPER_FOLDER "Helper Targets") 82 83# Options for Linux only 84if(UNIX AND NOT APPLE) # i.e. Linux 85 include(FindPkgConfig) 86 option(BUILD_WSI_XCB_SUPPORT "Build XCB WSI support" ON) 87 option(BUILD_WSI_XLIB_SUPPORT "Build Xlib WSI support" ON) 88 option(BUILD_WSI_WAYLAND_SUPPORT "Build Wayland WSI support" ON) 89 set(DEMOS_WSI_SELECTION "XCB" CACHE STRING "Select WSI target for demos (XCB, XLIB, WAYLAND, DISPLAY)") 90 91 if(BUILD_WSI_XCB_SUPPORT) 92 find_package(XCB REQUIRED) 93 endif() 94 95 if(BUILD_WSI_XLIB_SUPPORT) 96 find_package(X11 REQUIRED) 97 endif() 98 99 if(BUILD_WSI_WAYLAND_SUPPORT) 100 find_package(Wayland REQUIRED) 101 include_directories(${WAYLAND_CLIENT_INCLUDE_DIR}) 102 endif() 103endif() 104 105# Platform-specific compiler switches 106if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang") 107 add_compile_options(-Wall 108 -Wextra 109 -Wno-unused-parameter 110 -Wno-missing-field-initializers 111 -fno-strict-aliasing 112 -fno-builtin-memcmp 113 -fvisibility=hidden) 114 115 # Treat warnings as errors for versions of GCC and Clang that are shipped on Ubuntu 18.04 or older. 116 if((CMAKE_COMPILER_IS_GNUCXX AND NOT (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 7.3.0)) OR 117 (("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") AND NOT (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 3.8.0))) 118 add_compile_options(-Werror) 119 endif() 120 121 set(CMAKE_C_STANDARD 99) 122 set(CMAKE_CXX_STANDARD 11) 123 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti") 124 125 # For GCC version 7.1 or greater, we need to disable the implicit fallthrough warning since there's no consistent way to satisfy 126 # all compilers until they all accept the C++17 standard. 127 if(CMAKE_COMPILER_IS_GNUCC AND NOT (CMAKE_CXX_COMPILER_VERSION LESS 7.1)) 128 add_compile_options(-Wimplicit-fallthrough=0) 129 endif() 130elseif(MSVC) 131 # Treat warnings as errors 132 add_compile_options("/WX") 133 # Disable RTTI 134 add_compile_options("/GR-") 135 # Warn about nested declarations 136 add_compile_options("/w34456") 137 # Warn about potentially uninitialized variables 138 add_compile_options("/w34701") 139 add_compile_options("/w34703") 140 # Warn about different indirection types. 141 add_compile_options("/w34057") 142 # Warn about signed/unsigned mismatch. 143 add_compile_options("/w34245") 144endif() 145 146if(TARGET gtest OR IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/external/googletest) 147 option(BUILD_TESTS "Build tests" ON) 148else() 149 option(BUILD_TESTS "Build tests" OFF) 150endif() 151 152option(INSTALL_TESTS "Install tests" OFF) 153option(BUILD_LAYERS "Build layers" ON) 154option(BUILD_LAYER_SUPPORT_FILES "Generate layer files" OFF) # For generating files when not building layers 155 156if(BUILD_TESTS OR BUILD_LAYERS) 157 158 set(GLSLANG_INSTALL_DIR "GLSLANG-NOTFOUND" CACHE PATH "Absolute path to a glslang install directory") 159 if(NOT GLSLANG_INSTALL_DIR AND NOT DEFINED ENV{GLSLANG_INSTALL_DIR} AND NOT TARGET glslang) 160 message(FATAL_ERROR "Must define location of glslang binaries -- see BUILD.md") 161 endif() 162 163 # GLSLANG_INSTALL_DIR is used as the path to all dependent projects' install dirs 164 # CMake command line option overrides environment variable 165 if(NOT GLSLANG_INSTALL_DIR) 166 set(GLSLANG_INSTALL_DIR $ENV{GLSLANG_INSTALL_DIR}) 167 endif() 168 169 if (NOT TARGET glslang) 170 message(STATUS "Using glslang install located at ${GLSLANG_INSTALL_DIR}") 171 set(GLSLANG_SEARCH_PATH "${GLSLANG_INSTALL_DIR}/lib") 172 set(GLSLANG_DEBUG_SEARCH_PATH "${GLSLANG_INSTALL_DIR}/lib") 173 set(GLSLANG_SPIRV_INCLUDE_DIR "${GLSLANG_INSTALL_DIR}/include" CACHE PATH "Path to glslang spirv headers") 174 175 find_library(GLSLANG_LIB NAMES glslang HINTS ${GLSLANG_SEARCH_PATH}) 176 find_library(OGLCompiler_LIB NAMES OGLCompiler HINTS ${GLSLANG_SEARCH_PATH}) 177 find_library(OSDependent_LIB NAMES OSDependent HINTS ${GLSLANG_SEARCH_PATH}) 178 find_library(HLSL_LIB NAMES HLSL HINTS ${GLSLANG_SEARCH_PATH}) 179 find_library(SPIRV_LIB NAMES SPIRV HINTS ${GLSLANG_SEARCH_PATH}) 180 find_library(SPIRV_REMAPPER_LIB NAMES SPVRemapper HINTS ${GLSLANG_SEARCH_PATH}) 181 182 if(WIN32) 183 add_library(glslang STATIC IMPORTED) 184 add_library(OGLCompiler STATIC IMPORTED) 185 add_library(OSDependent STATIC IMPORTED) 186 add_library(HLSL STATIC IMPORTED) 187 add_library(SPIRV STATIC IMPORTED) 188 add_library(SPVRemapper STATIC IMPORTED) 189 add_library(Loader STATIC IMPORTED) 190 191 find_library(GLSLANG_DLIB NAMES glslangd HINTS ${GLSLANG_DEBUG_SEARCH_PATH}) 192 find_library(OGLCompiler_DLIB NAMES OGLCompilerd HINTS ${GLSLANG_DEBUG_SEARCH_PATH}) 193 find_library(OSDependent_DLIB NAMES OSDependentd HINTS ${GLSLANG_DEBUG_SEARCH_PATH}) 194 find_library(HLSL_DLIB NAMES HLSLd HINTS ${GLSLANG_DEBUG_SEARCH_PATH}) 195 find_library(SPIRV_DLIB NAMES SPIRVd HINTS ${GLSLANG_DEBUG_SEARCH_PATH}) 196 find_library(SPIRV_REMAPPER_DLIB NAMES SPVRemapperd HINTS ${GLSLANG_DEBUG_SEARCH_PATH}) 197 198 set_target_properties(glslang 199 PROPERTIES IMPORTED_LOCATION 200 "${GLSLANG_LIB}" 201 IMPORTED_LOCATION_DEBUG 202 "${GLSLANG_DLIB}") 203 set_target_properties(OGLCompiler 204 PROPERTIES IMPORTED_LOCATION 205 "${OGLCompiler_LIB}" 206 IMPORTED_LOCATION_DEBUG 207 "${OGLCompiler_DLIB}") 208 set_target_properties(OSDependent 209 PROPERTIES IMPORTED_LOCATION 210 "${OSDependent_LIB}" 211 IMPORTED_LOCATION_DEBUG 212 "${OSDependent_DLIB}") 213 set_target_properties(HLSL 214 PROPERTIES IMPORTED_LOCATION 215 "${HLSL_LIB}" 216 IMPORTED_LOCATION_DEBUG 217 "${HLSL_DLIB}") 218 set_target_properties(SPIRV 219 PROPERTIES IMPORTED_LOCATION 220 "${SPIRV_LIB}" 221 IMPORTED_LOCATION_DEBUG 222 "${SPIRV_DLIB}") 223 set_target_properties(SPVRemapper 224 PROPERTIES IMPORTED_LOCATION 225 "${SPIRV_REMAPPER_LIB}" 226 IMPORTED_LOCATION_DEBUG 227 "${SPIRV_REMAPPER_DLIB}") 228 229 set(GLSLANG_LIBRARIES glslang OGLCompiler OSDependent HLSL SPIRV SPVRemapper ${SPIRV_TOOLS_LIBRARIES}) 230 else() 231 set(GLSLANG_LIBRARIES 232 ${GLSLANG_LIB} 233 ${OGLCompiler_LIB} 234 ${OSDependent_LIB} 235 ${HLSL_LIB} 236 ${SPIRV_LIB} 237 ${SPIRV_REMAPPER_LIB} 238 ${SPIRV_TOOLS_LIBRARIES}) 239 endif() 240 else() 241 set(GLSLANG_SPIRV_INCLUDE_DIR "${glslang_SOURCE_DIR}" CACHE PATH "Path to glslang spirv headers") 242 set(GLSLANG_LIBRARIES glslang SPIRV SPVRemapper) 243 endif() 244 245 # spirv-tools 246 if (NOT TARGET SPIRV-Tools) 247 set(SPIRV_TOOLS_BINARY_ROOT "${GLSLANG_INSTALL_DIR}/lib" 248 CACHE PATH "User defined path to the SPIRV-Tools binaries for this project") 249 set(SPIRV_TOOLS_OPT_BINARY_ROOT "${GLSLANG_INSTALL_DIR}/lib" 250 CACHE PATH "User defined path to the SPIRV-Tools-opt binaries for this project") 251 set(SPIRV_TOOLS_INCLUDE_DIR "${GLSLANG_INSTALL_DIR}/include" CACHE PATH "Path to spirv tools headers") 252 set(SPIRV_TOOLS_SEARCH_PATH "${GLSLANG_INSTALL_DIR}/lib") 253 set(SPIRV_TOOLS_DEBUG_SEARCH_PATH "${GLSLANG_INSTALL_DIR}/lib") 254 set(SPIRV_TOOLS_OPT_SEARCH_PATH "${GLSLANG_INSTALL_DIR}/lib") 255 set(SPIRV_TOOLS_OPT_DEBUG_SEARCH_PATH "${GLSLANG_INSTALL_DIR}/lib") 256 257 find_library(SPIRV_TOOLS_LIB NAMES SPIRV-Tools HINTS ${SPIRV_TOOLS_SEARCH_PATH}) 258 find_library(SPIRV_TOOLS_OPT_LIB NAMES SPIRV-Tools-opt HINTS ${SPIRV_TOOLS_OPT_SEARCH_PATH}) 259 260 if(WIN32) 261 add_library(SPIRV-Tools-opt STATIC IMPORTED) 262 add_library(SPIRV-Tools STATIC IMPORTED) 263 264 find_library(SPIRV_TOOLS_DLIB NAMES SPIRV-Toolsd HINTS ${SPIRV_TOOLS_DEBUG_SEARCH_PATH}) 265 find_library(SPIRV_TOOLS_OPT_DLIB NAMES SPIRV-Tools-optd HINTS ${SPIRV_TOOLS_OPT_DEBUG_SEARCH_PATH}) 266 267 set_target_properties(SPIRV-Tools 268 PROPERTIES IMPORTED_LOCATION 269 "${SPIRV_TOOLS_LIB}" 270 IMPORTED_LOCATION_DEBUG 271 "${SPIRV_TOOLS_DLIB}") 272 set_target_properties(SPIRV-Tools-opt 273 PROPERTIES IMPORTED_LOCATION 274 "${SPIRV_TOOLS_OPT_LIB}" 275 IMPORTED_LOCATION_DEBUG 276 "${SPIRV_TOOLS_OPT_DLIB}") 277 278 set(SPIRV_TOOLS_LIBRARIES SPIRV-Tools-opt SPIRV-Tools) 279 else() 280 set(SPIRV_TOOLS_LIBRARIES ${SPIRV_TOOLS_OPT_LIB} ${SPIRV_TOOLS_LIB}) 281 endif() 282 else() 283 set(SPIRV_TOOLS_LIBRARIES SPIRV-Tools SPIRV-Tools-opt) 284 set(SPIRV_TOOLS_INCLUDE_DIR "${spirv-tools_SOURCE_DIR}/include" CACHE PATH "Path to spirv tools headers") 285 endif() 286 287 set(GLSLANG_LIBRARIES ${GLSLANG_LIBRARIES} ${SPIRV_TOOLS_LIBRARIES}) 288endif() 289 290# Generate dependent helper files ------------------------------------------------------------------------------------------------ 291 292set(SCRIPTS_DIR "${PROJECT_SOURCE_DIR}/scripts") 293 294# Generate a source file from vk.xml 295macro(GenerateFromVkXml dependency output) 296 add_custom_command(OUTPUT ${output} 297 COMMAND ${PYTHON_EXECUTABLE} ${SCRIPTS_DIR}/lvl_genvk.py -registry ${VulkanRegistry_DIR}/vk.xml -scripts 298 ${VulkanRegistry_DIR} ${output} 299 DEPENDS ${VulkanRegistry_DIR}/vk.xml 300 ${VulkanRegistry_DIR}/generator.py 301 ${SCRIPTS_DIR}/${dependency} 302 ${SCRIPTS_DIR}/lvl_genvk.py 303 ${VulkanRegistry_DIR}/reg.py) 304endmacro() 305 306# Add rules to generate XML-derived source files. 307GenerateFromVkXml(layer_dispatch_table_generator.py vk_layer_dispatch_table.h) 308GenerateFromVkXml(dispatch_table_helper_generator.py vk_dispatch_table_helper.h) 309GenerateFromVkXml(helper_file_generator.py vk_safe_struct.h) 310GenerateFromVkXml(helper_file_generator.py vk_safe_struct.cpp) 311GenerateFromVkXml(helper_file_generator.py vk_enum_string_helper.h) 312GenerateFromVkXml(helper_file_generator.py vk_object_types.h) 313GenerateFromVkXml(helper_file_generator.py vk_extension_helper.h) 314GenerateFromVkXml(helper_file_generator.py vk_typemap_helper.h) 315 316# This target causes the source files to be generated. 317add_custom_target(VulkanVL_generate_helper_files 318 DEPENDS vk_enum_string_helper.h 319 vk_safe_struct.h 320 vk_safe_struct.cpp 321 vk_object_types.h 322 vk_layer_dispatch_table.h 323 vk_dispatch_table_helper.h 324 vk_extension_helper.h 325 vk_typemap_helper.h) 326set_target_properties(VulkanVL_generate_helper_files PROPERTIES FOLDER ${LAYERS_HELPER_FOLDER}) 327 328# VkLayer_utils library ---------------------------------------------------------------------------------------------------------- 329# For Windows, we use a static lib because the Windows loader has a fairly restrictive loader search path that can't be easily 330# modified to point it to the same directory that contains the layers. TODO: This should not be a library -- in future, include 331# files directly in layers. 332 333add_library(VkLayer_utils 334 STATIC 335 layers/vk_layer_config.cpp 336 layers/vk_layer_extension_utils.cpp 337 layers/vk_layer_utils.cpp 338 layers/vk_format_utils.cpp) 339target_link_libraries(VkLayer_utils PUBLIC Vulkan::Headers) 340if(WIN32) 341 target_compile_definitions(VkLayer_utils PUBLIC _CRT_SECURE_NO_WARNINGS) 342endif() 343install(TARGETS VkLayer_utils DESTINATION ${CMAKE_INSTALL_LIBDIR}) 344set_target_properties(VkLayer_utils PROPERTIES LINKER_LANGUAGE CXX) 345add_dependencies(VkLayer_utils VulkanVL_generate_helper_files) 346target_include_directories(VkLayer_utils 347 PUBLIC ${VulkanHeaders_INCLUDE_DIR} 348 ${CMAKE_CURRENT_BINARY_DIR} 349 ${CMAKE_CURRENT_BINARY_DIR}/layers 350 ${PROJECT_BINARY_DIR}) 351 352# uninstall target --------------------------------------------------------------------------------------------------------------- 353if(NOT TARGET uninstall) 354 configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in" 355 "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" 356 IMMEDIATE 357 @ONLY) 358 add_custom_target(uninstall COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake) 359 set_target_properties(uninstall PROPERTIES FOLDER ${LAYERS_HELPER_FOLDER}) 360endif() 361 362# Fetch header version from vulkan_core.h ---------------------------------------------------------------------------------------- 363file(STRINGS "${VulkanHeaders_INCLUDE_DIRS}/vulkan/vulkan_core.h" lines REGEX "^#define VK_HEADER_VERSION [0-9]+") 364list(LENGTH lines len) 365if(${len} EQUAL 1) 366 string(REGEX MATCHALL 367 "[0-9]+" 368 vk_header_version 369 ${lines}) 370else() 371 message(FATAL_ERROR "Unable to fetch version from vulkan_core.h") 372endif() 373 374# Add subprojects ---------------------------------------------------------------------------------------------------------------- 375 376add_subdirectory(external) 377if(BUILD_TESTS) 378 add_subdirectory(tests) 379endif() 380 381if(BUILD_LAYERS OR BUILD_LAYER_SUPPORT_FILES) 382 add_subdirectory(layers) 383endif() 384