blob: 45b78e1b3a42fed13f671770b9b989411e3e0abc [file] [edit]
include(RunCMake)
# The policy only affects the MSVC compiler, which the test is only added for.
# Compilers older than Visual Studio 2017 (19.10) have no permissive flags.
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.10)
return()
endif()
# Configure and build a target with the given CMP0231 default, CXX_STANDARD
# and CXX_EXTENSIONS. The source is compiled for the mode that the compiler
# is expected to end up in, and fails to compile in the other one.
# <policy> OLD, NEW, or empty to leave the policy unset
# <std> CXX_STANDARD value, or empty for the compiler default
# <ext> CXX_EXTENSIONS value
# <mode> expected compiler mode: PERMISSIVE or NON_PERMISSIVE
# Extra arguments are passed to the configure step.
function(run_cmp0231 name policy std ext mode)
set(RunCMake_TEST_OPTIONS
-DCMP0231_POLICY=${policy}
-DCMP0231_STANDARD=${std}
-DCMP0231_EXTENSIONS=${ext}
-DCMP0231_EXPECT=${mode}
${ARGN})
if(policy)
list(APPEND RunCMake_TEST_OPTIONS -DCMAKE_POLICY_DEFAULT_CMP0231=${policy})
endif()
set(RunCMake_TEST_BINARY_DIR "${RunCMake_BINARY_DIR}/${name}-build")
run_cmake(${name})
set(RunCMake_TEST_NO_CLEAN 1)
run_cmake_command(${name}-build ${CMAKE_COMMAND} --build . --config Debug)
endfunction()
# Compiler default standard (C++14 for MSVC). CMP0128 leaves out its /std:
# flag, so /permissive- has to be added on its own.
if(CMAKE_CXX_STANDARD_DEFAULT)
run_cmp0231(CMP0231-NEW-ext-off-default "NEW" ${CMAKE_CXX_STANDARD_DEFAULT} OFF NON_PERMISSIVE)
endif()
# C++14 and C++17 stay permissive until /permissive- is passed.
# OLD and the unset (WARN) policy keep the default mode of the compiler.
run_cmp0231(CMP0231-OLD-ext-off-std14 "OLD" 14 OFF PERMISSIVE)
run_cmp0231(CMP0231-NEW-ext-off-std14 "NEW" 14 OFF NON_PERMISSIVE)
run_cmp0231(CMP0231-NEW-ext-on-std14 "NEW" 14 ON PERMISSIVE)
run_cmp0231(CMP0231-OLD-ext-off-std17 "OLD" 17 OFF PERMISSIVE)
run_cmp0231(CMP0231-WARN-ext-off-std17 "" 17 OFF PERMISSIVE)
run_cmp0231(CMP0231-NEW-ext-off-std17 "NEW" 17 OFF NON_PERMISSIVE)
run_cmp0231(CMP0231-NEW-ext-on-std17 "NEW" 17 ON PERMISSIVE)
# The policy is per target: a change after a target is created does not
# affect that target, only the ones created later.
run_cmp0231(CMP0231-per-target-NEW-then-OLD "NEW" 17 OFF NON_PERMISSIVE
-DCMP0231_LATE_POLICY=OLD -DCMP0231_LATE_EXPECT=PERMISSIVE)
run_cmp0231(CMP0231-per-target-OLD-then-NEW "OLD" 17 OFF PERMISSIVE
-DCMP0231_LATE_POLICY=NEW -DCMP0231_LATE_EXPECT=NON_PERMISSIVE)
# Visual Studio 2017 15.5 (19.12) is the first to have a C++20 option.
# /std:c++latest implies /permissive- since Visual Studio 2019 16.8 (19.28).
if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.12)
if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.28)
set(std20_default_mode NON_PERMISSIVE)
else()
set(std20_default_mode PERMISSIVE)
endif()
run_cmp0231(CMP0231-OLD-ext-on-std20 "OLD" 20 ON ${std20_default_mode})
run_cmp0231(CMP0231-NEW-ext-off-std20 "NEW" 20 OFF NON_PERMISSIVE)
run_cmp0231(CMP0231-NEW-ext-on-std20 "NEW" 20 ON PERMISSIVE)
endif()
# C++23 uses /std:c++latest, which implies /permissive-.
if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.29.30129)
run_cmp0231(CMP0231-OLD-ext-on-std23 "OLD" 23 ON NON_PERMISSIVE)
run_cmp0231(CMP0231-NEW-ext-off-std23 "NEW" 23 OFF NON_PERMISSIVE)
run_cmp0231(CMP0231-NEW-ext-on-std23 "NEW" 23 ON PERMISSIVE)
endif()