1
0
Эх сурвалжийг харах

VS: Add support to override VCTargetsPath through toolset

Fixes: #19708
Alexander Boczar 6 жил өмнө
parent
commit
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
   Specify the toolset version to use.  Supported by VS 2017
   and above with the specified toolset installed.
   and above with the specified toolset installed.
   See the :variable:`CMAKE_VS_PLATFORM_TOOLSET_VERSION` variable.
   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)
     if(CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION)
       set(id_WindowsTargetPlatformVersion "<WindowsTargetPlatformVersion>${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}</WindowsTargetPlatformVersion>")
       set(id_WindowsTargetPlatformVersion "<WindowsTargetPlatformVersion>${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}</WindowsTargetPlatformVersion>")
     endif()
     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)
     if(id_platform STREQUAL ARM64)
       set(id_WindowsSDKDesktopARMSupport "<WindowsSDKDesktopARM64Support>true</WindowsSDKDesktopARM64Support>")
       set(id_WindowsSDKDesktopARMSupport "<WindowsSDKDesktopARM64Support>true</WindowsSDKDesktopARM64Support>")
     elseif(id_platform STREQUAL ARM)
     elseif(id_platform STREQUAL ARM)

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

@@ -15,6 +15,7 @@
     @id_WindowsTargetPlatformVersion@
     @id_WindowsTargetPlatformVersion@
     @id_WindowsSDKDesktopARMSupport@
     @id_WindowsSDKDesktopARMSupport@
     @id_CudaToolkitCustomDir@
     @id_CudaToolkitCustomDir@
+    @id_ToolsetVCTargetsDir@
   </PropertyGroup>
   </PropertyGroup>
   @id_toolset_version_props@
   @id_toolset_version_props@
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.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 const char vs10generatorName[] = "Visual Studio 10 2010";
 static std::map<std::string, std::vector<cmIDEFlagTable>> loadedFlagJsonFiles;
 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.
 // Map generator name without year to name with year.
 static const char* cmVS10GenName(const std::string& name, std::string& genName)
 static const char* cmVS10GenName(const std::string& name, std::string& genName)
 {
 {
@@ -212,7 +222,7 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorToolset(
     return true;
     return true;
   }
   }
 
 
-  if (!this->FindVCTargetsPath(mf)) {
+  if (this->CustomVCTargetsPath.empty() && !this->FindVCTargetsPath(mf)) {
     return false;
     return false;
   }
   }
 
 
@@ -353,6 +363,11 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorToolset(
   if (const char* cudaDir = this->GetPlatformToolsetCudaCustomDir()) {
   if (const char* cudaDir = this->GetPlatformToolsetCudaCustomDir()) {
     mf->AddDefinition("CMAKE_VS_PLATFORM_TOOLSET_CUDA_CUSTOM_DIR", cudaDir);
     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;
   return true;
 }
 }
 
 
@@ -446,6 +461,11 @@ bool cmGlobalVisualStudio10Generator::ProcessGeneratorToolsetField(
     this->GeneratorToolsetVersion = value;
     this->GeneratorToolsetVersion = value;
     return true;
     return true;
   }
   }
+  if (key == "VCTargetsPath") {
+    this->CustomVCTargetsPath = value;
+    ConvertToWindowsSlashes(this->CustomVCTargetsPath);
+    return true;
+  }
   return false;
   return false;
 }
 }
 
 
@@ -607,6 +627,14 @@ void cmGlobalVisualStudio10Generator::EnableLanguage(
   cmGlobalVisualStudio8Generator::EnableLanguage(lang, mf, optional);
   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
 const char* cmGlobalVisualStudio10Generator::GetPlatformToolset() const
 {
 {
   std::string const& toolset = this->GetPlatformToolsetString();
   std::string const& toolset = this->GetPlatformToolsetString();

+ 5 - 0
Source/cmGlobalVisualStudio10Generator.h

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

+ 5 - 0
Source/cmVisualStudio10TargetGenerator.cxx

@@ -543,6 +543,11 @@ void cmVisualStudio10TargetGenerator::Generate()
         e1.Element("VCProjectUpgraderObjectName", "NoUpgrade");
         e1.Element("VCProjectUpgraderObjectName", "NoUpgrade");
       }
       }
 
 
+      if (const char* vcTargetsPath =
+            this->GlobalGenerator->GetCustomVCTargetsPath()) {
+        e1.Element("VCTargetsPath", vcTargetsPath);
+      }
+
       std::vector<std::string> keys = this->GeneratorTarget->GetPropertyKeys();
       std::vector<std::string> keys = this->GeneratorTarget->GetPropertyKeys();
       for (std::string const& keyIt : keys) {
       for (std::string const& keyIt : keys) {
         static const char* prefix = "VS_GLOBAL_";
         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")
     set(RunCMake_GENERATOR_TOOLSET "Test Toolset,host=x64,host=x86")
     run_cmake(BadToolsetHostArchTwice)
     run_cmake(BadToolsetHostArchTwice)
     if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[56]")
     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")
       set(RunCMake_GENERATOR_TOOLSET "Test Toolset,version=Test Toolset Version")
       run_cmake(TestToolsetVersionBoth)
       run_cmake(TestToolsetVersionBoth)
       set(RunCMake_GENERATOR_TOOLSET ",version=Test Toolset Version")
       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(VsPrecompileHeaders)
 run_cmake(VsPrecompileHeadersReuseFromCompilePDBName)
 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)
 if(CMAKE_C_COMPILER_ID STREQUAL "MSVC" AND CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 19.05)
   run_cmake(VsJustMyCode)
   run_cmake(VsJustMyCode)
 endif()
 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)