1# Copyright (C) 2020-2025 The Khronos Group Inc. 2# 3# All rights reserved. 4# 5# Redistribution and use in source and binary forms, with or without 6# modification, are permitted provided that the following conditions 7# are met: 8# 9# Redistributions of source code must retain the above copyright 10# notice, this list of conditions and the following disclaimer. 11# 12# Redistributions in binary form must reproduce the above 13# copyright notice, this list of conditions and the following 14# disclaimer in the documentation and/or other materials provided 15# with the distribution. 16# 17# Neither the name of The Khronos Group Inc. nor the names of its 18# contributors may be used to endorse or promote products derived 19# from this software without specific prior written permission. 20# 21# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 27# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 31# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32# POSSIBILITY OF SUCH DAMAGE. 33cmake_minimum_required(VERSION 3.22.1) 34project(glslang) 35 36set(GLSLANG_TESTS_DEFAULT ON) # Can be turned off, below, based on environment. 37set(GLSLANG_ENABLE_INSTALL_DEFAULT ON) # Can be turned off, below, based on environment. 38 39set_property(GLOBAL PROPERTY USE_FOLDERS ON) # Can be removed when min is 3.26 see policy CMP0143. 40 41# Adhere to GNU filesystem layout conventions 42include(GNUInstallDirs) 43include(CMakePackageConfigHelpers) 44 45# Needed for cmake_dependent_option macro 46include(CMakeDependentOption) 47 48option(BUILD_SHARED_LIBS "Build Shared Libraries") 49option(BUILD_EXTERNAL "Build external dependencies in /External" ON) 50option(BUILD_WERROR "Enable warnings as errors (default is OFF)" OFF) 51 52set(LIB_TYPE STATIC) 53 54if(BUILD_SHARED_LIBS) 55 set(LIB_TYPE SHARED) 56endif() 57 58get_cmake_property(isMultiConfig "GENERATOR_IS_MULTI_CONFIG") 59if (NOT isMultiConfig AND NOT CMAKE_BUILD_TYPE) 60 # This logic inside SPIRV-Tools, which can upset build target dependencies 61 # if changed after targets are already defined. To prevent these issues, 62 # ensure CMAKE_BUILD_TYPE is assigned early and at the glslang root scope. 63 message(STATUS "No build type selected, default to Debug") 64 set(CMAKE_BUILD_TYPE "Debug") 65endif() 66 67# Currently iOS and Android are very similar. 68# They both have their own packaging (APP/APK). 69# Which makes regular executables/testing problematic. 70# 71# Currently the only deliverables for these platforms are 72# libraries (either STATIC or SHARED). 73# 74# Furthermore testing is equally problematic. 75if (IOS OR ANDROID) 76 set(ENABLE_GLSLANG_BINARIES OFF) 77 set(GLSLANG_TESTS_DEFAULT OFF) 78endif() 79 80# Simplify the default case of including this project. 81# Otherwise add_subdirectory users have a harder time consuming the library. 82# Since glslang will pollute the installation and add undesirable testing. 83if(NOT PROJECT_IS_TOP_LEVEL) 84 set(GLSLANG_TESTS_DEFAULT OFF) 85 set(GLSLANG_ENABLE_INSTALL_DEFAULT OFF) 86endif() 87 88# Control whether Glslang self-tests are built and tested. 89# Always expose this as an option, so the defaults can be overridden. 90option(GLSLANG_TESTS "Enable glslang testing" ${GLSLANG_TESTS_DEFAULT}) 91 92# Control whether to install Glslang. 93# Always expose this as an option, so the defaults can be overridden. 94option(GLSLANG_ENABLE_INSTALL "Enable glslang installation" ${GLSLANG_ENABLE_INSTALL_DEFAULT}) 95 96option(ENABLE_SPIRV "Enables SPIRV output support" ON) 97option(ENABLE_SPVREMAPPER "Enables building of SPVRemapper" ON) 98 99option(ENABLE_GLSLANG_BINARIES "Builds glslang and spirv-remap" ON) 100 101option(ENABLE_GLSLANG_JS "If using Emscripten, build glslang.js. Otherwise, builds a sample executable for binary-size testing.") 102cmake_dependent_option(ENABLE_EMSCRIPTEN_SINGLE_FILE 103 "If using Emscripten, enables SINGLE_FILE build" 104 OFF "ENABLE_GLSLANG_JS AND EMSCRIPTEN" 105 OFF) 106cmake_dependent_option(ENABLE_EMSCRIPTEN_ENVIRONMENT_NODE 107 "If using Emscripten, builds to run on Node instead of Web" 108 OFF "ENABLE_GLSLANG_JS AND EMSCRIPTEN" 109 OFF) 110 111option(ENABLE_HLSL "Enables HLSL input support" ON) 112option(ENABLE_RTTI "Enables RTTI") 113option(ENABLE_EXCEPTIONS "Enables Exceptions") 114cmake_dependent_option(ENABLE_OPT "Enables spirv-opt capability if present" ON "ENABLE_SPIRV" OFF) 115 116if(MINGW OR (APPLE AND ${CMAKE_CXX_COMPILER_ID} MATCHES "GNU")) 117 # Workaround for CMake behavior on Mac OS with gcc, cmake generates -Xarch_* arguments 118 # which gcc rejects 119 set(ENABLE_PCH OFF) 120 message(NOTICE "Disabling PCH") 121endif() 122 123option(ENABLE_PCH "Enables Precompiled header" ON) 124 125if(ENABLE_SPIRV) 126 add_compile_definitions(ENABLE_SPIRV) 127endif() 128 129if(ENABLE_HLSL) 130 add_compile_definitions(ENABLE_HLSL) 131endif() 132 133if(WIN32) 134 set(CMAKE_DEBUG_POSTFIX "d") 135 add_compile_definitions(GLSLANG_OSINCLUDE_WIN32) 136elseif(UNIX OR ANDROID) 137 add_compile_definitions(GLSLANG_OSINCLUDE_UNIX) 138else() 139 message("unknown platform") 140endif() 141 142if(${CMAKE_CXX_COMPILER_ID} MATCHES "GNU") 143 add_compile_options(-Wall -Wmaybe-uninitialized -Wuninitialized -Wunused -Wunused-local-typedefs -Wimplicit-fallthrough 144 -Wunused-parameter -Wunused-value -Wunused-variable -Wunused-but-set-parameter -Wunused-but-set-variable -fno-exceptions) 145 if(NOT ENABLE_RTTI) 146 add_compile_options(-fno-rtti) 147 endif() 148 if(NOT ENABLE_EXCEPTIONS) 149 add_compile_options(-fno-exceptions) 150 endif() 151 if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "9.0.0") 152 add_compile_options(-Werror=deprecated-copy) 153 endif() 154 155 if(NOT (CMAKE_SYSTEM_NAME STREQUAL "OpenBSD")) 156 if (NOT APPLE) 157 # Error if there's symbols that are not found at link time. 158 add_link_options("-Wl,--no-undefined") 159 endif() 160 endif() 161elseif(${CMAKE_CXX_COMPILER_ID} MATCHES "Clang" AND NOT MSVC) 162 add_compile_options(-Wall -Wuninitialized -Wunused -Wunused-local-typedefs -Wimplicit-fallthrough 163 -Wunused-parameter -Wunused-value -Wunused-variable) 164 if(NOT ENABLE_RTTI) 165 add_compile_options(-fno-rtti) 166 endif() 167 if(NOT ENABLE_EXCEPTIONS) 168 add_compile_options(-fno-exceptions) 169 endif() 170 171 if(NOT (CMAKE_SYSTEM_NAME MATCHES "OpenBSD|Emscripten")) 172 # Error if there's symbols that are not found at link time. Some linkers do not support this flag. 173 if(NOT APPLE) 174 add_link_options("-Wl,--no-undefined") 175 endif() 176 endif() 177elseif(MSVC) 178 if(NOT ENABLE_RTTI) 179 add_compile_options(/GR-) # Disable RTTI 180 endif() 181 if(ENABLE_EXCEPTIONS) 182 add_compile_options(/EHsc) # Enable Exceptions 183 else() 184 string(REGEX REPLACE "/EHsc" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") # Try to remove default /EHsc cxx_flag 185 add_compile_options(/D_HAS_EXCEPTIONS=0) 186 endif() 187endif() 188 189# NOTE we could potentially replace this logic with COMPILE_WARNING_AS_ERROR if cmake minimum is bumped to >= 3.24 190if (BUILD_WERROR) 191 if (NOT MSVC) 192 add_compile_options(-Werror) 193 else() 194 add_compile_options(/WX) 195 endif() 196endif() 197 198if(ENABLE_GLSLANG_JS) 199 if(MSVC) 200 add_compile_options(/Os /GR-) 201 else() 202 add_compile_options(-Os -fno-rtti -fno-exceptions) 203 if(${CMAKE_CXX_COMPILER_ID} MATCHES "Clang" AND NOT MSVC) 204 add_compile_options(-Wno-unused-parameter) 205 add_compile_options(-Wno-unused-variable -Wno-unused-const-variable) 206 endif() 207 endif() 208endif() 209 210# Request C++17 211set(CMAKE_CXX_STANDARD 17) 212set(CMAKE_CXX_STANDARD_REQUIRED ON) 213set(CMAKE_CXX_EXTENSIONS OFF) 214 215function(glslang_set_link_args TARGET) 216 # For MinGW compiles, statically link against the GCC and C++ runtimes. 217 # This avoids the need to ship those runtimes as DLLs. 218 # This is supported by GCC and Clang. 219 if(MINGW) 220 target_link_options(${TARGET} PRIVATE -static -static-libgcc -static-libstdc++) 221 endif() 222endfunction() 223 224# Root directory for build-time generated include files 225set(GLSLANG_GENERATED_INCLUDEDIR "${CMAKE_BINARY_DIR}/include") 226 227################################################################################ 228# Build version information generation 229################################################################################ 230include(parse_version.cmake) 231set(GLSLANG_CHANGES_FILE "${CMAKE_CURRENT_SOURCE_DIR}/CHANGES.md") 232set(GLSLANG_BUILD_INFO_H_TMPL "${CMAKE_CURRENT_SOURCE_DIR}/build_info.h.tmpl") 233set(GLSLANG_BUILD_INFO_H "${GLSLANG_GENERATED_INCLUDEDIR}/glslang/build_info.h") 234 235parse_version(${GLSLANG_CHANGES_FILE} GLSLANG) 236 237function(configurate_version) 238 set(major ${GLSLANG_VERSION_MAJOR}) 239 set(minor ${GLSLANG_VERSION_MINOR}) 240 set(patch ${GLSLANG_VERSION_PATCH}) 241 set(flavor ${GLSLANG_VERSION_FLAVOR}) 242 configure_file(${GLSLANG_BUILD_INFO_H_TMPL} ${GLSLANG_BUILD_INFO_H} @ONLY) 243endfunction() 244 245configurate_version() 246 247# glslang_add_build_info_dependency() adds the glslang-build-info dependency and 248# generated include directories to target. 249function(glslang_add_build_info_dependency target) 250 target_include_directories(${target} PUBLIC $<BUILD_INTERFACE:${GLSLANG_GENERATED_INCLUDEDIR}>) 251endfunction() 252 253# glslang_only_export_explicit_symbols() makes the symbol visibility hidden by 254# default for <target> when building shared libraries, and sets the 255# GLSLANG_IS_SHARED_LIBRARY define, and GLSLANG_EXPORTING to 1 when specifically 256# building <target>. 257function(glslang_only_export_explicit_symbols target) 258 if(BUILD_SHARED_LIBS) 259 target_compile_definitions(${target} PUBLIC "GLSLANG_IS_SHARED_LIBRARY=1") 260 set_target_properties(${target} PROPERTIES CXX_VISIBILITY_PRESET hidden) 261 set_target_properties(${target} PROPERTIES C_VISIBILITY_PRESET hidden) 262 if(WIN32) 263 target_compile_definitions(${target} PRIVATE "GLSLANG_EXPORTING=1") 264 endif() 265 endif() 266endfunction() 267 268# glslang_pch() adds precompiled header rules to <target> for the pre-compiled 269# header file <pch>. As target_precompile_headers() was added in CMake 3.16, 270# this is a no-op if called on earlier versions of CMake. 271function(glslang_pch target pch) 272 if(ENABLE_PCH) 273 target_precompile_headers(${target} PRIVATE ${pch}) 274 endif() 275endfunction() 276 277if(BUILD_EXTERNAL AND IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/External) 278 # We depend on these for later projects, so they should come first. 279 add_subdirectory(External) 280endif() 281 282option(ALLOW_EXTERNAL_SPIRV_TOOLS "Allows to build against installed SPIRV-Tools-opt. This is unsupported if the commit isn't the one in known_good.json") 283if(NOT TARGET SPIRV-Tools-opt) 284 if(ALLOW_EXTERNAL_SPIRV_TOOLS) 285 # Look for external SPIR-V Tools build, if not building in-tree 286 message(STATUS "Trying to find local SPIR-V tools") 287 find_package(SPIRV-Tools-opt) 288 if(NOT TARGET SPIRV-Tools-opt) 289 if(ENABLE_OPT) 290 message(SEND_ERROR "ENABLE_OPT set but SPIR-V tools not found! Disabling SPIR-V optimization.") 291 endif() 292 set(ENABLE_OPT OFF) 293 endif() 294 else() 295 if(ENABLE_OPT) 296 message(SEND_ERROR "ENABLE_OPT set but SPIR-V tools not found. Please run update_glslang_sources.py, " 297 "set the ALLOW_EXTERNAL_SPIRV_TOOLS option to use a local install of SPIRV-Tools, or set ENABLE_OPT=0.") 298 endif() 299 endif() 300endif() 301 302if(ENABLE_OPT) 303 message(STATUS "optimizer enabled") 304 add_compile_definitions(ENABLE_OPT=1) 305else() 306 if(ENABLE_HLSL) 307 message(STATUS "spirv-tools not linked - illegal SPIRV may be generated for HLSL") 308 endif() 309 add_compile_definitions(ENABLE_OPT=0) 310endif() 311 312if(ENABLE_SPIRV) 313 add_subdirectory(SPIRV) 314endif() 315add_subdirectory(glslang) 316if(ENABLE_GLSLANG_BINARIES) 317 add_subdirectory(StandAlone) 318endif() 319 320if(GLSLANG_TESTS) 321 enable_testing() 322 add_subdirectory(gtests) 323 324 # glslang-testsuite runs a bash script on Windows. 325 # Make sure to use '-o igncr' flag to ignore carriage returns (\r). 326 set(IGNORE_CR_FLAG "") 327 if(WIN32) 328 set(IGNORE_CR_FLAG -o igncr) 329 endif() 330 331 if (isMultiConfig) 332 set(RESULTS_PATH ${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>/localResults) 333 set(VALIDATOR_PATH ${CMAKE_CURRENT_BINARY_DIR}/StandAlone/$<CONFIG>/glslang) 334 set(REMAP_PATH ${CMAKE_CURRENT_BINARY_DIR}/StandAlone/$<CONFIG>/spirv-remap) 335 else() 336 set(RESULTS_PATH ${CMAKE_CURRENT_BINARY_DIR}/localResults) 337 set(VALIDATOR_PATH ${CMAKE_CURRENT_BINARY_DIR}/StandAlone/glslang) 338 set(REMAP_PATH ${CMAKE_CURRENT_BINARY_DIR}/StandAlone/spirv-remap) 339 endif() 340 341 # The TARGET_RUNTIME_DLL_DIRS feature requires CMake 3.27 or greater. 342 if(WIN32 AND BUILD_SHARED_LIBS AND CMAKE_VERSION VERSION_LESS "3.27") 343 message(WARNING "The Windows shared library test configuration requires CMake 3.27 or greater") 344 else() 345 add_test(NAME glslang-testsuite 346 COMMAND bash ${IGNORE_CR_FLAG} runtests ${RESULTS_PATH} ${VALIDATOR_PATH} ${REMAP_PATH} 347 WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/Test/) 348 349 # Prepend paths to shared libraries. 350 if (BUILD_SHARED_LIBS) 351 set_tests_properties(glslang-testsuite PROPERTIES ENVIRONMENT_MODIFICATION "PATH=path_list_prepend:$<JOIN:$<TARGET_RUNTIME_DLL_DIRS:glslang-standalone>,\;>") 352 set_tests_properties(glslang-testsuite PROPERTIES ENVIRONMENT_MODIFICATION "PATH=path_list_prepend:$<JOIN:$<TARGET_RUNTIME_DLL_DIRS:spirv-remap>,\;>") 353 endif() 354 endif() 355endif() 356 357if (GLSLANG_ENABLE_INSTALL) 358 file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/glslang-config.cmake.in" [=[ 359 @PACKAGE_INIT@ 360 include(CMakeFindDependencyMacro) 361 if(@ENABLE_OPT@) 362 find_dependency(SPIRV-Tools-opt) 363 endif() 364 @INSTALL_CONFIG_UNIX@ 365 include("@PACKAGE_PATH_EXPORT_TARGETS@") 366 ]=]) 367 368 set(PATH_EXPORT_TARGETS "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}/glslang-targets.cmake") 369 if(UNIX OR "${CMAKE_SYSTEM_NAME}" STREQUAL "Fuchsia") 370 set(INSTALL_CONFIG_UNIX [=[ 371 set(THREADS_PREFER_PTHREAD_FLAG ON) 372 find_dependency(Threads) 373 ]=]) 374 endif() 375 configure_package_config_file( 376 "${CMAKE_CURRENT_BINARY_DIR}/glslang-config.cmake.in" 377 "${CMAKE_CURRENT_BINARY_DIR}/glslang-config.cmake" 378 PATH_VARS 379 PATH_EXPORT_TARGETS 380 INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} 381 ) 382 383 write_basic_package_version_file("${CMAKE_CURRENT_BINARY_DIR}/glslang-config-version.cmake" 384 VERSION ${GLSLANG_VERSION} 385 COMPATIBILITY SameMajorVersion 386 ) 387 388 install( 389 EXPORT glslang-targets 390 NAMESPACE "glslang::" 391 DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" 392 ) 393 394 install( 395 FILES 396 "${CMAKE_CURRENT_BINARY_DIR}/glslang-config.cmake" 397 "${CMAKE_CURRENT_BINARY_DIR}/glslang-config-version.cmake" 398 DESTINATION 399 "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" 400 ) 401endif() 402