Explorar el Código

Merge topic 'vs-vctargetspath'

e7d57bc3c3 VS: Propagate CMAKE_VS_GLOBALS into custom targets
45b4b4b930 VS: Propagate CMAKE_VS_GLOBALS into compiler id projects
548e9051a4 VS: Add support to override VCTargetsPath through toolset
99e83d4235 cmake: Teach --build mode to load CMAKE_GENERATOR_TOOLSET

Acked-by: Kitware Robot <[email protected]>
Merge-request: !3817
Brad King hace 6 años
padre
commit
b34b4c5eac

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

@@ -0,0 +1,10 @@
+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.
+
+* The :variable:`CMAKE_VS_GLOBALS` variable value now applies during
+  compiler identification and in targets created by the
+  :command:`add_custom_target` command.

+ 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.

+ 9 - 0
Modules/CMakeDetermineCompilerId.cmake

@@ -317,6 +317,15 @@ 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()
+    set(id_CustomGlobals "")
+    foreach(pair IN LISTS CMAKE_VS_GLOBALS)
+      if("${pair}" MATCHES "([^=]+)=(.*)$")
+        string(APPEND id_CustomGlobals "<${CMAKE_MATCH_1}>${CMAKE_MATCH_2}</${CMAKE_MATCH_1}>\n    ")
+      endif()
+    endforeach()
     if(id_platform STREQUAL ARM64)
       set(id_WindowsSDKDesktopARMSupport "<WindowsSDKDesktopARM64Support>true</WindowsSDKDesktopARM64Support>")
     elseif(id_platform STREQUAL ARM)

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

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

+ 2 - 2
Source/cmGlobalGenerator.cxx

@@ -165,7 +165,7 @@ bool cmGlobalGenerator::SetGeneratorPlatform(std::string const& p,
   return false;
 }
 
-bool cmGlobalGenerator::SetGeneratorToolset(std::string const& ts,
+bool cmGlobalGenerator::SetGeneratorToolset(std::string const& ts, bool,
                                             cmMakefile* mf)
 {
   if (ts.empty()) {
@@ -650,7 +650,7 @@ void cmGlobalGenerator::EnableLanguage(
 
     // Tell the generator about the toolset, if any.
     std::string toolset = mf->GetSafeDefinition("CMAKE_GENERATOR_TOOLSET");
-    if (!this->SetGeneratorToolset(toolset, mf)) {
+    if (!this->SetGeneratorToolset(toolset, false, mf)) {
       cmSystemTools::SetFatalErrorOccured();
       return;
     }

+ 2 - 1
Source/cmGlobalGenerator.h

@@ -128,7 +128,8 @@ public:
 
   /** Set the generator-specific toolset name.  Returns true if toolset
       is supported and false otherwise.  */
-  virtual bool SetGeneratorToolset(std::string const& ts, cmMakefile* mf);
+  virtual bool SetGeneratorToolset(std::string const& ts, bool build,
+                                   cmMakefile* mf);
 
   /**
    * Create LocalGenerators and process the CMakeLists files. This does not

+ 4 - 1
Source/cmGlobalGhsMultiGenerator.cxx

@@ -64,8 +64,11 @@ void cmGlobalGhsMultiGenerator::ComputeTargetObjectDirectory(
 }
 
 bool cmGlobalGhsMultiGenerator::SetGeneratorToolset(std::string const& ts,
-                                                    cmMakefile* mf)
+                                                    bool build, cmMakefile* mf)
 {
+  if (build) {
+    return true;
+  }
   std::string tsp; /* toolset path */
 
   this->GetToolset(mf, tsp, ts);

+ 2 - 1
Source/cmGlobalGhsMultiGenerator.h

@@ -58,7 +58,8 @@ public:
   static bool SupportsPlatform() { return true; }
 
   // Toolset / Platform Support
-  bool SetGeneratorToolset(std::string const& ts, cmMakefile* mf) override;
+  bool SetGeneratorToolset(std::string const& ts, bool build,
+                           cmMakefile* mf) override;
   bool SetGeneratorPlatform(std::string const& p, cmMakefile* mf) override;
 
   /**

+ 34 - 2
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)
 {
@@ -193,7 +203,7 @@ static void cmCudaToolVersion(std::string& s)
 }
 
 bool cmGlobalVisualStudio10Generator::SetGeneratorToolset(
-  std::string const& ts, cmMakefile* mf)
+  std::string const& ts, bool build, cmMakefile* mf)
 {
   if (this->SystemIsWindowsCE && ts.empty() &&
       this->DefaultPlatformToolset.empty()) {
@@ -208,7 +218,11 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorToolset(
     return false;
   }
 
-  if (!this->FindVCTargetsPath(mf)) {
+  if (build) {
+    return true;
+  }
+
+  if (this->CustomVCTargetsPath.empty() && !this->FindVCTargetsPath(mf)) {
     return false;
   }
 
@@ -349,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;
 }
 
@@ -442,6 +461,11 @@ bool cmGlobalVisualStudio10Generator::ProcessGeneratorToolsetField(
     this->GeneratorToolsetVersion = value;
     return true;
   }
+  if (key == "VCTargetsPath") {
+    this->CustomVCTargetsPath = value;
+    ConvertToWindowsSlashes(this->CustomVCTargetsPath);
+    return true;
+  }
   return false;
 }
 
@@ -603,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();

+ 7 - 1
Source/cmGlobalVisualStudio10Generator.h

@@ -20,7 +20,8 @@ public:
 
   bool SetSystemName(std::string const& s, cmMakefile* mf) override;
   bool SetGeneratorPlatform(std::string const& p, cmMakefile* mf) override;
-  bool SetGeneratorToolset(std::string const& ts, cmMakefile* mf) override;
+  bool SetGeneratorToolset(std::string const& ts, bool build,
+                           cmMakefile* mf) override;
 
   std::vector<GeneratedMakeCommand> GenerateBuildCommand(
     const std::string& makeProgram, const std::string& projectName,
@@ -45,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;
@@ -155,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;
@@ -206,6 +211,7 @@ private:
 
   bool ParseGeneratorToolset(std::string const& ts, cmMakefile* mf);
 
+  std::string CustomVCTargetsPath;
   std::string VCTargetsPath;
   bool FindVCTargetsPath(cmMakefile* mf);
 

+ 4 - 1
Source/cmGlobalXCodeGenerator.cxx

@@ -267,7 +267,7 @@ std::string cmGlobalXCodeGenerator::FindXcodeBuildCommand()
 }
 
 bool cmGlobalXCodeGenerator::SetGeneratorToolset(std::string const& ts,
-                                                 cmMakefile* mf)
+                                                 bool build, cmMakefile* mf)
 {
   if (ts.find_first_of(",=") != std::string::npos) {
     std::ostringstream e;
@@ -283,6 +283,9 @@ bool cmGlobalXCodeGenerator::SetGeneratorToolset(std::string const& ts,
     return false;
   }
   this->GeneratorToolset = ts;
+  if (build) {
+    return true;
+  }
   if (!this->GeneratorToolset.empty()) {
     mf->AddDefinition("CMAKE_XCODE_PLATFORM_TOOLSET", this->GeneratorToolset);
   }

+ 2 - 1
Source/cmGlobalXCodeGenerator.h

@@ -103,7 +103,8 @@ public:
 
   bool ShouldStripResourcePath(cmMakefile*) const override;
 
-  bool SetGeneratorToolset(std::string const& ts, cmMakefile* mf) override;
+  bool SetGeneratorToolset(std::string const& ts, bool build,
+                           cmMakefile* mf) override;
   void AppendFlag(std::string& flags, std::string const& flag) const;
 
 protected:

+ 1 - 2
Source/cmTarget.cxx

@@ -511,8 +511,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
     initProp("DOTNET_TARGET_FRAMEWORK_VERSION");
   }
 
-  if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
-      this->GetType() != cmStateEnums::UTILITY) {
+  if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
 
     // check for "CMAKE_VS_GLOBALS" variable and set up target properties
     // if any

+ 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_";

+ 8 - 0
Source/cmake.cxx

@@ -2619,6 +2619,14 @@ int cmake::Build(int jobs, const std::string& dir,
       return 1;
     }
   }
+  const char* cachedGeneratorToolset =
+    this->State->GetCacheEntryValue("CMAKE_GENERATOR_TOOLSET");
+  if (cachedGeneratorToolset) {
+    cmMakefile mf(gen, this->GetCurrentSnapshot());
+    if (!gen->SetGeneratorToolset(cachedGeneratorToolset, true, &mf)) {
+      return 1;
+    }
+  }
   std::string output;
   std::string projName;
   const char* cachedProjectName =

+ 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

@@ -29,6 +29,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()

+ 57 - 36
Tests/RunCMake/VS10Project/VsGlobals-check.cmake

@@ -1,44 +1,65 @@
-set(vcProjectFile "${RunCMake_TEST_BINARY_DIR}/foo.vcxproj")
-if(NOT EXISTS "${vcProjectFile}")
-  set(RunCMake_TEST_FAILED "Project file ${vcProjectFile} does not exist.")
-  return()
-endif()
+macro(check_project_file projectFile)
+  if(NOT EXISTS "${projectFile}")
+    set(RunCMake_TEST_FAILED "Project file ${projectFile} does not exist.")
+    return()
+  endif()
+
+  string(REPLACE "${RunCMake_TEST_BINARY_DIR}/" "" projectName ${projectFile})
 
-set(InsideGlobals FALSE)
-set(DefaultLanguageSet FALSE)
-set(MinimumVisualStudioVersionSet FALSE)
+  set(InsideGlobals FALSE)
+  set(DefaultLanguageSet FALSE)
+  set(MinimumVisualStudioVersionSet FALSE)
+  set(TestPropertySet FALSE)
 
-file(STRINGS "${vcProjectFile}" lines)
-foreach(line IN LISTS lines)
-  if(line MATCHES "^ *<PropertyGroup Label=\"Globals\"> *$")
-    set(InsideGlobals TRUE)
-  elseif(line MATCHES "^ *<DefaultLanguage>([a-zA-Z\\-]+)</DefaultLanguage> *$")
-    if("${CMAKE_MATCH_1}" STREQUAL "en-US")
-      if(InsideGlobals)
-        message(STATUS "foo.vcxproj has correct DefaultLanguage global property")
-        set(DefaultLanguageSet TRUE)
-      else()
-        message(STATUS "DefaultLanguage is set but not within \"Globals\" property group")
+  file(STRINGS "${projectFile}" lines)
+  foreach(line IN LISTS lines)
+    if(line MATCHES "^ *<PropertyGroup Label=\"Globals\"> *$")
+      set(InsideGlobals TRUE)
+    elseif(line MATCHES "^ *<DefaultLanguage>([a-zA-Z\\-]+)</DefaultLanguage> *$")
+      if("${CMAKE_MATCH_1}" STREQUAL "en-US")
+        if(InsideGlobals)
+          message(STATUS "${projectName} has correct DefaultLanguage global property")
+          set(DefaultLanguageSet TRUE)
+        else()
+          message(STATUS "DefaultLanguage is set but not within \"Globals\" property group")
+        endif()
       endif()
-    endif()
-  elseif(line MATCHES "^ *<MinimumVisualStudioVersion>([0-9\\.]+)</MinimumVisualStudioVersion> *$")
-    if("${CMAKE_MATCH_1}" STREQUAL "14.0")
-      if(InsideGlobals)
-        message(STATUS "foo.vcxproj has correct MinimumVisualStudioVersion global property")
-        set(MinimumVisualStudioVersionSet TRUE)
-      else()
-        message(STATUS "MinimumVisualStudioVersion is set but not within \"Globals\" property group")
+    elseif(line MATCHES "^ *<MinimumVisualStudioVersion>([0-9\\.]+)</MinimumVisualStudioVersion> *$")
+      if("${CMAKE_MATCH_1}" STREQUAL "10.0")
+        if(InsideGlobals)
+          message(STATUS "${projectName} has correct MinimumVisualStudioVersion global property")
+          set(MinimumVisualStudioVersionSet TRUE)
+        else()
+          message(STATUS "MinimumVisualStudioVersion is set but not within \"Globals\" property group")
+        endif()
+      endif()
+    elseif(line MATCHES "^ *<TestProperty>(.+)</TestProperty> *$")
+      if("${CMAKE_MATCH_1}" STREQUAL "TestValue")
+        if(InsideGlobals)
+          message(STATUS "${projectName} has correct TestProperty global property")
+          set(TestPropertySet TRUE)
+        else()
+          message(STATUS "TestProperty is set but not within \"Globals\" property group")
+        endif()
       endif()
     endif()
+  endforeach()
+
+  if(NOT DefaultLanguageSet)
+    set(RunCMake_TEST_FAILED "DefaultLanguage not found or not set correctly in ${projectName}.")
+    return()
+  endif()
+
+  if(NOT MinimumVisualStudioVersionSet)
+    set(RunCMake_TEST_FAILED "MinimumVisualStudioVersion not found or not set correctly in ${projectName}.")
+    return()
   endif()
-endforeach()
 
-if(NOT DefaultLanguageSet)
-  set(RunCMake_TEST_FAILED "DefaultLanguageSet not found or not set correctly.")
-  return()
-endif()
+  if(NOT TestPropertySet)
+    set(RunCMake_TEST_FAILED "TestProperty not found or not set correctly in ${projectName}.")
+    return()
+  endif()
+endmacro()
 
-if(NOT MinimumVisualStudioVersionSet)
-  set(RunCMake_TEST_FAILED "MinimumVisualStudioVersionSet not found or not set correctly.")
-  return()
-endif()
+check_project_file("${RunCMake_TEST_BINARY_DIR}/CMakeFiles/${CMAKE_VERSION}/CompilerIdCXX/CompilerIdCXX.vcxproj")
+check_project_file("${RunCMake_TEST_BINARY_DIR}/foo.vcxproj")

+ 4 - 3
Tests/RunCMake/VS10Project/VsGlobals.cmake

@@ -1,8 +1,9 @@
-enable_language(CXX)
-
 set(CMAKE_VS_GLOBALS
     "DefaultLanguage=en-US"
-    "MinimumVisualStudioVersion=14.0"
+    "MinimumVisualStudioVersion=10.0"
+    "TestProperty=TestValue"
 )
 
+enable_language(CXX)
+
 add_library(foo foo.cpp)

+ 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)