summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2024-02-20 15:37:18 (GMT)
committerKitware Robot <kwrobot@kitware.com>2024-02-20 15:37:32 (GMT)
commit3a171009e96a74da0c6c67030716ee83cd54a47e (patch)
treec65462fc074680d3d6a20a729236b99554f3d69e
parent3710358c7ed30cf1a0e19b689391140adaadba75 (diff)
parentb81464144468e930acc5bf55243dbb0a0f3ae0fb (diff)
downloadCMake-3a171009e96a74da0c6c67030716ee83cd54a47e.zip
CMake-3a171009e96a74da0c6c67030716ee83cd54a47e.tar.gz
CMake-3a171009e96a74da0c6c67030716ee83cd54a47e.tar.bz2
Merge topic 'vs-UseDebugLibraries'
b814641444 VS: Add [CMAKE_]VS_USE_DEBUG_LIBRARIES options to control UseDebugLibraries 67de5b7b82 VS: Suppress MSBuild default settings affected by UseDebugLibraries 0ae372daee VS: Factor out common MS tool configuration Acked-by: Kitware Robot <kwrobot@kitware.com> Merge-request: !9270
-rw-r--r--Help/manual/cmake-properties.7.rst1
-rw-r--r--Help/manual/cmake-variables.7.rst1
-rw-r--r--Help/prop_tgt/VS_USE_DEBUG_LIBRARIES-PURPOSE.txt18
-rw-r--r--Help/prop_tgt/VS_USE_DEBUG_LIBRARIES.rst27
-rw-r--r--Help/release/dev/vs-UseDebugLibraries.rst6
-rw-r--r--Help/variable/CMAKE_VS_USE_DEBUG_LIBRARIES.rst28
-rw-r--r--Source/cmCoreTryCompile.cxx1
-rw-r--r--Source/cmTarget.cxx1
-rw-r--r--Source/cmVisualStudio10TargetGenerator.cxx72
-rw-r--r--Source/cmVisualStudio10TargetGenerator.h2
-rw-r--r--Tests/MSVCRuntimeLibrary/CMakeLists.txt4
-rw-r--r--Tests/RunCMake/CMakeLists.txt1
-rw-r--r--Tests/RunCMake/VS10Project/RuntimeLibrary-check.cmake2
-rw-r--r--Tests/RunCMake/VS10Project/VsJustMyCode-check.cmake2
-rw-r--r--Tests/RunCMake/VS10ProjectUseDebugLibraries/CMakeLists.txt3
-rw-r--r--Tests/RunCMake/VS10ProjectUseDebugLibraries/Default-check.cmake8
-rw-r--r--Tests/RunCMake/VS10ProjectUseDebugLibraries/Default.cmake10
-rw-r--r--Tests/RunCMake/VS10ProjectUseDebugLibraries/Explicit-check.cmake10
-rw-r--r--Tests/RunCMake/VS10ProjectUseDebugLibraries/Explicit.cmake20
-rw-r--r--Tests/RunCMake/VS10ProjectUseDebugLibraries/RunCMakeTest.cmake5
-rw-r--r--Tests/RunCMake/VS10ProjectUseDebugLibraries/check-common.cmake42
-rw-r--r--Tests/RunCMake/VS10ProjectUseDebugLibraries/empty.cxx0
22 files changed, 242 insertions, 22 deletions
diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst
index 0d1046a..8d2d202 100644
--- a/Help/manual/cmake-properties.7.rst
+++ b/Help/manual/cmake-properties.7.rst
@@ -445,6 +445,7 @@ Properties on Targets
/prop_tgt/VS_SDK_REFERENCES
/prop_tgt/VS_SOLUTION_DEPLOY
/prop_tgt/VS_SOURCE_SETTINGS_tool
+ /prop_tgt/VS_USE_DEBUG_LIBRARIES
/prop_tgt/VS_USER_PROPS
/prop_tgt/VS_WINDOWS_TARGET_PLATFORM_MIN_VERSION
/prop_tgt/VS_WINRT_COMPONENT
diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst
index 8a5ab30..c7efdcf 100644
--- a/Help/manual/cmake-variables.7.rst
+++ b/Help/manual/cmake-variables.7.rst
@@ -137,6 +137,7 @@ Variables that Provide Information
/variable/CMAKE_VS_TARGET_FRAMEWORK_IDENTIFIER
/variable/CMAKE_VS_TARGET_FRAMEWORK_TARGETS_VERSION
/variable/CMAKE_VS_TARGET_FRAMEWORK_VERSION
+ /variable/CMAKE_VS_USE_DEBUG_LIBRARIES
/variable/CMAKE_VS_VERSION_BUILD_NUMBER
/variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_MIN_VERSION
/variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION
diff --git a/Help/prop_tgt/VS_USE_DEBUG_LIBRARIES-PURPOSE.txt b/Help/prop_tgt/VS_USE_DEBUG_LIBRARIES-PURPOSE.txt
new file mode 100644
index 0000000..8d3714e
--- /dev/null
+++ b/Help/prop_tgt/VS_USE_DEBUG_LIBRARIES-PURPOSE.txt
@@ -0,0 +1,18 @@
+Indicate to :ref:`Visual Studio Generators` what configurations are considered
+debug configurations. This controls the ``UseDebugLibraries`` setting in
+each configuration of a ``.vcxproj`` file.
+
+The "Use Debug Libraries" setting in Visual Studio projects, despite its
+specific-sounding name, is a general-purpose indicator of what configurations
+are considered debug configurations. In standalone projects, this may affect
+MSBuild's default selection of MSVC runtime library, optimization flags,
+runtime checks, and similar settings. In CMake projects those settings are
+typically generated explicitly based on the project's specification, e.g.,
+the MSVC runtime library is controlled by |MSVC_RUNTIME_LIBRARY|. However,
+the ``UseDebugLibraries`` indicator is useful for reference by both humans
+and tools, and may also affect the behavior of platform-specific SDKs.
+
+Set |VS_USE_DEBUG_LIBRARIES| to a true or false value to indicate whether
+each configuration is considered a debug configuration. The value may also
+be the empty string (``""``) in which case no ``UseDebugLibraries`` will be
+added explicitly by CMake, and MSBuild will use its default value, ``false``.
diff --git a/Help/prop_tgt/VS_USE_DEBUG_LIBRARIES.rst b/Help/prop_tgt/VS_USE_DEBUG_LIBRARIES.rst
new file mode 100644
index 0000000..78ad36a
--- /dev/null
+++ b/Help/prop_tgt/VS_USE_DEBUG_LIBRARIES.rst
@@ -0,0 +1,27 @@
+VS_USE_DEBUG_LIBRARIES
+----------------------
+
+.. versionadded:: 3.30
+
+.. |VS_USE_DEBUG_LIBRARIES| replace:: ``VS_USE_DEBUG_LIBRARIES``
+.. |MSVC_RUNTIME_LIBRARY| replace:: :prop_tgt:`MSVC_RUNTIME_LIBRARY`
+
+.. include:: VS_USE_DEBUG_LIBRARIES-PURPOSE.txt
+
+Use :manual:`generator expressions <cmake-generator-expressions(7)>`
+for per-configuration specification. For example, the code:
+
+.. code-block:: cmake
+
+ add_executable(foo foo.c)
+ set_property(TARGET foo PROPERTY
+ VS_USE_DEBUG_LIBRARIES "$<CONFIG:Debug,Custom>")
+
+indicates that target ``foo`` considers its "Debug" and "Custom"
+configurations to be debug configurations, and its other configurations
+to be non-debug configurations.
+
+The property is initialized from the value of the
+:variable:`CMAKE_VS_USE_DEBUG_LIBRARIES` variable, if it is set.
+If the property is not set, then CMake does not generate any
+``UseDebugLibraries`` indicator.
diff --git a/Help/release/dev/vs-UseDebugLibraries.rst b/Help/release/dev/vs-UseDebugLibraries.rst
new file mode 100644
index 0000000..477c385
--- /dev/null
+++ b/Help/release/dev/vs-UseDebugLibraries.rst
@@ -0,0 +1,6 @@
+vs-UseDebugLibraries
+--------------------
+
+* The :variable:`CMAKE_VS_USE_DEBUG_LIBRARIES` variable and corresponding
+ :prop_tgt:`VS_USE_DEBUG_LIBRARIES` target property were added to explicitly
+ control ``UseDebugLibraries`` indicators in ``.vcxproj`` files.
diff --git a/Help/variable/CMAKE_VS_USE_DEBUG_LIBRARIES.rst b/Help/variable/CMAKE_VS_USE_DEBUG_LIBRARIES.rst
new file mode 100644
index 0000000..45d3eff
--- /dev/null
+++ b/Help/variable/CMAKE_VS_USE_DEBUG_LIBRARIES.rst
@@ -0,0 +1,28 @@
+CMAKE_VS_USE_DEBUG_LIBRARIES
+----------------------------
+
+.. versionadded:: 3.30
+
+.. |VS_USE_DEBUG_LIBRARIES| replace:: ``CMAKE_VS_USE_DEBUG_LIBRARIES``
+.. |MSVC_RUNTIME_LIBRARY| replace:: :variable:`CMAKE_MSVC_RUNTIME_LIBRARY`
+
+.. include:: ../prop_tgt/VS_USE_DEBUG_LIBRARIES-PURPOSE.txt
+
+Use :manual:`generator expressions <cmake-generator-expressions(7)>`
+for per-configuration specification. For example, the code:
+
+.. code-block:: cmake
+
+ set(CMAKE_VS_USE_DEBUG_LIBRARIES "$<CONFIG:Debug,Custom>")
+
+indicates that all following targets consider their "Debug" and "Custom"
+configurations to be debug configurations, and their other configurations
+to be non-debug configurations.
+
+This variable is used to initialize the :prop_tgt:`VS_USE_DEBUG_LIBRARIES`
+property on all targets as they are created. It is also propagated by
+calls to the :command:`try_compile` command into its test project.
+
+If this variable is not set then the :prop_tgt:`VS_USE_DEBUG_LIBRARIES`
+property will not be set automatically. If that property is not set
+then CMake does not generate any ``UseDebugLibraries`` indicator.
diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx
index a4f36cc..25fc52f 100644
--- a/Source/cmCoreTryCompile.cxx
+++ b/Source/cmCoreTryCompile.cxx
@@ -1151,6 +1151,7 @@ cm::optional<cmTryCompileResult> cmCoreTryCompile::TryCompileCode(
vars.emplace("CMAKE_WATCOM_RUNTIME_LIBRARY"_s);
vars.emplace("CMAKE_MSVC_DEBUG_INFORMATION_FORMAT"_s);
vars.emplace("CMAKE_CXX_COMPILER_CLANG_SCAN_DEPS"_s);
+ vars.emplace("CMAKE_VS_USE_DEBUG_LIBRARIES"_s);
if (cmValue varListStr = this->Makefile->GetDefinition(
kCMAKE_TRY_COMPILE_PLATFORM_VARIABLES)) {
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 76cca21..b8001ad 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -404,6 +404,7 @@ TargetProperty const StaticTargetProperties[] = {
{ "VS_DEBUGGER_COMMAND_ARGUMENTS"_s, IC::ExecutableTarget },
{ "VS_DEBUGGER_ENVIRONMENT"_s, IC::ExecutableTarget },
{ "VS_DEBUGGER_WORKING_DIRECTORY"_s, IC::ExecutableTarget },
+ { "VS_USE_DEBUG_LIBRARIES"_s, IC::NonImportedTarget },
// ---- OpenWatcom
{ "WATCOM_RUNTIME_LIBRARY"_s, IC::CanCompileSources },
// -- Language
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index d572f30..38a2ed8 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -1512,7 +1512,6 @@ void cmVisualStudio10TargetGenerator::WriteCEDebugProjectConfigurationValues(
void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValues(
Elem& e1, std::string const& config)
{
- cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
cmValue mfcFlag = this->Makefile->GetDefinition("CMAKE_MFC_FLAG");
if (mfcFlag) {
std::string const mfcFlagValue =
@@ -1543,12 +1542,9 @@ void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValues(
} else {
e1.Element("CharacterSet", "MultiByte");
}
- if (cmValue projectToolsetOverride =
- this->GeneratorTarget->GetProperty("VS_PLATFORM_TOOLSET")) {
- e1.Element("PlatformToolset", *projectToolsetOverride);
- } else if (const char* toolset = gg->GetPlatformToolset()) {
- e1.Element("PlatformToolset", toolset);
- }
+
+ this->WriteMSToolConfigurationValuesCommon(e1, config);
+
if (this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_COMPONENT") ||
this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_EXTENSIONS")) {
e1.Element("WindowsAppContainer", "true");
@@ -1579,8 +1575,6 @@ void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValuesManaged(
return;
}
- cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
-
Options& o = *(this->ClOptions[config]);
if (o.IsDebug()) {
@@ -1598,12 +1592,7 @@ void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValuesManaged(
o.RemoveFlag("Platform");
}
- if (cmValue projectToolsetOverride =
- this->GeneratorTarget->GetProperty("VS_PLATFORM_TOOLSET")) {
- e1.Element("PlatformToolset", *projectToolsetOverride);
- } else if (const char* toolset = gg->GetPlatformToolset()) {
- e1.Element("PlatformToolset", toolset);
- }
+ this->WriteMSToolConfigurationValuesCommon(e1, config);
std::string postfixName =
cmStrCat(cmSystemTools::UpperCase(config), "_POSTFIX");
@@ -1623,6 +1612,37 @@ void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValuesManaged(
oh.OutputFlagMap();
}
+void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValuesCommon(
+ Elem& e1, std::string const& config)
+{
+ cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
+ if (cmValue projectToolsetOverride =
+ this->GeneratorTarget->GetProperty("VS_PLATFORM_TOOLSET")) {
+ e1.Element("PlatformToolset", *projectToolsetOverride);
+ } else if (const char* toolset = gg->GetPlatformToolset()) {
+ e1.Element("PlatformToolset", toolset);
+ }
+
+ cm::optional<bool> maybeUseDebugLibraries;
+ if (cmValue useDebugLibrariesProp =
+ this->GeneratorTarget->GetProperty("VS_USE_DEBUG_LIBRARIES")) {
+ // The project explicitly specified a value for this target.
+ // An empty string suppresses generation of the setting altogether.
+ std::string const useDebugLibraries = cmGeneratorExpression::Evaluate(
+ *useDebugLibrariesProp, this->LocalGenerator, config);
+ if (!useDebugLibraries.empty()) {
+ maybeUseDebugLibraries = cmIsOn(useDebugLibraries);
+ }
+ }
+ if (maybeUseDebugLibraries) {
+ if (*maybeUseDebugLibraries) {
+ e1.Element("UseDebugLibraries", "true");
+ } else {
+ e1.Element("UseDebugLibraries", "false");
+ }
+ }
+}
+
//----------------------------------------------------------------------------
void cmVisualStudio10TargetGenerator::WriteNsightTegraConfigurationValues(
Elem& e1, std::string const&)
@@ -3154,7 +3174,10 @@ void cmVisualStudio10TargetGenerator::OutputLinkIncremental(
Options& linkOptions = *(this->LinkOptions[configName]);
const std::string cond = this->CalcCondition(configName);
- if (this->IPOEnabledConfigurations.count(configName) == 0) {
+ if (this->IPOEnabledConfigurations.count(configName) > 0) {
+ // Suppress LinkIncremental in favor of WholeProgramOptimization.
+ e1.WritePlatformConfigTag("LinkIncremental", cond, "");
+ } else {
const char* incremental = linkOptions.GetFlag("LinkIncremental");
e1.WritePlatformConfigTag("LinkIncremental", cond,
(incremental ? incremental : "true"));
@@ -3499,6 +3522,23 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
clOptions.RemoveFlag("CompileAs");
}
+ if (this->ProjectType == VsProjectType::vcxproj && this->MSTools) {
+ // Suppress Microsoft.Cl.Common.props default settings for which the
+ // project specifies no flags. Do not let UseDebugLibraries affect them.
+ if (!clOptions.HasFlag("BasicRuntimeChecks")) {
+ clOptions.AddFlag("BasicRuntimeChecks", "Default");
+ }
+ if (!clOptions.HasFlag("Optimization")) {
+ clOptions.AddFlag("Optimization", "");
+ }
+ if (!clOptions.HasFlag("RuntimeLibrary")) {
+ clOptions.AddFlag("RuntimeLibrary", "");
+ }
+ if (!clOptions.HasFlag("SupportJustMyCode")) {
+ clOptions.AddFlag("SupportJustMyCode", "");
+ }
+ }
+
this->ClOptions[configName] = std::move(pOptions);
return true;
}
diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h
index 2080e9e..bafd5e9 100644
--- a/Source/cmVisualStudio10TargetGenerator.h
+++ b/Source/cmVisualStudio10TargetGenerator.h
@@ -72,6 +72,8 @@ private:
void WriteCEDebugProjectConfigurationValues(Elem& e0);
void WriteMSToolConfigurationValuesManaged(Elem& e1,
std::string const& config);
+ void WriteMSToolConfigurationValuesCommon(Elem& e1,
+ std::string const& config);
void WriteHeaderSource(Elem& e1, cmSourceFile const* sf,
ConfigToSettings const& toolSettings);
void WriteExtraSource(Elem& e1, cmSourceFile const* sf,
diff --git a/Tests/MSVCRuntimeLibrary/CMakeLists.txt b/Tests/MSVCRuntimeLibrary/CMakeLists.txt
index f7d9fec..f1ed9b4 100644
--- a/Tests/MSVCRuntimeLibrary/CMakeLists.txt
+++ b/Tests/MSVCRuntimeLibrary/CMakeLists.txt
@@ -57,10 +57,6 @@ function(verify lang src)
# VS 2005 and above default to multi-threaded.
target_compile_definitions(empty-${lang} PRIVATE VERIFY_MT)
endif()
- if(CMAKE_GENERATOR MATCHES "Visual Studio ([^9]|9[0-9])")
- # VS 2010 and above have a different default runtime library for projects than 'cl'.
- target_compile_definitions(empty-${lang} PRIVATE VERIFY_DLL)
- endif()
endif()
endfunction()
diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index d9090d6..a2a9ee9 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -731,6 +731,7 @@ if("${CMAKE_GENERATOR}" MATCHES "Visual Studio ([^9]|9[0-9])")
-DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID}
-DCMAKE_C_COMPILER_VERSION=${CMAKE_C_COMPILER_VERSION}
)
+ add_RunCMake_test(VS10ProjectUseDebugLibraries)
if( vs12 AND wince )
add_RunCMake_test( VS10ProjectWinCE "-DRunCMake_GENERATOR_PLATFORM=${wince_sdk}")
endif()
diff --git a/Tests/RunCMake/VS10Project/RuntimeLibrary-check.cmake b/Tests/RunCMake/VS10Project/RuntimeLibrary-check.cmake
index 689b35f..b5b195a 100644
--- a/Tests/RunCMake/VS10Project/RuntimeLibrary-check.cmake
+++ b/Tests/RunCMake/VS10Project/RuntimeLibrary-check.cmake
@@ -9,7 +9,7 @@ macro(RuntimeLibrary_check tgt rtl_expect)
file(STRINGS "${vcProjectFile}" lines)
foreach(line IN LISTS lines)
- if(line MATCHES "^ *<RuntimeLibrary>([^<>]+)</RuntimeLibrary>")
+ 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}'.")
diff --git a/Tests/RunCMake/VS10Project/VsJustMyCode-check.cmake b/Tests/RunCMake/VS10Project/VsJustMyCode-check.cmake
index 7119976..e76d931 100644
--- a/Tests/RunCMake/VS10Project/VsJustMyCode-check.cmake
+++ b/Tests/RunCMake/VS10Project/VsJustMyCode-check.cmake
@@ -9,7 +9,7 @@ macro(VsJustMyCode_check tgt jmc_expect)
file(STRINGS "${vcProjectFile}" lines)
foreach(line IN LISTS lines)
- if(line MATCHES "^ *<SupportJustMyCode>([^<>]+)</SupportJustMyCode>")
+ if(line MATCHES "^ *<SupportJustMyCode>([^<>]*)</SupportJustMyCode>")
set(jmc_actual "${CMAKE_MATCH_1}")
if(NOT "${jmc_actual}" STREQUAL "${jmc_expect}")
set(RunCMake_TEST_FAILED "Project file ${tgt}.vcxproj has <SupportJustMyCode> '${jmc_actual}', not '${jmc_expect}'.")
diff --git a/Tests/RunCMake/VS10ProjectUseDebugLibraries/CMakeLists.txt b/Tests/RunCMake/VS10ProjectUseDebugLibraries/CMakeLists.txt
new file mode 100644
index 0000000..94e43ba
--- /dev/null
+++ b/Tests/RunCMake/VS10ProjectUseDebugLibraries/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.29)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/VS10ProjectUseDebugLibraries/Default-check.cmake b/Tests/RunCMake/VS10ProjectUseDebugLibraries/Default-check.cmake
new file mode 100644
index 0000000..673144e
--- /dev/null
+++ b/Tests/RunCMake/VS10ProjectUseDebugLibraries/Default-check.cmake
@@ -0,0 +1,8 @@
+include(${CMAKE_CURRENT_LIST_DIR}/check-common.cmake)
+
+UseDebugLibraries_check(default "" "")
+UseDebugLibraries_check(defaultCLR "" "")
+UseDebugLibraries_check(defaultUtil "" "")
+UseDebugLibraries_check(defaultRTL "" "")
+UseDebugLibraries_check(ALL_BUILD "" "")
+UseDebugLibraries_check(ZERO_CHECK "" "")
diff --git a/Tests/RunCMake/VS10ProjectUseDebugLibraries/Default.cmake b/Tests/RunCMake/VS10ProjectUseDebugLibraries/Default.cmake
new file mode 100644
index 0000000..6afcfb6
--- /dev/null
+++ b/Tests/RunCMake/VS10ProjectUseDebugLibraries/Default.cmake
@@ -0,0 +1,10 @@
+set(CMAKE_CONFIGURATION_TYPES Debug Release)
+enable_language(CXX)
+
+# Test several generator code paths covering different target types.
+add_library(default empty.cxx)
+add_library(defaultCLR empty.cxx)
+set_property(TARGET defaultCLR PROPERTY COMMON_LANGUAGE_RUNTIME "")
+add_library(defaultRTL empty.cxx)
+set_property(TARGET defaultRTL PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreadedDLL")
+add_custom_target(defaultUtil)
diff --git a/Tests/RunCMake/VS10ProjectUseDebugLibraries/Explicit-check.cmake b/Tests/RunCMake/VS10ProjectUseDebugLibraries/Explicit-check.cmake
new file mode 100644
index 0000000..385b798
--- /dev/null
+++ b/Tests/RunCMake/VS10ProjectUseDebugLibraries/Explicit-check.cmake
@@ -0,0 +1,10 @@
+include(${CMAKE_CURRENT_LIST_DIR}/check-common.cmake)
+
+UseDebugLibraries_check(empty "" "")
+UseDebugLibraries_check(emptyCLR "" "")
+UseDebugLibraries_check(emptyUtil "" "")
+UseDebugLibraries_check(genex "true" "false")
+UseDebugLibraries_check(genexCLR "true" "false")
+UseDebugLibraries_check(genexUtil "true" "false")
+UseDebugLibraries_check(ALL_BUILD "false" "false")
+UseDebugLibraries_check(ZERO_CHECK "false" "false")
diff --git a/Tests/RunCMake/VS10ProjectUseDebugLibraries/Explicit.cmake b/Tests/RunCMake/VS10ProjectUseDebugLibraries/Explicit.cmake
new file mode 100644
index 0000000..3433745
--- /dev/null
+++ b/Tests/RunCMake/VS10ProjectUseDebugLibraries/Explicit.cmake
@@ -0,0 +1,20 @@
+set(CMAKE_CONFIGURATION_TYPES Debug Release)
+enable_language(CXX)
+
+# An empty string suppresses generation of the setting.
+set(CMAKE_VS_USE_DEBUG_LIBRARIES "")
+add_library(empty empty.cxx)
+add_library(emptyCLR empty.cxx)
+set_property(TARGET emptyCLR PROPERTY COMMON_LANGUAGE_RUNTIME "")
+add_custom_target(emptyUtil)
+
+# A generator expression can encode per-config values.
+set(CMAKE_VS_USE_DEBUG_LIBRARIES "$<CONFIG:Debug>")
+add_library(genex empty.cxx)
+add_library(genexCLR empty.cxx)
+set_property(TARGET genexCLR PROPERTY COMMON_LANGUAGE_RUNTIME "")
+add_custom_target(genexUtil)
+
+# The last setting in the top-level directcory affects
+# the builtin targets like ALL_BUILD and ZERO_CHECK.
+set(CMAKE_VS_USE_DEBUG_LIBRARIES 0)
diff --git a/Tests/RunCMake/VS10ProjectUseDebugLibraries/RunCMakeTest.cmake b/Tests/RunCMake/VS10ProjectUseDebugLibraries/RunCMakeTest.cmake
new file mode 100644
index 0000000..8db2028
--- /dev/null
+++ b/Tests/RunCMake/VS10ProjectUseDebugLibraries/RunCMakeTest.cmake
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 3.29)
+include(RunCMake)
+
+run_cmake(Default)
+run_cmake(Explicit)
diff --git a/Tests/RunCMake/VS10ProjectUseDebugLibraries/check-common.cmake b/Tests/RunCMake/VS10ProjectUseDebugLibraries/check-common.cmake
new file mode 100644
index 0000000..311c8a7
--- /dev/null
+++ b/Tests/RunCMake/VS10ProjectUseDebugLibraries/check-common.cmake
@@ -0,0 +1,42 @@
+cmake_policy(SET CMP0140 NEW)
+function(UseDebugLibraries_check tgt udl_expect_debug udl_expect_release)
+ 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_udl_debug 0)
+ set(have_udl_release 0)
+ set(inConfig "")
+
+ file(STRINGS "${vcProjectFile}" lines)
+ foreach(line IN LISTS lines)
+ if(line MATCHES [[^ *<PropertyGroup Condition="'\$\(Configuration\)\|\$\(Platform\)'=='([^"|]+)\|[^"]+" Label="Configuration">.*$]])
+ string(TOLOWER "${CMAKE_MATCH_1}" inConfig)
+ elseif(inConfig)
+ if(line MATCHES "^ *</PropertyGroup>.*$")
+ set(inConfig "")
+ elseif(line MATCHES "^ *<UseDebugLibraries>([^<>]+)</UseDebugLibraries>")
+ set(udl_actual "${CMAKE_MATCH_1}")
+ set(have_udl_${inConfig} 1)
+ if (NOT "${udl_expect_${inConfig}}" STREQUAL "")
+ if(NOT "${udl_actual}" STREQUAL "${udl_expect_${inConfig}}")
+ string(APPEND RunCMake_TEST_FAILED "Project file ${tgt}.vcxproj has ${inConfig} UseDebugLibraries '${udl_actual}', not '${udl_expect_${inConfig}}'.\n")
+ endif()
+ else()
+ string(APPEND RunCMake_TEST_FAILED "Project file ${tgt}.vcxproj has ${inConfig} UseDebugLibraries '${udl_actual}', but should not have one.\n")
+ endif()
+ unset(udl_actual)
+ endif()
+ endif()
+ endforeach()
+
+ if(NOT have_udl_debug AND NOT "${udl_expect_debug}" STREQUAL "")
+ string(APPEND RunCMake_TEST_FAILED "Project file ${tgt}.vcxproj does not have a debug UseDebugLibraries field, but should have one.\n")
+ endif()
+ if(NOT have_udl_release AND NOT "${udl_expect_release}" STREQUAL "")
+ string(APPEND RunCMake_TEST_FAILED "Project file ${tgt}.vcxproj does not have a release UseDebugLibraries field, but should have one.\n")
+ endif()
+ return(PROPAGATE RunCMake_TEST_FAILED)
+endfunction()
diff --git a/Tests/RunCMake/VS10ProjectUseDebugLibraries/empty.cxx b/Tests/RunCMake/VS10ProjectUseDebugLibraries/empty.cxx
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/RunCMake/VS10ProjectUseDebugLibraries/empty.cxx