# This modules provides variables with recommended Compiler and Linker switches # # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. set(COMPILER_DEFINES "") set(COMPILER_SWITCHES "") set(LINKER_SWITCHES "") #--- Determines target architecture if not explicitly set if(DEFINED VCPKG_TARGET_ARCHITECTURE) set(DIRECTX_ARCH ${VCPKG_TARGET_ARCHITECTURE}) elseif(CMAKE_GENERATOR_PLATFORM MATCHES "^[Ww][Ii][Nn]32$") set(DIRECTX_ARCH x86) elseif(CMAKE_GENERATOR_PLATFORM MATCHES "^[Xx]64$") set(DIRECTX_ARCH x64) elseif(CMAKE_GENERATOR_PLATFORM MATCHES "^[Aa][Rr][Mm]$") set(DIRECTX_ARCH arm) elseif(CMAKE_GENERATOR_PLATFORM MATCHES "^[Aa][Rr][Mm]64$") set(DIRECTX_ARCH arm64) elseif(CMAKE_GENERATOR_PLATFORM MATCHES "^[Aa][Rr][Mm]64EC$") set(DIRECTX_ARCH arm64ec) elseif(CMAKE_VS_PLATFORM_NAME_DEFAULT MATCHES "^[Ww][Ii][Nn]32$") set(DIRECTX_ARCH x86) elseif(CMAKE_VS_PLATFORM_NAME_DEFAULT MATCHES "^[Xx]64$") set(DIRECTX_ARCH x64) elseif(CMAKE_VS_PLATFORM_NAME_DEFAULT MATCHES "^[Aa][Rr][Mm]$") set(DIRECTX_ARCH arm) elseif(CMAKE_VS_PLATFORM_NAME_DEFAULT MATCHES "^[Aa][Rr][Mm]64$") set(DIRECTX_ARCH arm64) elseif(CMAKE_VS_PLATFORM_NAME_DEFAULT MATCHES "^[Aa][Rr][Mm]64EC$") set(DIRECTX_ARCH arm64ec) endif() #--- Determines host architecture if(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "[Aa][Rr][Mm]64|aarch64|arm64") set(DIRECTX_HOST_ARCH arm64) else() set(DIRECTX_HOST_ARCH x64) endif() #--- Build with Unicode Win32 APIs per "UTF-8 Everywhere" if(WIN32) list(APPEND COMPILER_DEFINES _UNICODE UNICODE) endif() #--- General MSVC-like SDL options if(MSVC) list(APPEND COMPILER_SWITCHES "$<$>:/guard:cf>") list(APPEND LINKER_SWITCHES /DYNAMICBASE /NXCOMPAT /INCREMENTAL:NO) if((${DIRECTX_ARCH} STREQUAL "x86") OR ((CMAKE_SIZEOF_VOID_P EQUAL 4) AND (NOT (${DIRECTX_ARCH} MATCHES "^arm")))) list(APPEND LINKER_SWITCHES /SAFESEH) endif() if((MSVC_VERSION GREATER_EQUAL 1928) AND (CMAKE_SIZEOF_VOID_P EQUAL 8) AND (NOT (TARGET OpenEXR::OpenEXR)) AND ((NOT (CMAKE_CXX_COMPILER_ID MATCHES "Clang|IntelLLVM")) OR (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 13.0))) list(APPEND COMPILER_SWITCHES "$<$>:/guard:ehcont>") list(APPEND LINKER_SWITCHES "$<$>:/guard:ehcont>") endif() else() list(APPEND COMPILER_DEFINES $,_DEBUG,NDEBUG>) endif() #--- Target architecture switches if(XBOX_CONSOLE_TARGET STREQUAL "scarlett") list(APPEND COMPILER_SWITCHES $,/favor:AMD64 /arch:AVX2,-march=znver2>) elseif(XBOX_CONSOLE_TARGET MATCHES "xboxone|durango") list(APPEND COMPILER_SWITCHES $,/favor:AMD64 /arch:AVX,-march=btver2>) elseif(NOT (${DIRECTX_ARCH} MATCHES "^arm")) if((${DIRECTX_ARCH} STREQUAL "x86") OR (CMAKE_SIZEOF_VOID_P EQUAL 4)) set(ARCH_SSE2 $<$:/arch:SSE2> $<$>:-msse2>) else() set(ARCH_SSE2 $<$>:-msse2>) endif() if(CMAKE_CXX_COMPILER_ID MATCHES "GNU") list(APPEND ARCH_SSE2 -mfpmath=sse) endif() list(APPEND COMPILER_SWITCHES ${ARCH_SSE2}) endif() #--- Compiler-specific switches if(CMAKE_CXX_COMPILER_ID MATCHES "Clang|IntelLLVM") if(MSVC AND (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 16.0)) list(APPEND COMPILER_SWITCHES /ZH:SHA_256) endif() elseif(CMAKE_CXX_COMPILER_ID MATCHES "Intel") list(APPEND COMPILER_SWITCHES /Zc:__cplusplus /Zc:inline /fp:fast /Qdiag-disable:161) elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") list(APPEND COMPILER_SWITCHES /sdl /Zc:inline /fp:fast) if(CMAKE_INTERPROCEDURAL_OPTIMIZATION) message(STATUS "Building using Whole Program Optimization") list(APPEND COMPILER_SWITCHES $<$>:/Gy /Gw>) endif() if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.10) list(APPEND COMPILER_SWITCHES /permissive-) endif() if((CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.11) AND (OpenMP_CXX_FOUND OR (XBOX_CONSOLE_TARGET STREQUAL "durango"))) # OpenMP in MSVC is not compatible with /permissive- unless you disable two-phase lookup list(APPEND COMPILER_SWITCHES /Zc:twoPhase-) endif() if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.14) list(APPEND COMPILER_SWITCHES /Zc:__cplusplus) endif() if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.15) list(APPEND COMPILER_SWITCHES /JMC-) endif() if((CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.20) AND (XBOX_CONSOLE_TARGET STREQUAL "durango")) list(APPEND COMPILER_SWITCHES /d2FH4-) if(CMAKE_INTERPROCEDURAL_OPTIMIZATION) list(APPEND LINKER_SWITCHES -d2:-FH4-) endif() endif() if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.24) list(APPEND COMPILER_SWITCHES /ZH:SHA_256) endif() if((CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.26) AND (NOT (XBOX_CONSOLE_TARGET STREQUAL "durango"))) list(APPEND COMPILER_SWITCHES /Zc:preprocessor /wd5104 /wd5105) endif() if((CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.27) AND (NOT (${DIRECTX_ARCH} MATCHES "^arm"))) list(APPEND LINKER_SWITCHES /CETCOMPAT) endif() if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.28) list(APPEND COMPILER_SWITCHES /Zc:lambda) endif() if((CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.29) AND (NOT VCPKG_TOOLCHAIN)) list(APPEND COMPILER_SWITCHES /external:W4) endif() if((CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.31) AND (XBOX_CONSOLE_TARGET STREQUAL "durango")) list(APPEND COMPILER_SWITCHES /Zc:static_assert-) endif() if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.35) if(CMAKE_INTERPROCEDURAL_OPTIMIZATION) list(APPEND COMPILER_SWITCHES $<$>:/Zc:checkGwOdr>) endif() if(NOT (DEFINED XBOX_CONSOLE_TARGET)) list(APPEND COMPILER_SWITCHES $<$:/Zc:templateScope>) endif() endif() endif() #--- Windows API Family include(CheckIncludeFileCXX) if(DEFINED XBOX_CONSOLE_TARGET) message(STATUS "Building for Xbox Console Target: ${XBOX_CONSOLE_TARGET}") set(CMAKE_REQUIRED_QUIET ON) if(XBOX_CONSOLE_TARGET STREQUAL "durango") CHECK_INCLUDE_FILE_CXX(xdk.h XDKLegacy_HEADER) if(NOT XDKLegacy_HEADER) message(FATAL_ERROR "Legacy Xbox One XDK required to build for Durango.") endif() list(APPEND COMPILER_DEFINES WINAPI_FAMILY=WINAPI_FAMILY_TV_TITLE _XBOX_ONE _TITLE MONOLITHIC=1) else() CHECK_INCLUDE_FILE_CXX(gxdk.h GXDK_HEADER) if(NOT GXDK_HEADER) message(FATAL_ERROR "Microsoft GDK with Xbox Extensions required to build for Xbox. See https://aka.ms/gdkx") endif() list(APPEND COMPILER_DEFINES WINAPI_FAMILY=WINAPI_FAMILY_GAMES) if(XBOX_CONSOLE_TARGET STREQUAL "scarlett") CHECK_INCLUDE_FILE_CXX(d3d12_xs.h D3D12XS_HEADER) if(NOT D3D12XS_HEADER) message(FATAL_ERROR "Microsoft GDK with Xbox Extensions environment needs to be set for Xbox Series X|S.") endif() list(APPEND COMPILER_DEFINES _GAMING_XBOX _GAMING_XBOX_SCARLETT) elseif(XBOX_CONSOLE_TARGET STREQUAL "xboxone") CHECK_INCLUDE_FILE_CXX(d3d12_x.h D3D12X_HEADER) if(NOT D3D12X_HEADER) message(FATAL_ERROR "Microsoft GDK with Xbox Extensions environment needs to be set for Xbox One.") endif() list(APPEND COMPILER_DEFINES _GAMING_XBOX _GAMING_XBOX_XBOXONE) else() message(FATAL_ERROR "Unknown XBOX_CONSOLE_TARGET") endif() endif() elseif(WINDOWS_STORE) list(APPEND COMPILER_DEFINES WINAPI_FAMILY=WINAPI_FAMILY_APP) endif() #--- Address Sanitizer switches if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") set(ASAN_SWITCHES /fsanitize=address /fsanitize-coverage=inline-8bit-counters /fsanitize-coverage=edge /fsanitize-coverage=trace-cmp /fsanitize-coverage=trace-div) set(ASAN_LIBS sancov.lib) endif() #--- Code coverage if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") set(COV_COMPILER_SWITCHES --coverage -g) if(${DIRECTX_ARCH} STREQUAL "x64") set(COV_LIBS clang_rt.profile-x86_64.lib) elseif(${DIRECTX_ARCH} STREQUAL "x86") set(COV_LIBS clang_rt.profile-i386.lib) elseif(${DIRECTX_ARCH} STREQUAL "arm64") set(COV_LIBS clang_rt.profile-aarch64.lib) endif() elseif((CMAKE_CXX_COMPILER_ID MATCHES "MSVC") AND (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.33)) set(COV_LINKER_SWITCHES /PROFILE) endif()