From 455836af8923b9ab423d6281f8ae9b9df49376d3 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Mon, 3 Feb 2025 00:30:39 +1000 Subject: [PATCH] CMake: Check C++20 features that are missing on some systems --- CMakeLists.txt | 11 +---- CMakeModules/DuckStationBuildSummary.cmake | 2 + .../DuckStationCompilerRequirement.cmake | 16 +++++++ CMakeModules/DuckStationUtils.cmake | 47 +++++++++++++++++++ src/common/heterogeneous_containers.h | 1 + 5 files changed, 68 insertions(+), 9 deletions(-) create mode 100644 CMakeModules/DuckStationCompilerRequirement.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 8e8d37371..23ee264ae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.16) +cmake_minimum_required(VERSION 3.19) project(duckstation C CXX) # Policy settings. @@ -16,10 +16,6 @@ if(NOT CMAKE_BUILD_TYPE MATCHES "Debug|Devel|MinSizeRel|RelWithDebInfo|Release") set(CMAKE_BUILD_TYPE "Release") endif() -message(STATUS "CMake Version: ${CMAKE_VERSION}") -message(STATUS "CMake System Name: ${CMAKE_SYSTEM_NAME}") -message(STATUS "Build Type: ${CMAKE_BUILD_TYPE}") - # Pull in modules. set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/CMakeModules/") include(DuckStationUtils) @@ -34,6 +30,7 @@ detect_cache_line_size() # Build options. Depends on system attributes. include(DuckStationBuildOptions) include(DuckStationDependencies) +include(DuckStationCompilerRequirement) # Enable PIC on Linux, otherwise the builds do not support ASLR. if(LINUX OR BSD) @@ -120,10 +117,6 @@ endif() # Prevent fmt from being built with exceptions, or being thrown at call sites. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DFMT_EXCEPTIONS=0") -# Use C++20. -set(CMAKE_CXX_STANDARD 20) -set(CMAKE_CXX_STANDARD_REQUIRED ON) - # Recursively include the source tree. add_subdirectory(dep) add_subdirectory(src) diff --git a/CMakeModules/DuckStationBuildSummary.cmake b/CMakeModules/DuckStationBuildSummary.cmake index adb69a259..6874b919a 100644 --- a/CMakeModules/DuckStationBuildSummary.cmake +++ b/CMakeModules/DuckStationBuildSummary.cmake @@ -1,3 +1,5 @@ +message(STATUS "Build Type: ${CMAKE_BUILD_TYPE}") + if(ENABLE_OPENGL) message(STATUS "Building with OpenGL support.") endif() diff --git a/CMakeModules/DuckStationCompilerRequirement.cmake b/CMakeModules/DuckStationCompilerRequirement.cmake new file mode 100644 index 000000000..b7fabbf86 --- /dev/null +++ b/CMakeModules/DuckStationCompilerRequirement.cmake @@ -0,0 +1,16 @@ +# Use C++20. +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +# C++20 feature checks. Some Linux environments are incomplete. +check_cpp20_feature("__cpp_structured_bindings" 201606) +check_cpp20_feature("__cpp_constinit" 201907) +check_cpp20_feature("__cpp_designated_initializers" 201707) +check_cpp20_feature("__cpp_using_enum" 201907) +check_cpp20_feature("__cpp_lib_bit_cast" 201806) +check_cpp20_feature("__cpp_lib_bitops" 201907) +check_cpp20_feature("__cpp_lib_int_pow2" 202002) +check_cpp20_feature("__cpp_lib_starts_ends_with" 201711) +check_cpp20_attribute("likely" 201803) +check_cpp20_attribute("unlikely" 201803) +check_cpp20_attribute("no_unique_address" 201803) diff --git a/CMakeModules/DuckStationUtils.cmake b/CMakeModules/DuckStationUtils.cmake index 9d7c5ad46..f0635f1ac 100644 --- a/CMakeModules/DuckStationUtils.cmake +++ b/CMakeModules/DuckStationUtils.cmake @@ -1,3 +1,5 @@ +include(CheckSourceCompiles) + function(disable_compiler_warnings_for_target target) if(MSVC) target_compile_options(${target} PRIVATE "/W0") @@ -245,3 +247,48 @@ function(install_imported_dep_library name) get_target_property(LOCATION "${name}" IMPORTED_LOCATION_RELEASE) install(FILES "${LOCATION}" RENAME "${SONAME}" DESTINATION "${CMAKE_INSTALL_LIBDIR}") endfunction() + +function(check_cpp20_feature MACRO MINIMUM_VALUE) + set(CACHE_VAR "CHECK_CPP20_FEATURE_${MACRO}") + if(NOT DEFINED ${CACHE_VAR}) + # Create a small source code snippet that fails to compile if the feature is not available. + set(TEMP_FILE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.cpp") + file(WRITE "${TEMP_FILE}" "#include +#if !defined(${MACRO}) || ${MACRO} < ${MINIMUM_VALUE}L +#error Missing feature +#endif + ") + set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) + try_compile(HAS_FEATURE + ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY} "${TEMP_FILE}" + CXX_STANDARD 20 + CXX_STANDARD_REQUIRED TRUE + ) + set(${CACHE_VAR} ${HAS_FEATURE} CACHE INTERNAL "Cached feature test result for ${MACRO}") + endif() + if(NOT HAS_FEATURE) + message(FATAL_ERROR "${MACRO} is not supported by your compiler, at least ${MINIMUM_VALUE} is required.") + endif() +endfunction() + +function(check_cpp20_attribute ATTRIBUTE MINIMUM_VALUE) + set(CACHE_VAR "CHECK_CPP20_ATTRIBUTE_${MACRO}") + if(NOT DEFINED ${CACHE_VAR}) + set(TEMP_FILE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.cpp") + file(WRITE "${TEMP_FILE}" "#include +#if !defined(__has_cpp_attribute) || __has_cpp_attribute(${ATTRIBUTE}) < ${MINIMUM_VALUE}L +#error Missing feature +#endif + ") + set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) + try_compile(HAS_FEATURE + ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY} "${TEMP_FILE}" + CXX_STANDARD 20 + CXX_STANDARD_REQUIRED TRUE + ) + set(${CACHE_VAR} ${HAS_FEATURE} CACHE INTERNAL "Cached attribute test result for ${MACRO}") + endif() + if(NOT HAS_FEATURE) + message(FATAL_ERROR "${ATTRIBUTE} is not supported by your compiler, at least ${MINIMUM_VALUE} is required.") + endif() +endfunction() diff --git a/src/common/heterogeneous_containers.h b/src/common/heterogeneous_containers.h index 2f7bf35ee..1549f36e7 100644 --- a/src/common/heterogeneous_containers.h +++ b/src/common/heterogeneous_containers.h @@ -13,6 +13,7 @@ #include #include #include +#include namespace detail { struct transparent_string_hash