MSVC: Add abstraction for runtime checks
Replace our hard-coded default for `/RTC1` with a first-class abstraction to select runtime checks from an enumeration of logical names. Add a `MSVC_RUNTIME_CHECKS` target property and corresponding `CMAKE_MSVC_RUNTIME_CHECKS` variable. Removing the old default flag requires a policy because existing projects may rely on string processing to edit them and choose runtime checks under the old behavior. Add policy CMP0184 to provide compatibility. Fixes: #26614
This commit is contained in:
parent
49dcd1ce5d
commit
2b2344b412
@ -305,6 +305,7 @@ syn keyword cmakeProperty contained
|
||||
\ MEASUREMENT
|
||||
\ MODIFIED
|
||||
\ MSVC_DEBUG_INFORMATION_FORMAT
|
||||
\ MSVC_RUNTIME_CHECKS
|
||||
\ MSVC_RUNTIME_LIBRARY
|
||||
\ NAME
|
||||
\ NO_SONAME
|
||||
@ -1532,6 +1533,7 @@ syn keyword cmakeVariable contained
|
||||
\ CMAKE_MODULE_PATH
|
||||
\ CMAKE_MSVCIDE_RUN_PATH
|
||||
\ CMAKE_MSVC_DEBUG_INFORMATION_FORMAT
|
||||
\ CMAKE_MSVC_RUNTIME_CHECKS
|
||||
\ CMAKE_MSVC_RUNTIME_LIBRARY
|
||||
\ CMAKE_NETRC
|
||||
\ CMAKE_NETRC_FILE
|
||||
|
@ -349,6 +349,7 @@ as needed to honor the state of the calling project:
|
||||
* :policy:`CMP0155`
|
||||
* :policy:`CMP0157`
|
||||
* :policy:`CMP0181`
|
||||
* :policy:`CMP0184`
|
||||
|
||||
.. versionadded:: 4.0
|
||||
The current setting of :policy:`CMP0181` policy is propagated through to the
|
||||
@ -417,6 +418,11 @@ configuration:
|
||||
propagated into the test project's build configuration when using the
|
||||
:ref:`whole-project signature <Try Compiling Whole Projects>`.
|
||||
|
||||
.. versionadded:: 4.0
|
||||
If :policy:`CMP0184` is set to ``NEW``, one can use
|
||||
:variable:`CMAKE_MSVC_RUNTIME_CHECKS` to specify the enabled MSVC runtime
|
||||
checks.
|
||||
|
||||
See Also
|
||||
^^^^^^^^
|
||||
|
||||
|
@ -57,6 +57,7 @@ Policies Introduced by CMake 4.0
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
CMP0184: MSVC runtime checks flags are selected by an abstraction. </policy/CMP0184>
|
||||
CMP0183: add_feature_info() supports full Condition Syntax. </policy/CMP0183>
|
||||
CMP0182: Create shared library archives by default on AIX. </policy/CMP0182>
|
||||
CMP0181: Link command-line fragment variables are parsed and re-quoted. </policy/CMP0181>
|
||||
|
@ -359,6 +359,7 @@ Properties on Targets
|
||||
/prop_tgt/MANUALLY_ADDED_DEPENDENCIES
|
||||
/prop_tgt/MAP_IMPORTED_CONFIG_CONFIG
|
||||
/prop_tgt/MSVC_DEBUG_INFORMATION_FORMAT
|
||||
/prop_tgt/MSVC_RUNTIME_CHECKS
|
||||
/prop_tgt/MSVC_RUNTIME_LIBRARY
|
||||
/prop_tgt/NAME
|
||||
/prop_tgt/NO_SONAME
|
||||
|
@ -518,6 +518,7 @@ Variables that Control the Build
|
||||
/variable/CMAKE_MODULE_LINKER_FLAGS_CONFIG_INIT
|
||||
/variable/CMAKE_MODULE_LINKER_FLAGS_INIT
|
||||
/variable/CMAKE_MSVC_DEBUG_INFORMATION_FORMAT
|
||||
/variable/CMAKE_MSVC_RUNTIME_CHECKS
|
||||
/variable/CMAKE_MSVC_RUNTIME_LIBRARY
|
||||
/variable/CMAKE_MSVCIDE_RUN_PATH
|
||||
/variable/CMAKE_NINJA_OUTPUT_PATH_PREFIX
|
||||
|
54
Help/policy/CMP0184.rst
Normal file
54
Help/policy/CMP0184.rst
Normal file
@ -0,0 +1,54 @@
|
||||
CMP0184
|
||||
-------
|
||||
|
||||
.. versionadded:: 4.0
|
||||
|
||||
MSVC runtime checks flags are selected by an abstraction.
|
||||
|
||||
Compilers targeting the MSVC ABI have flags to select the runtime checks.
|
||||
Runtime checks selection typically varies with build
|
||||
configuration.
|
||||
|
||||
In CMake 3.31 and below, runtime checks flags are added to
|
||||
the default :variable:`CMAKE_<LANG>_FLAGS_<CONFIG>` cache entries by CMake
|
||||
automatically. This allows users to edit their cache entries to adjust the
|
||||
flags. However, the presence of such default flags is problematic for
|
||||
projects that want to choose different runtime checks programmatically.
|
||||
In particular, it requires string editing of the
|
||||
:variable:`CMAKE_<LANG>_FLAGS_<CONFIG>` variables with knowledge of the
|
||||
CMake builtin defaults so they can be replaced.
|
||||
|
||||
CMake 4.0 and above prefer to leave the runtime checks flags
|
||||
out of the default :variable:`CMAKE_<LANG>_FLAGS_<CONFIG>` values and instead
|
||||
offer a first-class abstraction. The
|
||||
:variable:`CMAKE_MSVC_RUNTIME_CHECKS` variable and
|
||||
:prop_tgt:`MSVC_RUNTIME_CHECKS` target property may be set to
|
||||
select the MSVC runtime checks. If they are not set, CMake
|
||||
enables runtime checks in ``Debug`` configuration using the default value
|
||||
``$<$<CONFIG:Debug>:StackFrameErrorCheck;UninitializedVariable>``, if
|
||||
supported by the compiler, or empty value otherwise.
|
||||
|
||||
This policy provides compatibility with projects that have not been updated
|
||||
to be aware of the abstraction. The policy setting takes effect as of the
|
||||
first :command:`project` or :command:`enable_language` command that enables
|
||||
a language whose compiler targets the MSVC ABI.
|
||||
|
||||
.. note::
|
||||
|
||||
Once the policy has taken effect at the top of a project, that choice
|
||||
will be used throughout the tree. In projects that have nested projects
|
||||
in subdirectories, be sure to confirm if everything is working with the
|
||||
selected policy behavior.
|
||||
|
||||
The ``OLD`` behavior for this policy is to place MSVC runtimes checks
|
||||
flags in the default :variable:`CMAKE_<LANG>_FLAGS_<CONFIG>` cache
|
||||
entries and ignore the :variable:`CMAKE_MSVC_RUNTIME_CHECKS`
|
||||
abstraction. The ``NEW`` behavior for this policy is to *not* place MSVC
|
||||
runtime checks flags in the default cache entries and use
|
||||
the abstraction instead.
|
||||
|
||||
.. |INTRODUCED_IN_CMAKE_VERSION| replace:: 4.0
|
||||
.. |WARNS_OR_DOES_NOT_WARN| replace:: does *not* warn
|
||||
.. include:: STANDARD_ADVICE.txt
|
||||
|
||||
.. include:: DEPRECATED.txt
|
16
Help/prop_tgt/MSVC_RUNTIME_CHECKS-VALUES.txt
Normal file
16
Help/prop_tgt/MSVC_RUNTIME_CHECKS-VALUES.txt
Normal file
@ -0,0 +1,16 @@
|
||||
``PossibleDataLoss``
|
||||
Compile with ``-RTCc`` or equivalent flag(s) to enable possible
|
||||
data loss checks.
|
||||
``StackFrameErrorCheck``
|
||||
Compile with ``-RTCs`` or equivalent flag(s) to enable stack frame
|
||||
error checks.
|
||||
``UninitializedVariable``
|
||||
Compile with ``-RTCu`` or equivalent flag(s) to enable uninitialized
|
||||
variables checks.
|
||||
|
||||
The value is ignored on compilers not targeting the MSVC ABI, but an
|
||||
unsupported value will be rejected as an error when using a compiler
|
||||
targeting the MSVC ABI.
|
||||
|
||||
The value may also be the empty string (``""``), in which case no runtime
|
||||
error check flags will be added explicitly by CMake.
|
34
Help/prop_tgt/MSVC_RUNTIME_CHECKS.rst
Normal file
34
Help/prop_tgt/MSVC_RUNTIME_CHECKS.rst
Normal file
@ -0,0 +1,34 @@
|
||||
MSVC_RUNTIME_CHECKS
|
||||
-------------------
|
||||
|
||||
.. versionadded:: 4.0
|
||||
|
||||
Select the list of enabled runtime checks when targeting the MSVC ABI.
|
||||
|
||||
The allowed values are:
|
||||
|
||||
.. include:: MSVC_RUNTIME_CHECKS-VALUES.txt
|
||||
|
||||
Use :manual:`generator expressions <cmake-generator-expressions(7)>` to
|
||||
support per-configuration specification. For example, the code:
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
add_executable(foo foo.c)
|
||||
set_property(TARGET foo PROPERTY
|
||||
MSVC_RUNTIME_CHECKS "$<$<CONFIG:Debug,RelWithDebInfo>:PossibleDataLoss;UninitializedVariable>")
|
||||
|
||||
enables for the target ``foo`` the possible data loss and uninitialized variables checks
|
||||
for the ``Debug`` and ``RelWithDebInfo`` configurations.
|
||||
|
||||
This property is initialized from the value of the
|
||||
:variable:`CMAKE_MSVC_RUNTIME_CHECKS` variable, if it is set.
|
||||
If this property is not set, CMake selects a runtime checks using
|
||||
the default value ``$<$<CONFIG:Debug>:StackFrameErrorCheck;UninitializedVariable>``, if
|
||||
supported by the compiler, or empty value otherwise.
|
||||
|
||||
.. note::
|
||||
|
||||
This property has effect only when policy :policy:`CMP0184` is set to ``NEW``
|
||||
prior to the first :command:`project` or :command:`enable_language` command
|
||||
that enables a language using a compiler targeting the MSVC ABI.
|
7
Help/release/dev/msvc-runtime-checks.rst
Normal file
7
Help/release/dev/msvc-runtime-checks.rst
Normal file
@ -0,0 +1,7 @@
|
||||
msvc-runtime-checks
|
||||
-------------------
|
||||
|
||||
* The :variable:`CMAKE_MSVC_RUNTIME_CHECKS` variable and
|
||||
:prop_tgt:`MSVC_RUNTIME_CHECKS` target property were introduced
|
||||
to select runtime checks for compilers targeting the MSVC ABI.
|
||||
See policy :policy:`CMP0184`.
|
36
Help/variable/CMAKE_MSVC_RUNTIME_CHECKS.rst
Normal file
36
Help/variable/CMAKE_MSVC_RUNTIME_CHECKS.rst
Normal file
@ -0,0 +1,36 @@
|
||||
CMAKE_MSVC_RUNTIME_CHECKS
|
||||
-------------------------
|
||||
|
||||
.. versionadded:: 4.0
|
||||
|
||||
Select the list of enabled runtime checks when targeting the MSVC ABI.
|
||||
This variable is used to initialize the
|
||||
:prop_tgt:`MSVC_RUNTIME_CHECKS` property on all targets as they are
|
||||
created. It is also propagated by calls to the :command:`try_compile` command
|
||||
into the test project.
|
||||
|
||||
The allowed values are:
|
||||
|
||||
.. include:: ../prop_tgt/MSVC_RUNTIME_CHECKS-VALUES.txt
|
||||
|
||||
Use :manual:`generator expressions <cmake-generator-expressions(7)>` to
|
||||
support per-configuration specification. For example, the code:
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
set(CMAKE_MSVC_RUNTIME_CHECKS "$<$<CONFIG:Debug,RelWithDebInfo>:PossibleDataLoss;UninitializedVariable>")
|
||||
|
||||
enables for the target ``foo`` the possible data loss and uninitialized variables checks
|
||||
for the ``Debug`` and ``RelWithDebInfo`` configurations.
|
||||
|
||||
If this variable is not set, the :prop_tgt:`MSVC_RUNTIME_CHECKS`
|
||||
target property will not be set automatically. If that property is not set,
|
||||
CMake selects runtime checks using the default value
|
||||
``$<$<CONFIG:Debug>:StackFrameErrorCheck;UninitializedVariable>``,
|
||||
if supported by the compiler, or empty value otherwise.
|
||||
|
||||
.. note::
|
||||
|
||||
This variable has effect only when policy :policy:`CMP0184` is set to ``NEW``
|
||||
prior to the first :command:`project` or :command:`enable_language` command
|
||||
that enables a language using a compiler targeting the MSVC ABI.
|
@ -11,12 +11,15 @@ set(CMAKE_ASM${ASM_DIALECT}_SOURCE_FILE_EXTENSIONS asm)
|
||||
set(CMAKE_ASM${ASM_DIALECT}_COMPILE_OBJECT "<CMAKE_ASM${ASM_DIALECT}_COMPILER> <INCLUDES> <FLAGS> -o <OBJECT> <SOURCE>")
|
||||
set(CMAKE_ASM${ASM_DIALECT}_CREATE_STATIC_LIBRARY "<CMAKE_AR> <LINK_FLAGS> /out:<TARGET> <OBJECTS> ")
|
||||
|
||||
# The ASM_MARMASM compiler id for this compiler is "MSVC", so fill out the runtime library table.
|
||||
# The ASM_MARMASM compiler id for this compiler is "MSVC", so fill out the abstraction tables.
|
||||
set(CMAKE_ASM${ASM_DIALECT}_COMPILE_OPTIONS_MSVC_RUNTIME_CHECKS_PossibleDataLoss "")
|
||||
set(CMAKE_ASM${ASM_DIALECT}_COMPILE_OPTIONS_MSVC_RUNTIME_CHECKS_StackFrameErrorCheck "")
|
||||
set(CMAKE_ASM${ASM_DIALECT}_COMPILE_OPTIONS_MSVC_RUNTIME_CHECKS_UninitializedVariable "")
|
||||
set(CMAKE_ASM${ASM_DIALECT}_COMPILE_OPTIONS_MSVC_RUNTIME_CHECKS_RTCsu "")
|
||||
set(CMAKE_ASM${ASM_DIALECT}_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreaded "")
|
||||
set(CMAKE_ASM${ASM_DIALECT}_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDLL "")
|
||||
set(CMAKE_ASM${ASM_DIALECT}_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebug "")
|
||||
set(CMAKE_ASM${ASM_DIALECT}_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebugDLL "")
|
||||
|
||||
set(CMAKE_ASM${ASM_DIALECT}_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_Embedded "-g")
|
||||
set(CMAKE_ASM${ASM_DIALECT}_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_ProgramDatabase "")
|
||||
set(CMAKE_ASM${ASM_DIALECT}_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_EditAndContinue "")
|
||||
|
@ -11,12 +11,15 @@ set(CMAKE_ASM${ASM_DIALECT}_SOURCE_FILE_EXTENSIONS asm)
|
||||
set(CMAKE_ASM${ASM_DIALECT}_COMPILE_OBJECT "<CMAKE_ASM${ASM_DIALECT}_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -c -Fo <OBJECT> <SOURCE>")
|
||||
set(CMAKE_ASM${ASM_DIALECT}_CREATE_STATIC_LIBRARY "<CMAKE_AR> <LINK_FLAGS> /out:<TARGET> <OBJECTS> ")
|
||||
|
||||
# The ASM_MASM compiler id for this compiler is "MSVC", so fill out the runtime library table.
|
||||
# The ASM_MASM compiler id for this compiler is "MSVC", so fill out the abstraction tables.
|
||||
set(CMAKE_ASM${ASM_DIALECT}_COMPILE_OPTIONS_MSVC_RUNTIME_CHECKS_PossibleDataLoss "")
|
||||
set(CMAKE_ASM${ASM_DIALECT}_COMPILE_OPTIONS_MSVC_RUNTIME_CHECKS_StackFrameErrorCheck "")
|
||||
set(CMAKE_ASM${ASM_DIALECT}_COMPILE_OPTIONS_MSVC_RUNTIME_CHECKS_UninitializedVariable "")
|
||||
set(CMAKE_ASM${ASM_DIALECT}_COMPILE_OPTIONS_MSVC_RUNTIME_CHECKS_RTCsu "")
|
||||
set(CMAKE_ASM${ASM_DIALECT}_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreaded "")
|
||||
set(CMAKE_ASM${ASM_DIALECT}_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDLL "")
|
||||
set(CMAKE_ASM${ASM_DIALECT}_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebug "")
|
||||
set(CMAKE_ASM${ASM_DIALECT}_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebugDLL "")
|
||||
|
||||
set(CMAKE_ASM${ASM_DIALECT}_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_Embedded "-Zi")
|
||||
set(CMAKE_ASM${ASM_DIALECT}_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_ProgramDatabase "")
|
||||
set(CMAKE_ASM${ASM_DIALECT}_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_EditAndContinue "")
|
||||
|
@ -1,6 +1,10 @@
|
||||
include(Platform/Windows-Clang)
|
||||
__windows_compiler_clang(ASM)
|
||||
|
||||
set(CMAKE_ASM_COMPILE_OPTIONS_MSVC_RUNTIME_CHECKS_PossibleDataLoss "")
|
||||
set(CMAKE_ASM_COMPILE_OPTIONS_MSVC_RUNTIME_CHECKS_StackFrameErrorCheck "")
|
||||
set(CMAKE_ASM_COMPILE_OPTIONS_MSVC_RUNTIME_CHECKS_UninitializedVariable "")
|
||||
set(CMAKE_ASM_COMPILE_OPTIONS_MSVC_RUNTIME_CHECKS_RTCsu "")
|
||||
set(CMAKE_ASM_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreaded "")
|
||||
set(CMAKE_ASM_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDLL "")
|
||||
set(CMAKE_ASM_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebug "")
|
||||
|
@ -115,6 +115,13 @@ macro(__windows_compiler_clang_gnu lang)
|
||||
string(APPEND CMAKE_${lang}_FLAGS_RELEASE_INIT " -O3 -DNDEBUG${_RTL_FLAGS}")
|
||||
string(APPEND CMAKE_${lang}_FLAGS_RELWITHDEBINFO_INIT " -O2 -DNDEBUG${_DBG_FLAGS}${_RTL_FLAGS}")
|
||||
|
||||
# clang-cl accepts -RTC* flags but ignores them. Simulate this
|
||||
# with the GNU-like drivers by simply passing no flags at all.
|
||||
set(CMAKE_${lang}_COMPILE_OPTIONS_MSVC_RUNTIME_CHECKS_PossibleDataLoss "")
|
||||
set(CMAKE_${lang}_COMPILE_OPTIONS_MSVC_RUNTIME_CHECKS_StackFrameErrorCheck "")
|
||||
set(CMAKE_${lang}_COMPILE_OPTIONS_MSVC_RUNTIME_CHECKS_UninitializedVariable "")
|
||||
set(CMAKE_${lang}_COMPILE_OPTIONS_MSVC_RUNTIME_CHECKS_RTCsu "")
|
||||
|
||||
set(CMAKE_${lang}_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_Embedded -g -Xclang -gcodeview)
|
||||
#set(CMAKE_${lang}_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_ProgramDatabase) # not supported by Clang
|
||||
#set(CMAKE_${lang}_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_EditAndContinue) # not supported by Clang
|
||||
@ -235,6 +242,14 @@ if("x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC"
|
||||
endif()
|
||||
unset(__WINDOWS_MSVC_CMP0141)
|
||||
|
||||
cmake_policy(GET CMP0184 __WINDOWS_MSVC_CMP0184)
|
||||
if(__WINDOWS_MSVC_CMP0184 STREQUAL "NEW")
|
||||
set(CMAKE_MSVC_RUNTIME_CHECKS_DEFAULT "$<$<CONFIG:Debug>:StackFrameErrorCheck;UninitializedVariable>")
|
||||
else()
|
||||
set(CMAKE_MSVC_RUNTIME_CHECKS_DEFAULT "")
|
||||
endif()
|
||||
unset(__WINDOWS_MSVC_CMP0184)
|
||||
|
||||
set(CMAKE_BUILD_TYPE_INIT Debug)
|
||||
|
||||
__enable_llvm_rc_preprocessing("" "-x c")
|
||||
|
@ -29,6 +29,12 @@ unset(_LIBSDLL)
|
||||
unset(_DBGLIBS)
|
||||
unset(_THREADS)
|
||||
|
||||
# icl accepts -RTC* flags but ignores them. ifort accepts -RTCu only.
|
||||
set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_CHECKS_PossibleDataLoss "")
|
||||
set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_CHECKS_StackFrameErrorCheck "")
|
||||
set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_CHECKS_UninitializedVariable -RTCu)
|
||||
set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_CHECKS_RTCsu "")
|
||||
|
||||
set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreaded -threads -libs:static)
|
||||
set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDLL -threads -libs:dll)
|
||||
set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebug -threads -libs:static -dbglibs)
|
||||
|
@ -29,6 +29,12 @@ unset(_LIBSDLL)
|
||||
unset(_DBGLIBS)
|
||||
unset(_THREADS)
|
||||
|
||||
# icx accepts -RTC* flags but ignores them. ifx accepts -RTCu only.
|
||||
set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_CHECKS_PossibleDataLoss "")
|
||||
set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_CHECKS_StackFrameErrorCheck "")
|
||||
set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_CHECKS_UninitializedVariable -RTCu)
|
||||
set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_CHECKS_RTCsu "")
|
||||
|
||||
set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreaded -threads -libs:static)
|
||||
set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDLL -threads -libs:dll)
|
||||
set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebug -threads -libs:static -dbglibs)
|
||||
|
@ -192,6 +192,9 @@ if(WINCE)
|
||||
set(_PLATFORM_DEFINES_CXX " /D${_MSVC_CXX_ARCHITECTURE_FAMILY} /D_${_MSVC_CXX_ARCHITECTURE_FAMILY_UPPER}_")
|
||||
|
||||
set(_RTC1 "")
|
||||
set(_RTCc "")
|
||||
set(_RTCs "")
|
||||
set(_RTCu "")
|
||||
set(_FLAGS_C "")
|
||||
set(_FLAGS_CXX "${_GR} /EHsc")
|
||||
|
||||
@ -248,17 +251,24 @@ else()
|
||||
if(CMAKE_VS_PLATFORM_TOOLSET MATCHES "v[0-9]+_clang_.*")
|
||||
# Clang/C2 in MSVC14 Update 1 seems to not support -fsantinize (yet?)
|
||||
# set(_RTC1 "-fsantinize=memory,safe-stack")
|
||||
# set(_RTCs "-fsantinize=safe-stack")
|
||||
# set(_RTCu "-fsantinize=memory")
|
||||
set(_FLAGS_CXX " -frtti -fexceptions")
|
||||
else()
|
||||
set(_RTC1 "/RTC1")
|
||||
set(_RTC1 "-RTC1")
|
||||
set(_RTCc "-RTCc")
|
||||
set(_RTCs "-RTCs")
|
||||
set(_RTCu "-RTCu")
|
||||
set(_FLAGS_CXX "${_GR} /EHsc")
|
||||
endif()
|
||||
set(CMAKE_C_STANDARD_LIBRARIES_INIT "kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib")
|
||||
else()
|
||||
set(_RTC1 "/GZ")
|
||||
set(_RTC1 "-GZ")
|
||||
set(_RTCs "-GZ")
|
||||
set(_FLAGS_CXX "${_GR} /GX")
|
||||
set(CMAKE_C_STANDARD_LIBRARIES_INIT "kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib")
|
||||
endif()
|
||||
set(_RTCsu "${_RTC1}")
|
||||
|
||||
if((_MSVC_C_ARCHITECTURE_FAMILY STREQUAL "ARM64EC") OR (_MSVC_CXX_ARCHITECTURE_FAMILY STREQUAL "ARM64EC"))
|
||||
string(APPEND CMAKE_C_STANDARD_LIBRARIES_INIT " softintrin.lib")
|
||||
@ -353,6 +363,13 @@ else()
|
||||
endif()
|
||||
unset(__WINDOWS_MSVC_CMP0141)
|
||||
|
||||
cmake_policy(GET CMP0184 __WINDOWS_MSVC_CMP0184)
|
||||
if(__WINDOWS_MSVC_CMP0184 STREQUAL "NEW")
|
||||
set(CMAKE_MSVC_RUNTIME_CHECKS_DEFAULT "$<$<CONFIG:Debug>:StackFrameErrorCheck;UninitializedVariable>")
|
||||
else()
|
||||
set(CMAKE_MSVC_RUNTIME_CHECKS_DEFAULT "")
|
||||
endif()
|
||||
unset(__WINDOWS_MSVC_CMP0184)
|
||||
|
||||
macro(__windows_compiler_msvc lang)
|
||||
if(NOT MSVC_VERSION LESS 1400)
|
||||
@ -467,17 +484,23 @@ macro(__windows_compiler_msvc lang)
|
||||
set(_Zi " /Zi")
|
||||
endif()
|
||||
|
||||
if(CMAKE_MSVC_RUNTIME_CHECKS_DEFAULT)
|
||||
set(_RTC1_local "")
|
||||
else()
|
||||
string(REPLACE " -" " /" _RTC1_local " ${_RTC1}")
|
||||
endif()
|
||||
|
||||
if(CMAKE_VS_PLATFORM_TOOLSET MATCHES "v[0-9]+_clang_.*")
|
||||
# note: MSVC 14 2015 Update 1 sets -fno-ms-compatibility by default, but this does not allow one to compile many projects
|
||||
# that include MS's own headers. CMake itself is affected project too.
|
||||
string(APPEND CMAKE_${lang}_FLAGS_INIT " ${_PLATFORM_DEFINES}${_PLATFORM_DEFINES_${lang}} -fms-extensions -fms-compatibility -D_WINDOWS${_Wall}${_FLAGS_${lang}}")
|
||||
string(APPEND CMAKE_${lang}_FLAGS_DEBUG_INIT "${_MDd} -gline-tables-only -fno-inline -O0 ${_RTC1}")
|
||||
string(APPEND CMAKE_${lang}_FLAGS_DEBUG_INIT "${_MDd} -gline-tables-only -fno-inline -O0${_RTC1_local}")
|
||||
string(APPEND CMAKE_${lang}_FLAGS_RELEASE_INIT "${_MD} -O2 -DNDEBUG")
|
||||
string(APPEND CMAKE_${lang}_FLAGS_RELWITHDEBINFO_INIT "${_MD} -gline-tables-only -O2 -fno-inline -DNDEBUG")
|
||||
string(APPEND CMAKE_${lang}_FLAGS_MINSIZEREL_INIT "${_MD} -DNDEBUG") # TODO: Add '-Os' once VS generator maps it properly for Clang
|
||||
else()
|
||||
string(APPEND CMAKE_${lang}_FLAGS_INIT " ${_PLATFORM_DEFINES}${_PLATFORM_DEFINES_${lang}} /D_WINDOWS${_W3}${_FLAGS_${lang}}")
|
||||
string(APPEND CMAKE_${lang}_FLAGS_DEBUG_INIT "${_MDd}${_Zi} /Ob0 /Od ${_RTC1}")
|
||||
string(APPEND CMAKE_${lang}_FLAGS_DEBUG_INIT "${_MDd}${_Zi} /Ob0 /Od${_RTC1_local}")
|
||||
string(APPEND CMAKE_${lang}_FLAGS_RELEASE_INIT "${_MD} /O2 /Ob2 /DNDEBUG")
|
||||
string(APPEND CMAKE_${lang}_FLAGS_RELWITHDEBINFO_INIT "${_MD}${_Zi} /O2 /Ob1 /DNDEBUG")
|
||||
string(APPEND CMAKE_${lang}_FLAGS_MINSIZEREL_INIT "${_MD} /O1 /Ob1 /DNDEBUG")
|
||||
@ -487,7 +510,12 @@ macro(__windows_compiler_msvc lang)
|
||||
unset(_MDd)
|
||||
unset(_MD)
|
||||
unset(_Zi)
|
||||
unset(_RTC1_local)
|
||||
|
||||
set(CMAKE_${lang}_COMPILE_OPTIONS_MSVC_RUNTIME_CHECKS_PossibleDataLoss "${_RTCc}")
|
||||
set(CMAKE_${lang}_COMPILE_OPTIONS_MSVC_RUNTIME_CHECKS_StackFrameErrorCheck "${_RTCs}")
|
||||
set(CMAKE_${lang}_COMPILE_OPTIONS_MSVC_RUNTIME_CHECKS_UninitializedVariable "${_RTCu}")
|
||||
set(CMAKE_${lang}_COMPILE_OPTIONS_MSVC_RUNTIME_CHECKS_RTCsu "${_RTCsu}")
|
||||
set(CMAKE_${lang}_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreaded -MT)
|
||||
set(CMAKE_${lang}_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDLL -MD)
|
||||
set(CMAKE_${lang}_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebug -MTd)
|
||||
|
@ -69,6 +69,12 @@ else()
|
||||
set(_Zi " -Zi")
|
||||
endif()
|
||||
|
||||
if(CMAKE_MSVC_RUNTIME_CHECKS_DEFAULT)
|
||||
set(_RTC1_local "")
|
||||
else()
|
||||
string(REPLACE " -" " /" _RTC1_local " ${_RTC1}")
|
||||
endif()
|
||||
|
||||
cmake_policy(GET CMP0092 _cmp0092)
|
||||
if(_cmp0092 STREQUAL "NEW")
|
||||
set(_W3 "")
|
||||
@ -78,7 +84,7 @@ endif()
|
||||
unset(_cmp0092)
|
||||
|
||||
string(APPEND CMAKE_CUDA_FLAGS_INIT " ${PLATFORM_DEFINES_CUDA} -D_WINDOWS -Xcompiler=\"${_W3}${_FLAGS_CXX}\"")
|
||||
string(APPEND CMAKE_CUDA_FLAGS_DEBUG_INIT " -Xcompiler=\"${_MDd}${_Zi} -Ob0 -Od ${_RTC1}\"")
|
||||
string(APPEND CMAKE_CUDA_FLAGS_DEBUG_INIT " -Xcompiler=\"${_MDd}${_Zi} -Ob0 -Od${_RTC1_local}\"")
|
||||
string(APPEND CMAKE_CUDA_FLAGS_RELEASE_INIT " -Xcompiler=\"${_MD}-O2 -Ob2\" -DNDEBUG")
|
||||
string(APPEND CMAKE_CUDA_FLAGS_RELWITHDEBINFO_INIT " -Xcompiler=\"${_MD}${_Zi} -O2 -Ob1\" -DNDEBUG")
|
||||
string(APPEND CMAKE_CUDA_FLAGS_MINSIZEREL_INIT " -Xcompiler=\"${_MD}-O1 -Ob1\" -DNDEBUG")
|
||||
@ -86,7 +92,12 @@ unset(_W3)
|
||||
unset(_Zi)
|
||||
unset(_MDd)
|
||||
unset(_MD)
|
||||
unset(_RTC1_local)
|
||||
|
||||
set(CMAKE_CUDA_COMPILE_OPTIONS_MSVC_RUNTIME_CHECKS_PossibleDataLoss "-Xcompiler=${_RTCc} -D_ALLOW_RTCc_IN_STL")
|
||||
set(CMAKE_CUDA_COMPILE_OPTIONS_MSVC_RUNTIME_CHECKS_StackFrameErrorCheck "-Xcompiler=${_RTCs}")
|
||||
set(CMAKE_CUDA_COMPILE_OPTIONS_MSVC_RUNTIME_CHECKS_UninitializedVariable "-Xcompiler=${_RTCu}")
|
||||
set(CMAKE_CUDA_COMPILE_OPTIONS_MSVC_RUNTIME_CHECKS_RTCsu "-Xcompiler=${_RTCsu}")
|
||||
set(CMAKE_CUDA_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreaded -Xcompiler=-MT)
|
||||
set(CMAKE_CUDA_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDLL -Xcompiler=-MD)
|
||||
set(CMAKE_CUDA_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebug -Xcompiler=-MTd)
|
||||
|
@ -110,6 +110,8 @@ std::string const kCMAKE_WATCOM_RUNTIME_LIBRARY_DEFAULT =
|
||||
"CMAKE_WATCOM_RUNTIME_LIBRARY_DEFAULT";
|
||||
std::string const kCMAKE_MSVC_DEBUG_INFORMATION_FORMAT_DEFAULT =
|
||||
"CMAKE_MSVC_DEBUG_INFORMATION_FORMAT_DEFAULT";
|
||||
std::string const kCMAKE_MSVC_RUNTIME_CHECKS_DEFAULT =
|
||||
"CMAKE_MSVC_RUNTIME_CHECKS_DEFAULT";
|
||||
|
||||
/* GHS Multi platform variables */
|
||||
std::set<std::string> const ghs_platform_vars{
|
||||
@ -683,6 +685,13 @@ cm::optional<cmTryCompileResult> cmCoreTryCompile::TryCompileCode(
|
||||
!msvcDebugInformationFormatDefault->empty() ? "NEW" : "OLD");
|
||||
}
|
||||
|
||||
/* Set MSVC runtime checks policy to match our selection. */
|
||||
if (cmValue msvcRuntimeChecksDefault =
|
||||
this->Makefile->GetDefinition(kCMAKE_MSVC_RUNTIME_CHECKS_DEFAULT)) {
|
||||
fprintf(fout, "cmake_policy(SET CMP0184 %s)\n",
|
||||
!msvcRuntimeChecksDefault->empty() ? "NEW" : "OLD");
|
||||
}
|
||||
|
||||
/* Set cache/normal variable policy to match outer project.
|
||||
It may affect toolchain files. */
|
||||
if (this->Makefile->GetPolicyStatus(cmPolicies::CMP0126) !=
|
||||
@ -1111,6 +1120,7 @@ cm::optional<cmTryCompileResult> cmCoreTryCompile::TryCompileCode(
|
||||
vars.emplace("CMAKE_MSVC_RUNTIME_LIBRARY"_s);
|
||||
vars.emplace("CMAKE_WATCOM_RUNTIME_LIBRARY"_s);
|
||||
vars.emplace("CMAKE_MSVC_DEBUG_INFORMATION_FORMAT"_s);
|
||||
vars.emplace("CMAKE_MSVC_RUNTIME_CHECKS"_s);
|
||||
vars.emplace("CMAKE_CXX_COMPILER_CLANG_SCAN_DEPS"_s);
|
||||
vars.emplace("CMAKE_VS_USE_DEBUG_LIBRARIES"_s);
|
||||
|
||||
|
@ -2193,10 +2193,7 @@ void cmLocalGenerator::AddLanguageFlags(std::string& flags,
|
||||
"CMAKE_" + lang + "_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_" +
|
||||
msvcRuntimeLibrary)) {
|
||||
this->AppendCompileOptions(flags, *msvcRuntimeLibraryOptions);
|
||||
} else if ((this->Makefile->GetSafeDefinition(
|
||||
"CMAKE_" + lang + "_COMPILER_ID") == "MSVC" ||
|
||||
this->Makefile->GetSafeDefinition(
|
||||
"CMAKE_" + lang + "_SIMULATE_ID") == "MSVC") &&
|
||||
} else if ((compiler == "MSVC" || compilerSimulateId == "MSVC") &&
|
||||
!cmSystemTools::GetErrorOccurredFlag()) {
|
||||
// The compiler uses the MSVC ABI so it needs a known runtime library.
|
||||
this->IssueMessage(MessageType::FATAL_ERROR,
|
||||
@ -2224,10 +2221,8 @@ void cmLocalGenerator::AddLanguageFlags(std::string& flags,
|
||||
"CMAKE_" + lang + "_COMPILE_OPTIONS_WATCOM_RUNTIME_LIBRARY_" +
|
||||
watcomRuntimeLibrary)) {
|
||||
this->AppendCompileOptions(flags, *watcomRuntimeLibraryOptions);
|
||||
} else if ((this->Makefile->GetSafeDefinition(
|
||||
"CMAKE_" + lang + "_COMPILER_ID") == "OpenWatcom" ||
|
||||
this->Makefile->GetSafeDefinition(
|
||||
"CMAKE_" + lang + "_SIMULATE_ID") == "OpenWatcom") &&
|
||||
} else if ((compiler == "OpenWatcom" ||
|
||||
compilerSimulateId == "OpenWatcom") &&
|
||||
!cmSystemTools::GetErrorOccurredFlag()) {
|
||||
// The compiler uses the Watcom ABI so it needs a known runtime
|
||||
// library.
|
||||
@ -2239,6 +2234,49 @@ void cmLocalGenerator::AddLanguageFlags(std::string& flags,
|
||||
}
|
||||
}
|
||||
|
||||
// Add MSVC runtime checks flags. This is activated by the presence
|
||||
// of a default selection whether or not it is overridden by a property.
|
||||
cmValue msvcRuntimeChecksDefault =
|
||||
this->Makefile->GetDefinition("CMAKE_MSVC_RUNTIME_CHECKS_DEFAULT");
|
||||
if (cmNonempty(msvcRuntimeChecksDefault)) {
|
||||
cmValue msvcRuntimeChecksValue =
|
||||
target->GetProperty("MSVC_RUNTIME_CHECKS");
|
||||
if (!msvcRuntimeChecksValue) {
|
||||
msvcRuntimeChecksValue = msvcRuntimeChecksDefault;
|
||||
}
|
||||
cmList msvcRuntimeChecksList = cmGeneratorExpression::Evaluate(
|
||||
*msvcRuntimeChecksValue, this, config, target);
|
||||
msvcRuntimeChecksList.remove_duplicates();
|
||||
|
||||
// RTC1/RTCsu VS GUI workaround
|
||||
std::string const stackFrameErrorCheck = "StackFrameErrorCheck";
|
||||
std::string const unitinitializedVariable = "UninitializedVariable";
|
||||
std::string const rtcSU = "RTCsu";
|
||||
if ((cm::contains(msvcRuntimeChecksList, stackFrameErrorCheck) &&
|
||||
cm::contains(msvcRuntimeChecksList, unitinitializedVariable)) ||
|
||||
cm::contains(msvcRuntimeChecksList, rtcSU)) {
|
||||
msvcRuntimeChecksList.remove_items(
|
||||
{ stackFrameErrorCheck, unitinitializedVariable, rtcSU });
|
||||
msvcRuntimeChecksList.append(rtcSU);
|
||||
}
|
||||
|
||||
for (std::string const& msvcRuntimeChecks : msvcRuntimeChecksList) {
|
||||
if (cmValue msvcRuntimeChecksOptions =
|
||||
this->Makefile->GetDefinition(cmStrCat(
|
||||
"CMAKE_", lang,
|
||||
"_COMPILE_OPTIONS_MSVC_RUNTIME_CHECKS_" + msvcRuntimeChecks))) {
|
||||
this->AppendCompileOptions(flags, *msvcRuntimeChecksOptions);
|
||||
} else if ((compiler == "MSVC" || compilerSimulateId == "MSVC") &&
|
||||
!cmSystemTools::GetErrorOccurredFlag()) {
|
||||
// The compiler uses the MSVC ABI so it needs a known runtime checks.
|
||||
this->IssueMessage(MessageType::FATAL_ERROR,
|
||||
cmStrCat("MSVC_RUNTIME_CHECKS value '",
|
||||
msvcRuntimeChecks, "' not known for this ",
|
||||
lang, " compiler."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add MSVC debug information format flags if CMP0141 is NEW.
|
||||
if (cm::optional<std::string> msvcDebugInformationFormat =
|
||||
this->GetMSVCDebugFormatName(config, target)) {
|
||||
@ -2249,10 +2287,7 @@ void cmLocalGenerator::AddLanguageFlags(std::string& flags,
|
||||
"_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_",
|
||||
*msvcDebugInformationFormat))) {
|
||||
this->AppendCompileOptions(flags, *msvcDebugInformationFormatOptions);
|
||||
} else if ((this->Makefile->GetSafeDefinition(
|
||||
cmStrCat("CMAKE_", lang, "_COMPILER_ID")) == "MSVC"_s ||
|
||||
this->Makefile->GetSafeDefinition(
|
||||
cmStrCat("CMAKE_", lang, "_SIMULATE_ID")) == "MSVC"_s) &&
|
||||
} else if ((compiler == "MSVC" || compilerSimulateId == "MSVC") &&
|
||||
!cmSystemTools::GetErrorOccurredFlag()) {
|
||||
// The compiler uses the MSVC ABI so it needs a known runtime library.
|
||||
this->IssueMessage(MessageType::FATAL_ERROR,
|
||||
|
@ -549,7 +549,10 @@ class cmMakefile;
|
||||
SELECT(POLICY, CMP0182, \
|
||||
"Create shared library archives by default on AIX.", 4, 0, 0, WARN) \
|
||||
SELECT(POLICY, CMP0183, \
|
||||
"add_feature_info() supports full Condition Syntax.", 4, 0, 0, WARN)
|
||||
"add_feature_info() supports full Condition Syntax.", 4, 0, 0, WARN) \
|
||||
SELECT(POLICY, CMP0184, \
|
||||
"MSVC runtime check flags are selected by an abstraction.", 4, 0, 0, \
|
||||
WARN)
|
||||
|
||||
#define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
|
||||
#define CM_FOR_EACH_POLICY_ID(POLICY) \
|
||||
|
@ -330,6 +330,7 @@ TargetProperty const StaticTargetProperties[] = {
|
||||
{ "OSX_ARCHITECTURES"_s, IC::CanCompileSources },
|
||||
// ---- Windows
|
||||
{ "MSVC_DEBUG_INFORMATION_FORMAT"_s, IC::CanCompileSources },
|
||||
{ "MSVC_RUNTIME_CHECKS"_s, IC::CanCompileSources },
|
||||
{ "MSVC_RUNTIME_LIBRARY"_s, IC::CanCompileSources },
|
||||
{ "VS_JUST_MY_CODE_DEBUGGING"_s, IC::CanCompileSources },
|
||||
{ "VS_DEBUGGER_COMMAND"_s, IC::ExecutableTarget },
|
||||
@ -1763,6 +1764,7 @@ void cmTarget::CopyImportedCxxModulesProperties(cmTarget const* tgt)
|
||||
"OSX_ARCHITECTURES",
|
||||
// ---- Windows
|
||||
"MSVC_DEBUG_INFORMATION_FORMAT",
|
||||
"MSVC_RUNTIME_CHECKS",
|
||||
"MSVC_RUNTIME_LIBRARY",
|
||||
"VS_PLATFORM_TOOLSET",
|
||||
// ---- OpenWatcom
|
||||
|
@ -2128,6 +2128,14 @@ if(BUILD_TESTING)
|
||||
set_property(TEST MSVCDebugInformationFormat APPEND
|
||||
PROPERTY LABELS "CUDA" "Fortran")
|
||||
|
||||
set(MSVCRuntimeChecks_BUILD_OPTIONS -DCMake_TEST_CUDA=${CMake_TEST_CUDA})
|
||||
if(CMAKE_Fortran_COMPILER)
|
||||
list(APPEND MSVCRuntimeChecks_BUILD_OPTIONS -DCMake_TEST_Fortran=1)
|
||||
endif()
|
||||
ADD_TEST_MACRO(MSVCRuntimeChecks)
|
||||
set_property(TEST MSVCRuntimeChecks APPEND
|
||||
PROPERTY LABELS "CUDA" "Fortran")
|
||||
|
||||
set(MSVCRuntimeLibrary_BUILD_OPTIONS -DCMake_TEST_CUDA=${CMake_TEST_CUDA})
|
||||
ADD_TEST_MACRO(MSVCRuntimeLibrary)
|
||||
set_property(TEST MSVCRuntimeLibrary APPEND
|
||||
|
@ -1,4 +1,5 @@
|
||||
cmake_minimum_required(VERSION 3.10...3.25) # Enable CMP0091 and CMP0141.
|
||||
cmake_policy(SET CMP0184 NEW)
|
||||
project(FortranOnly Fortran)
|
||||
message("CTEST_FULL_OUTPUT ")
|
||||
|
||||
|
105
Tests/MSVCRuntimeChecks/CMakeLists.txt
Normal file
105
Tests/MSVCRuntimeChecks/CMakeLists.txt
Normal file
@ -0,0 +1,105 @@
|
||||
cmake_minimum_required(VERSION 3.31)
|
||||
cmake_policy(SET CMP0184 NEW)
|
||||
|
||||
# All runtime checks flags enables single preprocessor definition,
|
||||
# so override our table of flags to artificially add a definition we can check.
|
||||
set(CMAKE_USER_MAKE_RULES_OVERRIDE_C ${CMAKE_CURRENT_SOURCE_DIR}/override-C.cmake)
|
||||
set(CMAKE_USER_MAKE_RULES_OVERRIDE_CXX ${CMAKE_CURRENT_SOURCE_DIR}/override-CXX.cmake)
|
||||
set(CMAKE_USER_MAKE_RULES_OVERRIDE_CUDA ${CMAKE_CURRENT_SOURCE_DIR}/override-CUDA.cmake)
|
||||
set(CMAKE_USER_MAKE_RULES_OVERRIDE_Fortran ${CMAKE_CURRENT_SOURCE_DIR}/override-Fortran.cmake)
|
||||
|
||||
project(MSVCRuntimeChecks)
|
||||
if(CMake_TEST_CUDA STREQUAL "NVIDIA")
|
||||
enable_language(CUDA)
|
||||
endif()
|
||||
if(CMake_TEST_Fortran)
|
||||
enable_language(Fortran)
|
||||
endif()
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
set(verify_default VERIFY_RTCsu)
|
||||
|
||||
set(verify_def_PossibleDataLoss -DVERIFY_RTCc)
|
||||
set(verify_def_StackFrameErrorCheck -DVERIFY_RTCs)
|
||||
set(verify_def_UninitializedVariable -DVERIFY_RTCu)
|
||||
set(verify_def_RTCsu -DVERIFY_RTCsu)
|
||||
|
||||
function(verify_combination format verify_format_defs lang src)
|
||||
# Test that try_compile builds with this runtime check.
|
||||
set(CMAKE_MSVC_RUNTIME_CHECKS "${format}")
|
||||
set(CMAKE_TRY_COMPILE_CONFIGURATION "Debug")
|
||||
set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY")
|
||||
|
||||
string(REPLACE ";" "_" format_var_name "${format}")
|
||||
if (NOT format_var_name)
|
||||
set(format_var_name "Empty")
|
||||
endif()
|
||||
|
||||
if (NOT verify_format_defs)
|
||||
foreach(format_for_def IN LISTS format)
|
||||
list(APPEND verify_format_defs ${verify_def_${format_for_def}})
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
try_compile(${format_var_name}_COMPILES
|
||||
${CMAKE_CURRENT_BINARY_DIR}/try_compile/${format_var_name}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/${src}
|
||||
COMPILE_DEFINITIONS ${verify_format_defs}
|
||||
CMAKE_FLAGS -DINCLUDE_DIRECTORIES=${CMAKE_CURRENT_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE ${format_var_name}_OUTPUT
|
||||
)
|
||||
if(${format_var_name}_COMPILES)
|
||||
message(STATUS "try_compile ${lang} with \"${format}\" worked")
|
||||
else()
|
||||
string(REPLACE "\n" "\n " ${format_var_name}_OUTPUT " ${${format_var_name}_OUTPUT}")
|
||||
message(SEND_ERROR "try_compile ${lang} with \"${format}\" failed:\n${${format_var_name}_OUTPUT}")
|
||||
endif()
|
||||
|
||||
# Test that targets build with this runtime check.
|
||||
set(CMAKE_MSVC_RUNTIME_CHECKS "$<$<BOOL:$<TARGET_PROPERTY:BOOL_TRUE>>:${format}>$<$<BOOL:$<TARGET_PROPERTY:BOOL_FALSE>>:BadContent>")
|
||||
add_library(${format_var_name}-${lang} ${src})
|
||||
set_property(TARGET ${format_var_name}-${lang} PROPERTY BOOL_TRUE TRUE)
|
||||
target_compile_definitions(${format_var_name}-${lang} PRIVATE ${verify_format_defs})
|
||||
endfunction()
|
||||
|
||||
function(verify lang src)
|
||||
add_library(default-${lang} ${src})
|
||||
target_compile_definitions(default-${lang} PRIVATE "$<$<CONFIG:Debug>:${verify_default}>")
|
||||
|
||||
# zero checkers
|
||||
verify_combination("" "" ${lang} ${src})
|
||||
|
||||
# single checker
|
||||
verify_combination(PossibleDataLoss "" ${lang} ${src})
|
||||
verify_combination(StackFrameErrorCheck "" ${lang} ${src})
|
||||
verify_combination(UninitializedVariable "" ${lang} ${src})
|
||||
verify_combination(RTCsu "" ${lang} ${src})
|
||||
|
||||
# multiple checkers (without RTCsu merging)
|
||||
verify_combination("PossibleDataLoss;StackFrameErrorCheck" "" ${lang} ${src})
|
||||
verify_combination("PossibleDataLoss;UninitializedVariable" "" ${lang} ${src})
|
||||
|
||||
# multiple checkers (only RTCsu merging)
|
||||
set(defs "${verify_def_RTCsu}")
|
||||
verify_combination("StackFrameErrorCheck;UninitializedVariable" "${defs}" ${lang} ${src})
|
||||
verify_combination("StackFrameErrorCheck;RTCsu" "${defs}" ${lang} ${src})
|
||||
verify_combination("UninitializedVariable;RTCsu" "${defs}" ${lang} ${src})
|
||||
verify_combination("StackFrameErrorCheck;UninitializedVariable;RTCsu" "${defs}" ${lang} ${src})
|
||||
|
||||
# multiple checkers (with RTCsu merging)
|
||||
list(APPEND defs "${verify_def_PossibleDataLoss}")
|
||||
verify_combination("PossibleDataLoss;StackFrameErrorCheck;UninitializedVariable" "${defs}" ${lang} ${src})
|
||||
verify_combination("PossibleDataLoss;StackFrameErrorCheck;RTCsu" "${defs}" ${lang} ${src})
|
||||
verify_combination("PossibleDataLoss;UninitializedVariable;RTCsu" "${defs}" ${lang} ${src})
|
||||
verify_combination("PossibleDataLoss;StackFrameErrorCheck;UninitializedVariable;RTCsu" "${defs}" ${lang} ${src})
|
||||
endfunction()
|
||||
|
||||
verify(C verify.c)
|
||||
verify(CXX verify.cxx)
|
||||
if(CMake_TEST_CUDA STREQUAL "NVIDIA")
|
||||
verify(CUDA verify.cu)
|
||||
endif()
|
||||
if(CMake_TEST_Fortran)
|
||||
verify(Fortran verify.F90)
|
||||
endif()
|
3
Tests/MSVCRuntimeChecks/override-C.cmake
Normal file
3
Tests/MSVCRuntimeChecks/override-C.cmake
Normal file
@ -0,0 +1,3 @@
|
||||
set(delimiter ";")
|
||||
set(lang "C")
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/override-common.cmake)
|
3
Tests/MSVCRuntimeChecks/override-CUDA.cmake
Normal file
3
Tests/MSVCRuntimeChecks/override-CUDA.cmake
Normal file
@ -0,0 +1,3 @@
|
||||
set(delimiter " ")
|
||||
set(lang "CUDA")
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/override-common.cmake)
|
3
Tests/MSVCRuntimeChecks/override-CXX.cmake
Normal file
3
Tests/MSVCRuntimeChecks/override-CXX.cmake
Normal file
@ -0,0 +1,3 @@
|
||||
set(delimiter ";")
|
||||
set(lang "CXX")
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/override-common.cmake)
|
3
Tests/MSVCRuntimeChecks/override-Fortran.cmake
Normal file
3
Tests/MSVCRuntimeChecks/override-Fortran.cmake
Normal file
@ -0,0 +1,3 @@
|
||||
set(delimiter ";")
|
||||
set(lang "Fortran")
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/override-common.cmake)
|
50
Tests/MSVCRuntimeChecks/override-common.cmake
Normal file
50
Tests/MSVCRuntimeChecks/override-common.cmake
Normal file
@ -0,0 +1,50 @@
|
||||
if("${CMAKE_${lang}_COMPILER_ID};${CMAKE_${lang}_SIMULATE_ID};${CMAKE_${lang}_COMPILER_FRONTEND_VARIANT}" STREQUAL "Clang;MSVC;GNU")
|
||||
# Clang does not actually support these, so Windows-Clang passes no flags.
|
||||
set(empty_PossibleDataLoss 1)
|
||||
set(empty_StackFrameErrorCheck 1)
|
||||
set(empty_UninitializedVariable 1)
|
||||
set(empty_RTCsu 1)
|
||||
elseif("${CMAKE_${lang}_COMPILER_ID};${CMAKE_${lang}_SIMULATE_ID};${lang}" MATCHES "^Intel(LLVM)?;MSVC;Fortran$")
|
||||
# IntelLLVM Fortran does not actually support these, so Windows-IntelLLVM-Fortran passes no flags.
|
||||
set(empty_PossibleDataLoss 1)
|
||||
set(empty_StackFrameErrorCheck 1)
|
||||
set(empty_UninitializedVariable 0) # this one is supported
|
||||
set(empty_RTCsu 1)
|
||||
elseif(CMAKE_${lang}_COMPILER_ID STREQUAL "MSVC" AND CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 14)
|
||||
set(empty_PossibleDataLoss 1)
|
||||
set(empty_StackFrameErrorCheck 0)
|
||||
set(empty_UninitializedVariable 1)
|
||||
set(empty_RTCsu 0)
|
||||
else()
|
||||
set(empty_PossibleDataLoss 0)
|
||||
set(empty_StackFrameErrorCheck 0)
|
||||
set(empty_UninitializedVariable 0)
|
||||
set(empty_RTCsu 0)
|
||||
endif()
|
||||
|
||||
set(var "CMAKE_${lang}_COMPILE_OPTIONS_MSVC_RUNTIME_CHECKS_PossibleDataLoss")
|
||||
if(empty_PossibleDataLoss AND ${var} STREQUAL "")
|
||||
set("${var}" "-DTEST_RTCc")
|
||||
else()
|
||||
string(REPLACE "-RTCc" "-RTCc${delimiter}-DTEST_RTCc" "${var}" "${${var}}")
|
||||
endif()
|
||||
set(var "CMAKE_${lang}_COMPILE_OPTIONS_MSVC_RUNTIME_CHECKS_StackFrameErrorCheck")
|
||||
if(empty_StackFrameErrorCheck AND ${var} STREQUAL "")
|
||||
set("${var}" "-DTEST_RTCs")
|
||||
else()
|
||||
string(REPLACE "-RTCs" "-RTCs${delimiter}-DTEST_RTCs" "${var}" "${${var}}")
|
||||
string(REPLACE "-GZ" "-GZ${delimiter}-DTEST_RTCs" "${var}" "${${var}}")
|
||||
endif()
|
||||
set(var "CMAKE_${lang}_COMPILE_OPTIONS_MSVC_RUNTIME_CHECKS_UninitializedVariable")
|
||||
if(empty_UninitializedVariable AND ${var} STREQUAL "")
|
||||
set("${var}" "-DTEST_RTCu")
|
||||
else()
|
||||
string(REPLACE "-RTCu" "-RTCu${delimiter}-DTEST_RTCu" "${var}" "${${var}}")
|
||||
endif()
|
||||
set(var "CMAKE_${lang}_COMPILE_OPTIONS_MSVC_RUNTIME_CHECKS_RTCsu")
|
||||
if(empty_RTCsu AND ${var} STREQUAL "")
|
||||
set("${var}" "-DTEST_RTCsu")
|
||||
else()
|
||||
string(REPLACE "-RTC1" "-RTC1${delimiter}-DTEST_RTCsu" "${var}" "${${var}}")
|
||||
string(REPLACE "-GZ" "-GZ${delimiter}-DTEST_RTCsu" "${var}" "${${var}}")
|
||||
endif()
|
1
Tests/MSVCRuntimeChecks/verify.F90
Normal file
1
Tests/MSVCRuntimeChecks/verify.F90
Normal file
@ -0,0 +1 @@
|
||||
#include "verify.h"
|
1
Tests/MSVCRuntimeChecks/verify.c
Normal file
1
Tests/MSVCRuntimeChecks/verify.c
Normal file
@ -0,0 +1 @@
|
||||
#include "verify.h"
|
1
Tests/MSVCRuntimeChecks/verify.cu
Normal file
1
Tests/MSVCRuntimeChecks/verify.cu
Normal file
@ -0,0 +1 @@
|
||||
#include "verify.h"
|
1
Tests/MSVCRuntimeChecks/verify.cxx
Normal file
1
Tests/MSVCRuntimeChecks/verify.cxx
Normal file
@ -0,0 +1 @@
|
||||
#include "verify.h"
|
61
Tests/MSVCRuntimeChecks/verify.h
Normal file
61
Tests/MSVCRuntimeChecks/verify.h
Normal file
@ -0,0 +1,61 @@
|
||||
/* Some compilers ignore the -RTC flags even if specified. */
|
||||
#if (defined(_MSC_VER) && _MSC_VER <= 1310) || defined(__clang__) || \
|
||||
defined(__INTEL_LLVM_COMPILER) || defined(__INTEL_COMPILER)
|
||||
# define NO__MSVC_RUNTIME_CHECKS
|
||||
#endif
|
||||
|
||||
#ifdef VERIFY_RTCc
|
||||
# ifndef TEST_RTCc
|
||||
# error "TEST_RTCc incorrectly not defined by enabled runtime check"
|
||||
# endif
|
||||
# if !defined(__MSVC_RUNTIME_CHECKS) && !defined(NO__MSVC_RUNTIME_CHECKS)
|
||||
# error \
|
||||
"__MSVC_RUNTIME_CHECKS incorrectly not defined by enabled RTCc runtime check"
|
||||
# endif
|
||||
#else
|
||||
# ifdef TEST_RTCc
|
||||
# error "TEST_RTCc incorrectly defined by disabled runtime check"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef VERIFY_RTCs
|
||||
# ifndef TEST_RTCs
|
||||
# error "TEST_RTCs incorrectly not defined by enabled runtime check"
|
||||
# endif
|
||||
# if !defined(__MSVC_RUNTIME_CHECKS) && !defined(NO__MSVC_RUNTIME_CHECKS)
|
||||
# error \
|
||||
"__MSVC_RUNTIME_CHECKS incorrectly not defined by enabled RTCs runtime check"
|
||||
# endif
|
||||
#else
|
||||
# ifdef TEST_RTCs
|
||||
# error "TEST_RTCs incorrectly defined by disabled runtime check"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef VERIFY_RTCu
|
||||
# ifndef TEST_RTCu
|
||||
# error "TEST_RTCu incorrectly not defined by enabled runtime check"
|
||||
# endif
|
||||
# if !defined(__MSVC_RUNTIME_CHECKS) && !defined(NO__MSVC_RUNTIME_CHECKS)
|
||||
# error \
|
||||
"__MSVC_RUNTIME_CHECKS incorrectly not defined by enabled RTCu runtime check"
|
||||
# endif
|
||||
#else
|
||||
# ifdef TEST_RTCu
|
||||
# error "TEST_RTCu incorrectly defined by disabled runtime check"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef VERIFY_RTCsu
|
||||
# ifndef TEST_RTCsu
|
||||
# error "TEST_RTCsu incorrectly not defined by enabled runtime check"
|
||||
# endif
|
||||
# if !defined(__MSVC_RUNTIME_CHECKS) && !defined(NO__MSVC_RUNTIME_CHECKS)
|
||||
# error \
|
||||
"__MSVC_RUNTIME_CHECKS incorrectly not defined by enabled RTCsu runtime check"
|
||||
# endif
|
||||
#else
|
||||
# ifdef TEST_RTCsu
|
||||
# error "TEST_RTCsu incorrectly defined by disabled runtime check"
|
||||
# endif
|
||||
#endif
|
@ -483,6 +483,7 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "^(Cray|PGI|NVHPC|XL|XLClang|IBMClang|Fujitsu|F
|
||||
add_RunCMake_test(MetaCompileFeatures)
|
||||
endif()
|
||||
if(MSVC)
|
||||
add_RunCMake_test(MSVCRuntimeChecks)
|
||||
add_RunCMake_test(MSVCRuntimeLibrary)
|
||||
add_RunCMake_test(MSVCRuntimeTypeInfo)
|
||||
add_RunCMake_test(MSVCWarningFlags)
|
||||
|
1
Tests/RunCMake/MSVCRuntimeChecks/CMP0184-NEW-result.txt
Normal file
1
Tests/RunCMake/MSVCRuntimeChecks/CMP0184-NEW-result.txt
Normal file
@ -0,0 +1 @@
|
||||
1
|
4
Tests/RunCMake/MSVCRuntimeChecks/CMP0184-NEW-stderr.txt
Normal file
4
Tests/RunCMake/MSVCRuntimeChecks/CMP0184-NEW-stderr.txt
Normal file
@ -0,0 +1,4 @@
|
||||
^CMake Error in CMakeLists.txt:
|
||||
MSVC_RUNTIME_CHECKS value 'BogusValue' not known for this C compiler.
|
||||
+
|
||||
CMake Generate step failed\. Build files cannot be regenerated correctly\.$
|
2
Tests/RunCMake/MSVCRuntimeChecks/CMP0184-NEW.cmake
Normal file
2
Tests/RunCMake/MSVCRuntimeChecks/CMP0184-NEW.cmake
Normal file
@ -0,0 +1,2 @@
|
||||
cmake_policy(SET CMP0184 NEW)
|
||||
include(CMP0184-common.cmake)
|
4
Tests/RunCMake/MSVCRuntimeChecks/CMP0184-NoEffect.cmake
Normal file
4
Tests/RunCMake/MSVCRuntimeChecks/CMP0184-NoEffect.cmake
Normal file
@ -0,0 +1,4 @@
|
||||
include(CMP0184-common.cmake)
|
||||
|
||||
# Setting this policy after enable_language command has no effect.
|
||||
cmake_policy(SET CMP0184 NEW)
|
2
Tests/RunCMake/MSVCRuntimeChecks/CMP0184-OLD.cmake
Normal file
2
Tests/RunCMake/MSVCRuntimeChecks/CMP0184-OLD.cmake
Normal file
@ -0,0 +1,2 @@
|
||||
cmake_policy(SET CMP0184 OLD)
|
||||
include(CMP0184-common.cmake)
|
2
Tests/RunCMake/MSVCRuntimeChecks/CMP0184-WARN.cmake
Normal file
2
Tests/RunCMake/MSVCRuntimeChecks/CMP0184-WARN.cmake
Normal file
@ -0,0 +1,2 @@
|
||||
|
||||
include(CMP0184-common.cmake)
|
25
Tests/RunCMake/MSVCRuntimeChecks/CMP0184-common.cmake
Normal file
25
Tests/RunCMake/MSVCRuntimeChecks/CMP0184-common.cmake
Normal file
@ -0,0 +1,25 @@
|
||||
enable_language(C)
|
||||
|
||||
cmake_policy(GET CMP0184 cmp0184)
|
||||
if(cmp0184 STREQUAL "NEW")
|
||||
if(NOT CMAKE_MSVC_RUNTIME_CHECKS_DEFAULT)
|
||||
message(SEND_ERROR "CMAKE_MSVC_RUNTIME_CHECKS_DEFAULT not set under NEW behavior")
|
||||
endif()
|
||||
else()
|
||||
if(CMAKE_MSVC_RUNTIME_CHECKS_DEFAULT)
|
||||
message(SEND_ERROR "CMAKE_MSVC_RUNTIME_CHECKS_DEFAULT is set under OLD behavior")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(cmp0184 STREQUAL "NEW")
|
||||
if(CMAKE_C_FLAGS_DEBUG MATCHES "[/-](RTC1|GZ)( |$)")
|
||||
message(SEND_ERROR "CMAKE_C_FLAGS_DEBUG has -RTC1 flag under NEW behavior:\n ${CMAKE_C_FLAGS_DEBUG}")
|
||||
endif()
|
||||
else()
|
||||
if(NOT (CMAKE_C_FLAGS_DEBUG MATCHES "/(RTC1|GZ)( |$)"))
|
||||
message(SEND_ERROR "CMAKE_C_FLAGS_DEBUG does not have /RTC1 flag under OLD behavior:\n ${CMAKE_C_FLAGS_DEBUG}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(CMAKE_MSVC_RUNTIME_CHECKS BogusValue)
|
||||
add_library(foo empty.c)
|
3
Tests/RunCMake/MSVCRuntimeChecks/CMakeLists.txt
Normal file
3
Tests/RunCMake/MSVCRuntimeChecks/CMakeLists.txt
Normal file
@ -0,0 +1,3 @@
|
||||
cmake_minimum_required(VERSION 3.31)
|
||||
project(${RunCMake_TEST} NONE)
|
||||
include(${RunCMake_TEST}.cmake)
|
6
Tests/RunCMake/MSVCRuntimeChecks/RunCMakeTest.cmake
Normal file
6
Tests/RunCMake/MSVCRuntimeChecks/RunCMakeTest.cmake
Normal file
@ -0,0 +1,6 @@
|
||||
include(RunCMake)
|
||||
|
||||
run_cmake(CMP0184-WARN)
|
||||
run_cmake(CMP0184-OLD)
|
||||
run_cmake(CMP0184-NEW)
|
||||
run_cmake(CMP0184-NoEffect)
|
0
Tests/RunCMake/MSVCRuntimeChecks/empty.c
Normal file
0
Tests/RunCMake/MSVCRuntimeChecks/empty.c
Normal file
@ -1,4 +1,5 @@
|
||||
cmake_minimum_required(VERSION 3.25) # Enable CMP0141
|
||||
cmake_policy(SET CMP0184 NEW)
|
||||
project(VSMARMASM C ASM_MARMASM)
|
||||
add_executable(VSMARMASM main.c foo.asm)
|
||||
target_compile_options(VSMARMASM PRIVATE
|
||||
|
@ -1,4 +1,5 @@
|
||||
cmake_minimum_required(VERSION 3.25) # Enable CMP0141
|
||||
cmake_policy(SET CMP0184 NEW)
|
||||
project(VSMASM C ASM_MASM)
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
add_definitions(-DTESTx64)
|
||||
|
Loading…
Reference in New Issue
Block a user