فهرست منبع

VS: Add support to override VCTargetsPath through toolset

Fixes: #19708
Alexander Boczar 6 سال پیش
والد
کامیت
548e9051a4

+ 6 - 0
Help/release/dev/vs-vctargetspath.rst

@@ -0,0 +1,6 @@
+vs-vctargetspath
+----------------
+
+* With :ref:`Visual Studio Generators` for VS 2010 and above,
+  the :variable:`CMAKE_GENERATOR_TOOLSET` setting gained an option
+  to specify the ``VCTargetsPath`` value for project files.

+ 5 - 0
Help/variable/CMAKE_GENERATOR_TOOLSET.rst

@@ -58,3 +58,8 @@ Supported pairs are:
   Specify the toolset version to use.  Supported by VS 2017
   and above with the specified toolset installed.
   See the :variable:`CMAKE_VS_PLATFORM_TOOLSET_VERSION` variable.
+
+``VCTargetsPath=<path>``
+  Specify an alternative ``VCTargetsPath`` value for Visual Studio
+  project files.  This allows use of VS platform extension configuration
+  files (``.props`` and ``.targets``) that are not installed with VS.

+ 3 - 0
Modules/CMakeDetermineCompilerId.cmake

@@ -317,6 +317,9 @@ Id flags: ${testflags} ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS}
     if(CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION)
       set(id_WindowsTargetPlatformVersion "<WindowsTargetPlatformVersion>${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}</WindowsTargetPlatformVersion>")
     endif()
+    if(CMAKE_VS_PLATFORM_TOOLSET_VCTARGETS_CUSTOM_DIR)
+      set(id_ToolsetVCTargetsDir "<VCTargetsPath>${CMAKE_VS_PLATFORM_TOOLSET_VCTARGETS_CUSTOM_DIR}</VCTargetsPath>")
+    endif()
     if(id_platform STREQUAL ARM64)
       set(id_WindowsSDKDesktopARMSupport "<WindowsSDKDesktopARM64Support>true</WindowsSDKDesktopARM64Support>")
     elseif(id_platform STREQUAL ARM)

+ 1 - 0
Modules/CompilerId/VS-10.vcxproj.in

@@ -15,6 +15,7 @@
     @id_WindowsTargetPlatformVersion@
     @id_WindowsSDKDesktopARMSupport@
     @id_CudaToolkitCustomDir@
+    @id_ToolsetVCTargetsDir@
   </PropertyGroup>
   @id_toolset_version_props@
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+ 29 - 1
Source/cmGlobalVisualStudio10Generator.cxx

@@ -26,6 +26,16 @@
 static const char vs10generatorName[] = "Visual Studio 10 2010";
 static std::map<std::string, std::vector<cmIDEFlagTable>> loadedFlagJsonFiles;
 
+static void ConvertToWindowsSlashes(std::string& s)
+{
+  // first convert all of the slashes
+  for (auto& ch : s) {
+    if (ch == '/') {
+      ch = '\\';
+    }
+  }
+}
+
 // Map generator name without year to name with year.
 static const char* cmVS10GenName(const std::string& name, std::string& genName)
 {
@@ -212,7 +222,7 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorToolset(
     return true;
   }
 
-  if (!this->FindVCTargetsPath(mf)) {
+  if (this->CustomVCTargetsPath.empty() && !this->FindVCTargetsPath(mf)) {
     return false;
   }
 
@@ -353,6 +363,11 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorToolset(
   if (const char* cudaDir = this->GetPlatformToolsetCudaCustomDir()) {
     mf->AddDefinition("CMAKE_VS_PLATFORM_TOOLSET_CUDA_CUSTOM_DIR", cudaDir);
   }
+  if (const char* vcTargetsDir = this->GetCustomVCTargetsPath()) {
+    mf->AddDefinition("CMAKE_VS_PLATFORM_TOOLSET_VCTARGETS_CUSTOM_DIR",
+                      vcTargetsDir);
+  }
+
   return true;
 }
 
@@ -446,6 +461,11 @@ bool cmGlobalVisualStudio10Generator::ProcessGeneratorToolsetField(
     this->GeneratorToolsetVersion = value;
     return true;
   }
+  if (key == "VCTargetsPath") {
+    this->CustomVCTargetsPath = value;
+    ConvertToWindowsSlashes(this->CustomVCTargetsPath);
+    return true;
+  }
   return false;
 }
 
@@ -607,6 +627,14 @@ void cmGlobalVisualStudio10Generator::EnableLanguage(
   cmGlobalVisualStudio8Generator::EnableLanguage(lang, mf, optional);
 }
 
+const char* cmGlobalVisualStudio10Generator::GetCustomVCTargetsPath() const
+{
+  if (this->CustomVCTargetsPath.empty()) {
+    return nullptr;
+  }
+  return this->CustomVCTargetsPath.c_str();
+}
+
 const char* cmGlobalVisualStudio10Generator::GetPlatformToolset() const
 {
   std::string const& toolset = this->GetPlatformToolsetString();

+ 5 - 0
Source/cmGlobalVisualStudio10Generator.h

@@ -46,6 +46,9 @@ public:
   bool IsNsightTegra() const;
   std::string GetNsightTegraVersion() const;
 
+  /** The vctargets path for the target platform.  */
+  const char* GetCustomVCTargetsPath() const;
+
   /** The toolset name for the target platform.  */
   const char* GetPlatformToolset() const;
   std::string const& GetPlatformToolsetString() const;
@@ -156,6 +159,7 @@ protected:
   std::string GeneratorToolset;
   std::string GeneratorToolsetVersion;
   std::string GeneratorToolsetHostArchitecture;
+  std::string GeneratorToolsetCustomVCTargetsDir;
   std::string GeneratorToolsetCuda;
   std::string GeneratorToolsetCudaCustomDir;
   std::string DefaultPlatformToolset;
@@ -207,6 +211,7 @@ private:
 
   bool ParseGeneratorToolset(std::string const& ts, cmMakefile* mf);
 
+  std::string CustomVCTargetsPath;
   std::string VCTargetsPath;
   bool FindVCTargetsPath(cmMakefile* mf);
 

+ 5 - 0
Source/cmVisualStudio10TargetGenerator.cxx

@@ -543,6 +543,11 @@ void cmVisualStudio10TargetGenerator::Generate()
         e1.Element("VCProjectUpgraderObjectName", "NoUpgrade");
       }
 
+      if (const char* vcTargetsPath =
+            this->GlobalGenerator->GetCustomVCTargetsPath()) {
+        e1.Element("VCTargetsPath", vcTargetsPath);
+      }
+
       std::vector<std::string> keys = this->GeneratorTarget->GetPropertyKeys();
       for (std::string const& keyIt : keys) {
         static const char* prefix = "VS_GLOBAL_";

+ 2 - 0
Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake

@@ -30,6 +30,8 @@ if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[012456]")
     set(RunCMake_GENERATOR_TOOLSET "Test Toolset,host=x64,host=x86")
     run_cmake(BadToolsetHostArchTwice)
     if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[56]")
+      set(RunCMake_GENERATOR_TOOLSET "VCTargetsPath=Test Path")
+      run_cmake(TestToolsetVCTargetsPathOnly)
       set(RunCMake_GENERATOR_TOOLSET "Test Toolset,version=Test Toolset Version")
       run_cmake(TestToolsetVersionBoth)
       set(RunCMake_GENERATOR_TOOLSET ",version=Test Toolset Version")

+ 2 - 0
Tests/RunCMake/GeneratorToolset/TestToolsetVCTargetsPathOnly-stdout.txt

@@ -0,0 +1,2 @@
+-- CMAKE_VS_PLATFORM_TOOLSET='v[0-9]+'
+-- CMAKE_VS_PLATFORM_TOOLSET_VCTARGETS_CUSTOM_DIR='Test Path'

+ 2 - 0
Tests/RunCMake/GeneratorToolset/TestToolsetVCTargetsPathOnly.cmake

@@ -0,0 +1,2 @@
+message(STATUS "CMAKE_VS_PLATFORM_TOOLSET='${CMAKE_VS_PLATFORM_TOOLSET}'")
+message(STATUS "CMAKE_VS_PLATFORM_TOOLSET_VCTARGETS_CUSTOM_DIR='${CMAKE_VS_PLATFORM_TOOLSET_VCTARGETS_CUSTOM_DIR}'")

+ 4 - 0
Tests/RunCMake/VS10Project/RunCMakeTest.cmake

@@ -28,6 +28,10 @@ run_cmake(VsDpiAwareBadParam)
 run_cmake(VsPrecompileHeaders)
 run_cmake(VsPrecompileHeadersReuseFromCompilePDBName)
 
+set(RunCMake_GENERATOR_TOOLSET "VCTargetsPath=$(VCTargetsPath)")
+run_cmake(VsVCTargetsPath)
+unset(RunCMake_GENERATOR_TOOLSET)
+
 if(CMAKE_C_COMPILER_ID STREQUAL "MSVC" AND CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 19.05)
   run_cmake(VsJustMyCode)
 endif()

+ 32 - 0
Tests/RunCMake/VS10Project/VsVCTargetsPath-check.cmake

@@ -0,0 +1,32 @@
+macro(check_project_file projectFile)
+  set(insideGlobals FALSE)
+  set(pathFound FALSE)
+
+  if(NOT EXISTS "${projectFile}")
+    set(RunCMake_TEST_FAILED "Project file ${projectFile} does not exist.")
+    return()
+  endif()
+
+  string(REPLACE "${RunCMake_TEST_BINARY_DIR}/" "" projectName ${projectFile})
+
+  file(STRINGS "${projectFile}" lines)
+  foreach(line IN LISTS lines)
+    if(line MATCHES "^ *<PropertyGroup Label=\"Globals\">.*$")
+      set(insideGlobals TRUE)
+    elseif(insideGlobals)
+      if(line MATCHES "^ *</PropertyGroup>.*$")
+        set(insideGlobals FALSE)
+      elseif(line MATCHES "^ *<VCTargetsPath>(.+)</VCTargetsPath>*$")
+        message(STATUS "Found VCTargetsPath = ${CMAKE_MATCH_1} in PropertyGroup 'Globals' in ${projectName}")
+        set(pathFound TRUE)
+      endif()
+    endif()
+  endforeach()
+  if(NOT pathFound)
+    set(RunCMake_TEST_FAILED "VCTargetsPath not found in \"Globals\" propertygroup in ${projectName}")
+    return() # This should intentionally return from the caller, not the macro
+  endif()
+endmacro()
+
+check_project_file("${RunCMake_TEST_BINARY_DIR}/CMakeFiles/${CMAKE_VERSION}/CompilerIdCXX/CompilerIdCXX.vcxproj")
+check_project_file("${RunCMake_TEST_BINARY_DIR}/foo.vcxproj")

+ 3 - 0
Tests/RunCMake/VS10Project/VsVCTargetsPath.cmake

@@ -0,0 +1,3 @@
+enable_language(CXX)
+
+add_library(foo foo.cpp)