mirror of
https://github.com/reactos/CMake.git
synced 2024-11-24 20:19:53 +00:00
MSVC: Add abstraction for runtime library selection
Replace our hard-coded defaults for `/MD` and `/MDd` with a first-class abstraction to select the runtime library from an enumeration of logical names. We've long hesitated to do this because the idea of "runtime library selection" touches on related concepts on several platforms. Avoid that scope creep by simply defining an abstraction that applies only when targeting the MSVC ABI on Windows. Removing the old default flags requires a policy because existing projects may rely on string processing to edit them and choose a runtime library under the old behavior. Add policy CMP0091 to provide compatibility. Fixes: #19108
This commit is contained in:
parent
f621e7fa5d
commit
fb3370b6a1
@ -135,6 +135,7 @@ default values:
|
||||
* :variable:`CMAKE_ENABLE_EXPORTS`
|
||||
* :variable:`CMAKE_LINK_SEARCH_START_STATIC`
|
||||
* :variable:`CMAKE_LINK_SEARCH_END_STATIC`
|
||||
* :variable:`CMAKE_MSVC_RUNTIME_LIBRARY`
|
||||
* :variable:`CMAKE_POSITION_INDEPENDENT_CODE`
|
||||
|
||||
If :policy:`CMP0056` is set to ``NEW``, then
|
||||
|
@ -57,6 +57,7 @@ Policies Introduced by CMake 3.15
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
CMP0091: MSVC runtime library flags are selected by an abstraction. </policy/CMP0091>
|
||||
CMP0090: export(PACKAGE) does not populate package registry by default. </policy/CMP0090>
|
||||
CMP0089: Compiler id for IBM Clang-based XL compilers is now XLClang. </policy/CMP0089>
|
||||
|
||||
|
@ -280,6 +280,7 @@ Properties on Targets
|
||||
/prop_tgt/MACOSX_RPATH
|
||||
/prop_tgt/MANUALLY_ADDED_DEPENDENCIES
|
||||
/prop_tgt/MAP_IMPORTED_CONFIG_CONFIG
|
||||
/prop_tgt/MSVC_RUNTIME_LIBRARY
|
||||
/prop_tgt/NAME
|
||||
/prop_tgt/NO_SONAME
|
||||
/prop_tgt/NO_SYSTEM_FROM_IMPORTED
|
||||
|
@ -386,6 +386,7 @@ Variables that Control the Build
|
||||
/variable/CMAKE_MODULE_LINKER_FLAGS_CONFIG_INIT
|
||||
/variable/CMAKE_MODULE_LINKER_FLAGS_INIT
|
||||
/variable/CMAKE_MSVCIDE_RUN_PATH
|
||||
/variable/CMAKE_MSVC_RUNTIME_LIBRARY
|
||||
/variable/CMAKE_NINJA_OUTPUT_PATH_PREFIX
|
||||
/variable/CMAKE_NO_BUILTIN_CHRPATH
|
||||
/variable/CMAKE_NO_SYSTEM_FROM_IMPORTED
|
||||
|
47
Help/policy/CMP0091.rst
Normal file
47
Help/policy/CMP0091.rst
Normal file
@ -0,0 +1,47 @@
|
||||
CMP0091
|
||||
-------
|
||||
|
||||
MSVC runtime library flags are selected by an abstraction.
|
||||
|
||||
Compilers targeting the MSVC ABI have flags to select the MSVC runtime library.
|
||||
Runtime library selection typically varies with build configuration because
|
||||
there is a separate runtime library for Debug builds.
|
||||
|
||||
In CMake 3.14 and below, MSVC runtime library selection 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 a different runtime library 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 3.15 and above prefer to leave the MSVC runtime library selection flags
|
||||
out of the default :variable:`CMAKE_<LANG>_FLAGS_<CONFIG>` values and instead
|
||||
offer a first-class abstraction. The :variable:`CMAKE_MSVC_RUNTIME_LIBRARY`
|
||||
variable and :prop_tgt:`MSVC_RUNTIME_LIBRARY` target property may be set to
|
||||
select the MSVC runtime library.
|
||||
|
||||
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
|
||||
must be used throughout the tree. In projects that have nested projects
|
||||
in subdirectories, be sure to convert everything together.
|
||||
|
||||
The ``OLD`` behavior for this policy is to place MSVC runtime library
|
||||
flags in the default :variable:`CMAKE_<LANG>_FLAGS_<CONFIG>` cache
|
||||
entries and ignore the :variable:`CMAKE_MSVC_RUNTIME_LIBRARY` abstraction.
|
||||
The ``NEW`` behavior for this policy is to *not* place MSVC runtime
|
||||
library flags in the default cache entries and use the abstraction instead.
|
||||
|
||||
This policy was introduced in CMake version 3.15. Use the
|
||||
:command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` explicitly.
|
||||
Unlike many policies, CMake version |release| does *not* warn
|
||||
when this policy is not set and simply uses ``OLD`` behavior.
|
||||
|
||||
.. include:: DEPRECATED.txt
|
15
Help/prop_tgt/MSVC_RUNTIME_LIBRARY-VALUES.txt
Normal file
15
Help/prop_tgt/MSVC_RUNTIME_LIBRARY-VALUES.txt
Normal file
@ -0,0 +1,15 @@
|
||||
``MultiThreaded``
|
||||
Compile with ``-MT`` or equivalent flag(s) to use a multi-threaded
|
||||
statically-linked runtime library.
|
||||
``MultiThreadedDLL``
|
||||
Compile with ``-MD`` or equivalent flag(s) to use a multi-threaded
|
||||
dynamically-linked runtime library.
|
||||
``MultiThreadedDebug``
|
||||
Compile with ``-MTd`` or equivalent flag(s) to use a multi-threaded
|
||||
statically-linked runtime library.
|
||||
``MultiThreadedDebugDLL``
|
||||
Compile with ``-MDd`` or equivalent flag(s) to use a multi-threaded
|
||||
dynamically-linked runtime library.
|
||||
|
||||
The value is ignored on non-MSVC compilers but an unsupported value will
|
||||
be rejected as an error when using a compiler targeting the MSVC ABI.
|
26
Help/prop_tgt/MSVC_RUNTIME_LIBRARY.rst
Normal file
26
Help/prop_tgt/MSVC_RUNTIME_LIBRARY.rst
Normal file
@ -0,0 +1,26 @@
|
||||
MSVC_RUNTIME_LIBRARY
|
||||
--------------------
|
||||
|
||||
Select the MSVC runtime library for use by compilers targeting the MSVC ABI.
|
||||
|
||||
The allowed values are:
|
||||
|
||||
.. include:: MSVC_RUNTIME_LIBRARY-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_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
||||
|
||||
selects for the target ``foo`` a multi-threaded statically-linked runtime
|
||||
library with or without debug information depending on the configuration.
|
||||
|
||||
.. note::
|
||||
|
||||
This property has effect only when policy :policy:`CMP0091` 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-library.rst
Normal file
7
Help/release/dev/msvc-runtime-library.rst
Normal file
@ -0,0 +1,7 @@
|
||||
msvc-runtime-library
|
||||
--------------------
|
||||
|
||||
* The :variable:`CMAKE_MSVC_RUNTIME_LIBRARY` variable and
|
||||
:prop_tgt:`MSVC_RUNTIME_LIBRARY` target property were introduced to
|
||||
select the runtime library used by compilers targeting the MSVC ABI.
|
||||
See policy :policy:`CMP0091`.
|
27
Help/variable/CMAKE_MSVC_RUNTIME_LIBRARY.rst
Normal file
27
Help/variable/CMAKE_MSVC_RUNTIME_LIBRARY.rst
Normal file
@ -0,0 +1,27 @@
|
||||
CMAKE_MSVC_RUNTIME_LIBRARY
|
||||
--------------------------
|
||||
|
||||
Select the MSVC runtime library for use by compilers targeting the MSVC ABI.
|
||||
This variable is used to initialize the :prop_tgt:`MSVC_RUNTIME_LIBRARY`
|
||||
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_LIBRARY-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_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
||||
|
||||
selects for all following targets a multi-threaded statically-linked runtime
|
||||
library with or without debug information depending on the configuration.
|
||||
|
||||
.. note::
|
||||
|
||||
This variable has effect only when policy :policy:`CMP0091` 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.
|
@ -4,8 +4,34 @@ set(_COMPILE_Fortran " /fpp")
|
||||
set(CMAKE_Fortran_MODDIR_FLAG "-module:")
|
||||
set(CMAKE_Fortran_STANDARD_LIBRARIES_INIT "user32.lib")
|
||||
__windows_compiler_intel(Fortran)
|
||||
string(APPEND CMAKE_Fortran_FLAGS_INIT " /W1 /nologo /fpp /libs:dll /threads")
|
||||
string(APPEND CMAKE_Fortran_FLAGS_DEBUG_INIT " /Od /debug:full /dbglibs")
|
||||
if(CMAKE_MSVC_RUNTIME_LIBRARY_DEFAULT)
|
||||
set(_LIBSDLL "")
|
||||
set(_DBGLIBS "")
|
||||
set(_THREADS "")
|
||||
else()
|
||||
set(_LIBSDLL " /libs:dll")
|
||||
set(_DBGLIBS " /dbglibs")
|
||||
set(_THREADS " /threads")
|
||||
endif()
|
||||
string(APPEND CMAKE_Fortran_FLAGS_INIT " /W1 /nologo /fpp${_LIBSDLL}${_THREADS}")
|
||||
string(APPEND CMAKE_Fortran_FLAGS_DEBUG_INIT " /Od /debug:full${_DBGLIBS}")
|
||||
string(APPEND CMAKE_Fortran_FLAGS_MINSIZEREL_INIT " /O1 /DNDEBUG")
|
||||
string(APPEND CMAKE_Fortran_FLAGS_RELEASE_INIT " /O2 /DNDEBUG")
|
||||
string(APPEND CMAKE_Fortran_FLAGS_RELWITHDEBINFO_INIT " /O2 /debug:full /DNDEBUG")
|
||||
unset(_LIBSDLL)
|
||||
unset(_DBGLIBS)
|
||||
unset(_THREADS)
|
||||
|
||||
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)
|
||||
set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebugDLL -threads -libs:dll -dbglibs)
|
||||
|
||||
# Intel Fortran for Windows supports single-threaded RTL but it is
|
||||
# not implemented by the Visual Studio integration.
|
||||
if(NOT CMAKE_GENERATOR MATCHES "Visual Studio")
|
||||
set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_SingleThreaded -libs:static)
|
||||
set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_SingleThreadedDLL -libs:dll)
|
||||
set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_SingleThreadedDebug -libs:static -dbglibs)
|
||||
set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_SingleThreadedDebugDLL -libs:dll -dbglibs)
|
||||
endif()
|
||||
|
@ -298,6 +298,14 @@ endforeach()
|
||||
string(APPEND CMAKE_STATIC_LINKER_FLAGS_INIT " ${_MACHINE_ARCH_FLAG}")
|
||||
unset(_MACHINE_ARCH_FLAG)
|
||||
|
||||
cmake_policy(GET CMP0091 __WINDOWS_MSVC_CMP0091)
|
||||
if(__WINDOWS_MSVC_CMP0091 STREQUAL "NEW")
|
||||
set(CMAKE_MSVC_RUNTIME_LIBRARY_DEFAULT "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL")
|
||||
else()
|
||||
set(CMAKE_MSVC_RUNTIME_LIBRARY_DEFAULT "")
|
||||
endif()
|
||||
unset(__WINDOWS_MSVC_CMP0091)
|
||||
|
||||
macro(__windows_compiler_msvc lang)
|
||||
if(NOT MSVC_VERSION LESS 1400)
|
||||
# for 2005 make sure the manifest is put in the dll with mt
|
||||
@ -351,21 +359,35 @@ macro(__windows_compiler_msvc lang)
|
||||
|
||||
if("x${lang}" STREQUAL "xC" OR
|
||||
"x${lang}" STREQUAL "xCXX")
|
||||
if(CMAKE_MSVC_RUNTIME_LIBRARY_DEFAULT)
|
||||
set(_MDd "")
|
||||
set(_MD "")
|
||||
else()
|
||||
set(_MDd " /MDd")
|
||||
set(_MD " /MD")
|
||||
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_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
|
||||
string(APPEND CMAKE_${lang}_FLAGS_DEBUG_INIT "${_MDd} -gline-tables-only -fno-inline -O0 ${_RTC1}")
|
||||
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_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")
|
||||
string(APPEND CMAKE_${lang}_FLAGS_DEBUG_INIT "${_MDd} /Zi /Ob0 /Od ${_RTC1}")
|
||||
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")
|
||||
endif()
|
||||
unset(_MDd)
|
||||
unset(_MD)
|
||||
|
||||
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)
|
||||
set(CMAKE_${lang}_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebugDLL -MDd)
|
||||
endif()
|
||||
set(CMAKE_${lang}_LINKER_SUPPORTS_PDB ON)
|
||||
set(CMAKE_NINJA_DEPTYPE_${lang} msvc)
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "cmSystemTools.h"
|
||||
#include "cmTarget.h"
|
||||
#include "cmVersion.h"
|
||||
#include "cm_static_string_view.hxx"
|
||||
#include "cmake.h"
|
||||
|
||||
static std::string const kCMAKE_C_COMPILER_EXTERNAL_TOOLCHAIN =
|
||||
@ -42,6 +43,8 @@ static std::string const kCMAKE_LINK_SEARCH_END_STATIC =
|
||||
"CMAKE_LINK_SEARCH_END_STATIC";
|
||||
static std::string const kCMAKE_LINK_SEARCH_START_STATIC =
|
||||
"CMAKE_LINK_SEARCH_START_STATIC";
|
||||
static std::string const kCMAKE_MSVC_RUNTIME_LIBRARY_DEFAULT =
|
||||
"CMAKE_MSVC_RUNTIME_LIBRARY_DEFAULT";
|
||||
static std::string const kCMAKE_OSX_ARCHITECTURES = "CMAKE_OSX_ARCHITECTURES";
|
||||
static std::string const kCMAKE_OSX_DEPLOYMENT_TARGET =
|
||||
"CMAKE_OSX_DEPLOYMENT_TARGET";
|
||||
@ -500,6 +503,13 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
|
||||
fprintf(fout, "set(CMAKE_MODULE_PATH \"%s\")\n", def);
|
||||
}
|
||||
|
||||
/* Set MSVC runtime library policy to match our selection. */
|
||||
if (const char* msvcRuntimeLibraryDefault =
|
||||
this->Makefile->GetDefinition(kCMAKE_MSVC_RUNTIME_LIBRARY_DEFAULT)) {
|
||||
fprintf(fout, "cmake_policy(SET CMP0091 %s)\n",
|
||||
*msvcRuntimeLibraryDefault ? "NEW" : "OLD");
|
||||
}
|
||||
|
||||
std::string projectLangs;
|
||||
for (std::string const& li : testLangs) {
|
||||
projectLangs += " " + li;
|
||||
@ -660,6 +670,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
|
||||
vars.insert(kCMAKE_SYSROOT_COMPILE);
|
||||
vars.insert(kCMAKE_SYSROOT_LINK);
|
||||
vars.insert(kCMAKE_WARN_DEPRECATED);
|
||||
vars.emplace("CMAKE_MSVC_RUNTIME_LIBRARY"_s);
|
||||
|
||||
if (const char* varListStr = this->Makefile->GetDefinition(
|
||||
kCMAKE_TRY_COMPILE_PLATFORM_VARIABLES)) {
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "cmComputeLinkInformation.h"
|
||||
#include "cmCustomCommandGenerator.h"
|
||||
#include "cmGeneratedFileStream.h"
|
||||
#include "cmGeneratorExpression.h"
|
||||
#include "cmGeneratorExpressionEvaluationFile.h"
|
||||
#include "cmGeneratorTarget.h"
|
||||
#include "cmGlobalGenerator.h"
|
||||
@ -1519,8 +1520,40 @@ void cmLocalGenerator::AddLanguageFlags(std::string& flags,
|
||||
flagsVar += "_FLAGS";
|
||||
this->AddConfigVariableFlags(flags, flagsVar, config);
|
||||
|
||||
// Placeholder for possible future per-target flags.
|
||||
static_cast<void>(target);
|
||||
// Add MSVC runtime library flags. This is activated by the presence
|
||||
// of a default selection whether or not it is overridden by a property.
|
||||
const char* msvcRuntimeLibraryDefault =
|
||||
this->Makefile->GetDefinition("CMAKE_MSVC_RUNTIME_LIBRARY_DEFAULT");
|
||||
if (msvcRuntimeLibraryDefault && *msvcRuntimeLibraryDefault) {
|
||||
const char* msvcRuntimeLibraryValue =
|
||||
target->GetProperty("MSVC_RUNTIME_LIBRARY");
|
||||
if (!msvcRuntimeLibraryValue) {
|
||||
msvcRuntimeLibraryValue = msvcRuntimeLibraryDefault;
|
||||
}
|
||||
cmGeneratorExpression ge;
|
||||
std::unique_ptr<cmCompiledGeneratorExpression> cge =
|
||||
ge.Parse(msvcRuntimeLibraryValue);
|
||||
std::string const msvcRuntimeLibrary =
|
||||
cge->Evaluate(this, config, false, target);
|
||||
if (!msvcRuntimeLibrary.empty()) {
|
||||
if (const char* msvcRuntimeLibraryOptions =
|
||||
this->Makefile->GetDefinition(
|
||||
"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") &&
|
||||
!cmSystemTools::GetErrorOccuredFlag()) {
|
||||
// The compiler uses the MSVC ABI so it needs a known runtime library.
|
||||
this->IssueMessage(MessageType::FATAL_ERROR,
|
||||
"MSVC_RUNTIME_LIBRARY value '" +
|
||||
msvcRuntimeLibrary + "' not known for this " +
|
||||
lang + " compiler.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cmLocalGenerator::AddLanguageFlagsForLinking(
|
||||
|
@ -267,7 +267,10 @@ class cmMakefile;
|
||||
15, 0, cmPolicies::WARN) \
|
||||
SELECT(POLICY, CMP0090, \
|
||||
"export(PACKAGE) does not populate package registry by default.", 3, \
|
||||
15, 0, cmPolicies::WARN)
|
||||
15, 0, cmPolicies::WARN) \
|
||||
SELECT(POLICY, CMP0091, \
|
||||
"MSVC runtime library flags are selected by an abstraction.", 3, 15, \
|
||||
0, cmPolicies::WARN)
|
||||
|
||||
#define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
|
||||
#define CM_FOR_EACH_POLICY_ID(POLICY) \
|
||||
|
@ -304,6 +304,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
|
||||
InitProperty("AUTORCC_OPTIONS", nullptr);
|
||||
InitProperty("LINK_DEPENDS_NO_SHARED", nullptr);
|
||||
InitProperty("LINK_INTERFACE_LIBRARIES", nullptr);
|
||||
InitProperty("MSVC_RUNTIME_LIBRARY", nullptr);
|
||||
InitProperty("WIN32_EXECUTABLE", nullptr);
|
||||
InitProperty("MACOSX_BUNDLE", nullptr);
|
||||
InitProperty("MACOSX_RPATH", nullptr);
|
||||
|
@ -1995,6 +1995,10 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release
|
||||
if(NOT CMAKE_C_COMPILER_ID STREQUAL "Clang")
|
||||
ADD_TEST_MACRO(PrecompiledHeader foo)
|
||||
endif()
|
||||
ADD_TEST_MACRO(MSVCRuntimeLibrary)
|
||||
if(CMAKE_Fortran_COMPILER)
|
||||
ADD_TEST_MACRO(MSVCRuntimeLibrary.Fortran)
|
||||
endif()
|
||||
endif()
|
||||
if(MSVC OR
|
||||
"${CMAKE_GENERATOR}" MATCHES "(MSYS|MinGW) Makefiles")
|
||||
|
49
Tests/MSVCRuntimeLibrary/CMakeLists.txt
Normal file
49
Tests/MSVCRuntimeLibrary/CMakeLists.txt
Normal file
@ -0,0 +1,49 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
cmake_policy(SET CMP0091 NEW)
|
||||
project(MSVCRuntimeLibrary)
|
||||
|
||||
function(verify_combinations threads lang src)
|
||||
set(verify_tc_config_ Release)
|
||||
set(verify_tc_config_Debug Debug)
|
||||
set(verify_def_MultiThreaded -DVERIFY_MT)
|
||||
set(verify_def_Debug -DVERIFY_DEBUG)
|
||||
set(verify_def_DLL -DVERIFY_DLL)
|
||||
foreach(dbg "" Debug)
|
||||
foreach(dll "" DLL)
|
||||
# Construct the name of this runtime library combination.
|
||||
set(rtl "${threads}${dbg}${dll}")
|
||||
|
||||
# Test that try_compile builds with this RTL.
|
||||
set(CMAKE_MSVC_RUNTIME_LIBRARY "${rtl}")
|
||||
set(CMAKE_TRY_COMPILE_CONFIGURATION "${verify_tc_config_${dbg}}")
|
||||
set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY")
|
||||
try_compile(${rtl}_COMPILES
|
||||
${CMAKE_CURRENT_BINARY_DIR}/try_compile/${rtl}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/${src}
|
||||
COMPILE_DEFINITIONS ${verify_def_${threads}} ${verify_def_${dbg}} ${verify_def_${dll}}
|
||||
OUTPUT_VARIABLE ${rtl}_OUTPUT
|
||||
)
|
||||
if(${rtl}_COMPILES)
|
||||
message(STATUS "try_compile with ${rtl} worked")
|
||||
else()
|
||||
string(REPLACE "\n" "\n " ${rtl}_OUTPUT " ${${rtl}_OUTPUT}")
|
||||
message(SEND_ERROR "try_compile with ${rtl} failed:\n${${rtl}_OUTPUT}")
|
||||
endif()
|
||||
|
||||
# Test that targets build with this RTL.
|
||||
set(CMAKE_MSVC_RUNTIME_LIBRARY "$<$<BOOL:$<TARGET_PROPERTY:BOOL_TRUE>>:${rtl}>$<$<BOOL:$<TARGET_PROPERTY:BOOL_FALSE>>:BadContent>")
|
||||
add_library(${rtl}-${lang} ${src})
|
||||
set_property(TARGET ${rtl}-${lang} PROPERTY BOOL_TRUE TRUE)
|
||||
target_compile_definitions(${rtl}-${lang} PRIVATE ${verify_def_${threads}} ${verify_def_${dbg}} ${verify_def_${dll}})
|
||||
endforeach()
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
function(verify lang src)
|
||||
add_library(default-${lang} ${src})
|
||||
target_compile_definitions(default-${lang} PRIVATE VERIFY_MT VERIFY_DLL "$<$<CONFIG:Debug>:VERIFY_DEBUG>")
|
||||
verify_combinations(MultiThreaded ${lang} ${src})
|
||||
endfunction()
|
||||
|
||||
verify(C verify.c)
|
||||
verify(CXX verify.cxx)
|
50
Tests/MSVCRuntimeLibrary/Fortran/CMakeLists.txt
Normal file
50
Tests/MSVCRuntimeLibrary/Fortran/CMakeLists.txt
Normal file
@ -0,0 +1,50 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
cmake_policy(SET CMP0091 NEW)
|
||||
project(MSVCRuntimeLibraryFortran Fortran)
|
||||
|
||||
foreach(t MultiThreaded SingleThreaded)
|
||||
foreach(dbg "" Debug)
|
||||
foreach(dll "" DLL)
|
||||
set(var "CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_${t}${dbg}${dll}")
|
||||
# ifort does not actually define these, so inject them
|
||||
string(REPLACE "-threads" "-threads;-D_MT" "${var}" "${${var}}")
|
||||
string(REPLACE "-dbglibs" "-dbglibs;-D_DEBUG" "${var}" "${${var}}")
|
||||
endforeach()
|
||||
endforeach()
|
||||
endforeach()
|
||||
string(APPEND CMAKE_Fortran_FLAGS " -w")
|
||||
|
||||
function(verify_combinations threads lang src)
|
||||
set(verify_tc_config_ Release)
|
||||
set(verify_tc_config_Debug Debug)
|
||||
set(verify_def_MultiThreaded -DVERIFY_MT)
|
||||
set(verify_def_Debug -DVERIFY_DEBUG)
|
||||
set(verify_def_DLL -DVERIFY_DLL)
|
||||
foreach(dbg "" Debug)
|
||||
foreach(dll "" DLL)
|
||||
# Construct the name of this runtime library combination.
|
||||
set(rtl "${threads}${dbg}${dll}")
|
||||
|
||||
# Test that targets build with this RTL.
|
||||
set(CMAKE_MSVC_RUNTIME_LIBRARY "$<$<BOOL:$<TARGET_PROPERTY:BOOL_TRUE>>:${rtl}>$<$<BOOL:$<TARGET_PROPERTY:BOOL_FALSE>>:BadContent>")
|
||||
add_library(${rtl}-${lang} ${src})
|
||||
set_property(TARGET ${rtl}-${lang} PROPERTY BOOL_TRUE TRUE)
|
||||
target_compile_definitions(${rtl}-${lang} PRIVATE ${verify_def_${threads}} ${verify_def_${dbg}} ${verify_def_${dll}})
|
||||
endforeach()
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
function(verify lang src)
|
||||
add_library(default-${lang} ${src})
|
||||
target_compile_definitions(default-${lang} PRIVATE VERIFY_MT VERIFY_DLL "$<$<CONFIG:Debug>:VERIFY_DEBUG>")
|
||||
verify_combinations(MultiThreaded ${lang} ${src})
|
||||
endfunction()
|
||||
|
||||
verify(Fortran verify.F90)
|
||||
# Intel Fortran for Windows supports single-threaded RTL but it is
|
||||
# not implemented by the Visual Studio integration.
|
||||
if(NOT CMAKE_GENERATOR MATCHES "Visual Studio")
|
||||
verify_combinations(SingleThreaded Fortran verify.F90)
|
||||
endif()
|
1
Tests/MSVCRuntimeLibrary/Fortran/verify.F90
Normal file
1
Tests/MSVCRuntimeLibrary/Fortran/verify.F90
Normal file
@ -0,0 +1 @@
|
||||
#include "../verify.h"
|
1
Tests/MSVCRuntimeLibrary/verify.c
Normal file
1
Tests/MSVCRuntimeLibrary/verify.c
Normal file
@ -0,0 +1 @@
|
||||
#include "verify.h"
|
1
Tests/MSVCRuntimeLibrary/verify.cxx
Normal file
1
Tests/MSVCRuntimeLibrary/verify.cxx
Normal file
@ -0,0 +1 @@
|
||||
#include "verify.h"
|
29
Tests/MSVCRuntimeLibrary/verify.h
Normal file
29
Tests/MSVCRuntimeLibrary/verify.h
Normal file
@ -0,0 +1,29 @@
|
||||
#ifdef VERIFY_DEBUG
|
||||
# ifndef _DEBUG
|
||||
# error "_DEBUG not defined by debug runtime library selection"
|
||||
# endif
|
||||
#else
|
||||
# ifdef _DEBUG
|
||||
# error "_DEBUG defined by non-debug runtime library selection"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef VERIFY_DLL
|
||||
# ifndef _DLL
|
||||
# error "_DLL not defined by DLL runtime library selection"
|
||||
# endif
|
||||
#else
|
||||
# ifdef _DLL
|
||||
# error "_DLL defined by non-DLL runtime library selection"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef VERIFY_MT
|
||||
# ifndef _MT
|
||||
# error "_MT not defined by multi-threaded runtime library selection"
|
||||
# endif
|
||||
#else
|
||||
# ifdef _MT
|
||||
# error "_MT defined by single-threaded runtime library selection"
|
||||
# endif
|
||||
#endif
|
@ -195,6 +195,9 @@ add_RunCMake_test(LinkStatic)
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "^(Cray|PGI|XL|XLClang)$")
|
||||
add_RunCMake_test(MetaCompileFeatures)
|
||||
endif()
|
||||
if(MSVC)
|
||||
add_RunCMake_test(MSVCRuntimeLibrary)
|
||||
endif()
|
||||
add_RunCMake_test(ObjectLibrary)
|
||||
add_RunCMake_test(ParseImplicitIncludeInfo)
|
||||
if(UNIX AND CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG AND CMAKE_EXECUTABLE_FORMAT STREQUAL "ELF")
|
||||
|
1
Tests/RunCMake/MSVCRuntimeLibrary/CMP0091-NEW-result.txt
Normal file
1
Tests/RunCMake/MSVCRuntimeLibrary/CMP0091-NEW-result.txt
Normal file
@ -0,0 +1 @@
|
||||
1
|
2
Tests/RunCMake/MSVCRuntimeLibrary/CMP0091-NEW-stderr.txt
Normal file
2
Tests/RunCMake/MSVCRuntimeLibrary/CMP0091-NEW-stderr.txt
Normal file
@ -0,0 +1,2 @@
|
||||
^CMake Error in CMakeLists.txt:
|
||||
MSVC_RUNTIME_LIBRARY value 'BogusValue' not known for this C compiler.$
|
2
Tests/RunCMake/MSVCRuntimeLibrary/CMP0091-NEW.cmake
Normal file
2
Tests/RunCMake/MSVCRuntimeLibrary/CMP0091-NEW.cmake
Normal file
@ -0,0 +1,2 @@
|
||||
cmake_policy(SET CMP0091 NEW)
|
||||
include(CMP0091-common.cmake)
|
2
Tests/RunCMake/MSVCRuntimeLibrary/CMP0091-OLD.cmake
Normal file
2
Tests/RunCMake/MSVCRuntimeLibrary/CMP0091-OLD.cmake
Normal file
@ -0,0 +1,2 @@
|
||||
cmake_policy(SET CMP0091 OLD)
|
||||
include(CMP0091-common.cmake)
|
2
Tests/RunCMake/MSVCRuntimeLibrary/CMP0091-WARN.cmake
Normal file
2
Tests/RunCMake/MSVCRuntimeLibrary/CMP0091-WARN.cmake
Normal file
@ -0,0 +1,2 @@
|
||||
|
||||
include(CMP0091-common.cmake)
|
37
Tests/RunCMake/MSVCRuntimeLibrary/CMP0091-common.cmake
Normal file
37
Tests/RunCMake/MSVCRuntimeLibrary/CMP0091-common.cmake
Normal file
@ -0,0 +1,37 @@
|
||||
enable_language(C)
|
||||
|
||||
cmake_policy(GET CMP0091 cmp0091)
|
||||
if(cmp0091 STREQUAL "NEW")
|
||||
if(NOT CMAKE_MSVC_RUNTIME_LIBRARY_DEFAULT)
|
||||
message(SEND_ERROR "CMAKE_MSVC_RUNTIME_LIBRARY_DEFAULT not set under NEW behavior")
|
||||
endif()
|
||||
else()
|
||||
if(CMAKE_MSVC_RUNTIME_LIBRARY_DEFAULT)
|
||||
message(SEND_ERROR "CMAKE_MSVC_RUNTIME_LIBRARY_DEFAULT is set under OLD behavior")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CMAKE_C_COMPILER_ID STREQUAL "MSVC")
|
||||
if(CMAKE_C_FLAGS_DEBUG MATCHES "[/-]MDd( |$)")
|
||||
set(have_MDd 1)
|
||||
else()
|
||||
set(have_MDd 0)
|
||||
endif()
|
||||
if(CMAKE_C_FLAGS_RELEASE MATCHES "[/-]MD( |$)")
|
||||
set(have_MD 1)
|
||||
else()
|
||||
set(have_MD 0)
|
||||
endif()
|
||||
if(cmp0091 STREQUAL "NEW")
|
||||
if(have_MDd OR have_MD)
|
||||
message(SEND_ERROR "Have a -MD* flag under NEW behavior.")
|
||||
endif()
|
||||
else()
|
||||
if(NOT (have_MDd AND have_MD))
|
||||
message(SEND_ERROR "Do not have -MD* flags under OLD behavior.")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(CMAKE_MSVC_RUNTIME_LIBRARY BogusValue)
|
||||
add_library(foo empty.c)
|
3
Tests/RunCMake/MSVCRuntimeLibrary/CMakeLists.txt
Normal file
3
Tests/RunCMake/MSVCRuntimeLibrary/CMakeLists.txt
Normal file
@ -0,0 +1,3 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
project(${RunCMake_TEST} NONE)
|
||||
include(${RunCMake_TEST}.cmake)
|
5
Tests/RunCMake/MSVCRuntimeLibrary/RunCMakeTest.cmake
Normal file
5
Tests/RunCMake/MSVCRuntimeLibrary/RunCMakeTest.cmake
Normal file
@ -0,0 +1,5 @@
|
||||
include(RunCMake)
|
||||
|
||||
run_cmake(CMP0091-WARN)
|
||||
run_cmake(CMP0091-OLD)
|
||||
run_cmake(CMP0091-NEW)
|
0
Tests/RunCMake/MSVCRuntimeLibrary/empty.c
Normal file
0
Tests/RunCMake/MSVCRuntimeLibrary/empty.c
Normal file
@ -2,6 +2,7 @@ include(RunCMake)
|
||||
|
||||
run_cmake(VsCSharpCompilerOpts)
|
||||
run_cmake(ExplicitCMakeLists)
|
||||
run_cmake(RuntimeLibrary)
|
||||
run_cmake(SourceGroupCMakeLists)
|
||||
|
||||
run_cmake(VsConfigurationType)
|
||||
|
34
Tests/RunCMake/VS10Project/RuntimeLibrary-check.cmake
Normal file
34
Tests/RunCMake/VS10Project/RuntimeLibrary-check.cmake
Normal file
@ -0,0 +1,34 @@
|
||||
macro(RuntimeLibrary_check tgt rtl_expect)
|
||||
set(vcProjectFile "${RunCMake_TEST_BINARY_DIR}/${tgt}.vcxproj")
|
||||
if(NOT EXISTS "${vcProjectFile}")
|
||||
set(RunCMake_TEST_FAILED "Project file ${tgt}.vcxproj does not exist.")
|
||||
return()
|
||||
endif()
|
||||
|
||||
set(HAVE_Runtimelibrary 0)
|
||||
|
||||
file(STRINGS "${vcProjectFile}" lines)
|
||||
foreach(line IN LISTS lines)
|
||||
if(line MATCHES "^ *<RuntimeLibrary>([^<>]+)</RuntimeLibrary>")
|
||||
set(rtl_actual "${CMAKE_MATCH_1}")
|
||||
if(NOT "${rtl_actual}" STREQUAL "${rtl_expect}")
|
||||
set(RunCMake_TEST_FAILED "Project file ${tgt}.vcxproj has RuntimeLibrary '${rtl_actual}', not '${rtl_expect}'.")
|
||||
return()
|
||||
endif()
|
||||
set(HAVE_Runtimelibrary 1)
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(NOT HAVE_Runtimelibrary)
|
||||
set(RunCMake_TEST_FAILED "Project file ${tgt}.vcxproj does not have a RuntimeLibrary field.")
|
||||
return()
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
RuntimeLibrary_check(default-C MultiThreadedDebugDLL)
|
||||
RuntimeLibrary_check(default-CXX MultiThreadedDebugDLL)
|
||||
RuntimeLibrary_check(MTd-C MultiThreadedDebug)
|
||||
RuntimeLibrary_check(MTd-CXX MultiThreadedDebug)
|
||||
RuntimeLibrary_check(MT-C MultiThreaded)
|
||||
RuntimeLibrary_check(MT-CXX MultiThreaded)
|
16
Tests/RunCMake/VS10Project/RuntimeLibrary.cmake
Normal file
16
Tests/RunCMake/VS10Project/RuntimeLibrary.cmake
Normal file
@ -0,0 +1,16 @@
|
||||
set(CMAKE_CONFIGURATION_TYPES Debug)
|
||||
cmake_policy(SET CMP0091 NEW)
|
||||
enable_language(C)
|
||||
enable_language(CXX)
|
||||
|
||||
add_library(default-C empty.c)
|
||||
add_library(default-CXX empty.cxx)
|
||||
|
||||
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreadedDebug")
|
||||
add_library(MTd-C empty.c)
|
||||
add_library(MTd-CXX empty.cxx)
|
||||
|
||||
add_library(MT-C empty.c)
|
||||
set_property(TARGET MT-C PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded")
|
||||
add_library(MT-CXX empty.cxx)
|
||||
set_property(TARGET MT-CXX PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded")
|
0
Tests/RunCMake/VS10Project/empty.c
Normal file
0
Tests/RunCMake/VS10Project/empty.c
Normal file
0
Tests/RunCMake/VS10Project/empty.cxx
Normal file
0
Tests/RunCMake/VS10Project/empty.cxx
Normal file
Loading…
Reference in New Issue
Block a user