Browse Source

Merge topic 'vs-framework-version' into release-3.22

d51246c662 VS: Default TargetFrameworkVersion to v4.7.2 for VS 2022
f97f8537f3 VS: Model a default target framework
e40cedddc0 cmVisualStudio10TargetGenerator: Refactor target framework selection
78782cc7dc cmGlobalVisualStudio8Generator: Refactor SetGeneratorPlatform

Acked-by: Kitware Robot <[email protected]>
Merge-request: !6699
Brad King 4 years ago
parent
commit
2b9b64269f

+ 3 - 0
Help/manual/cmake-variables.7.rst

@@ -125,6 +125,9 @@ Variables that Provide Information
    /variable/CMAKE_VS_PLATFORM_TOOLSET_CUDA_CUSTOM_DIR
    /variable/CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE
    /variable/CMAKE_VS_PLATFORM_TOOLSET_VERSION
+   /variable/CMAKE_VS_TARGET_FRAMEWORK_VERSION
+   /variable/CMAKE_VS_TARGET_FRAMEWORK_IDENTIFIER
+   /variable/CMAKE_VS_TARGET_FRAMEWORK_TARGETS_VERSION
    /variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION
    /variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION_MAXIMUM
    /variable/CMAKE_XCODE_BUILD_SYSTEM

+ 13 - 0
Help/variable/CMAKE_VS_TARGET_FRAMEWORK_IDENTIFIER.rst

@@ -0,0 +1,13 @@
+CMAKE_VS_TARGET_FRAMEWORK_IDENTIFIER
+------------------------------------
+
+.. versionadded:: 3.22
+
+Visual Studio target framework identifier.
+
+In some cases, the :ref:`Visual Studio Generators` may use an explicit value
+for the MSBuild ``TargetFrameworkIdentifier`` setting in ``.csproj`` files.
+CMake provides the chosen value in this variable.
+
+See also :variable:`CMAKE_VS_TARGET_FRAMEWORK_VERSION` and
+:variable:`CMAKE_VS_TARGET_FRAMEWORK_TARGETS_VERSION`.

+ 13 - 0
Help/variable/CMAKE_VS_TARGET_FRAMEWORK_TARGETS_VERSION.rst

@@ -0,0 +1,13 @@
+CMAKE_VS_TARGET_FRAMEWORK_TARGETS_VERSION
+-----------------------------------------
+
+.. versionadded:: 3.22
+
+Visual Studio target framework targets version.
+
+In some cases, the :ref:`Visual Studio Generators` may use an explicit value
+for the MSBuild ``TargetFrameworkTargetsVersion`` setting in ``.csproj`` files.
+CMake provides the chosen value in this variable.
+
+See also :variable:`CMAKE_VS_TARGET_FRAMEWORK_VERSION` and
+:variable:`CMAKE_VS_TARGET_FRAMEWORK_IDENTIFIER`.

+ 17 - 0
Help/variable/CMAKE_VS_TARGET_FRAMEWORK_VERSION.rst

@@ -0,0 +1,17 @@
+CMAKE_VS_TARGET_FRAMEWORK_VERSION
+---------------------------------
+
+.. versionadded:: 3.22
+
+Visual Studio target framework version.
+
+In some cases, the :ref:`Visual Studio Generators` may use an explicit value
+for the MSBuild ``TargetFrameworkVersion`` setting in ``.csproj`` files.
+CMake provides the chosen value in this variable.
+
+See the :variable:`CMAKE_DOTNET_TARGET_FRAMEWORK_VERSION` variable
+and :prop_tgt:`DOTNET_TARGET_FRAMEWORK_VERSION` target property to
+specify custom ``TargetFrameworkVersion`` values for project targets.
+
+See also :variable:`CMAKE_VS_TARGET_FRAMEWORK_IDENTIFIER` and
+:variable:`CMAKE_VS_TARGET_FRAMEWORK_TARGETS_VERSION`.

+ 9 - 0
Modules/CMakeDetermineCompilerId.cmake

@@ -421,6 +421,15 @@ Id flags: ${testflags} ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS}
     if(CMAKE_VS_PLATFORM_TOOLSET_VCTARGETS_CUSTOM_DIR)
       set(id_ToolsetVCTargetsDir "<VCTargetsPath>${CMAKE_VS_PLATFORM_TOOLSET_VCTARGETS_CUSTOM_DIR}</VCTargetsPath>")
     endif()
+    if(CMAKE_VS_TARGET_FRAMEWORK_VERSION)
+      set(id_TargetFrameworkVersion "<TargetFrameworkVersion>${CMAKE_VS_TARGET_FRAMEWORK_VERSION}</TargetFrameworkVersion>")
+    endif()
+    if(CMAKE_VS_TARGET_FRAMEWORK_IDENTIFIER)
+      set(id_TargetFrameworkIdentifier "<TargetFrameworkIdentifier>${CMAKE_VS_TARGET_FRAMEWORK_IDENTIFIER}</TargetFrameworkIdentifier>")
+    endif()
+    if(CMAKE_VS_TARGET_FRAMEWORK_TARGETS_VERSION)
+      set(id_TargetFrameworkTargetsVersion "<TargetFrameworkTargetsVersion>${CMAKE_VS_TARGET_FRAMEWORK_TARGETS_VERSION}</TargetFrameworkTargetsVersion>")
+    endif()
     set(id_CustomGlobals "")
     foreach(pair IN LISTS CMAKE_VS_GLOBALS)
       if("${pair}" MATCHES "([^=]+)=(.*)$")

+ 3 - 0
Modules/CompilerId/VS-10.csproj.in

@@ -6,6 +6,9 @@
     <Keyword>Win32Proj</Keyword>
     @id_system@
     @id_system_version@
+    @id_TargetFrameworkVersion@
+    @id_TargetFrameworkIdentifier@
+    @id_TargetFrameworkTargetsVersion@
     @id_WindowsTargetPlatformVersion@
     @id_WindowsSDKDesktopARMSupport@
   </PropertyGroup>

+ 7 - 0
Source/cmGlobalVisualStudio10Generator.cxx

@@ -580,6 +580,13 @@ bool cmGlobalVisualStudio10Generator::InitializeWindowsCE(cmMakefile* mf)
 
   this->DefaultPlatformToolset = this->SelectWindowsCEToolset();
 
+  if (this->GetVersion() == cmGlobalVisualStudioGenerator::VS12) {
+    // VS 12 .NET CF defaults to .NET framework 3.9 for Windows CE.
+    this->DefaultTargetFrameworkVersion = "v3.9";
+    this->DefaultTargetFrameworkIdentifier = "WindowsEmbeddedCompact";
+    this->DefaultTargetFrameworkTargetsVersion = "v8.0";
+  }
+
   return true;
 }
 

+ 47 - 4
Source/cmGlobalVisualStudio8Generator.cxx

@@ -67,12 +67,55 @@ void cmGlobalVisualStudio8Generator::AddPlatformDefinitions(cmMakefile* mf)
 bool cmGlobalVisualStudio8Generator::SetGeneratorPlatform(std::string const& p,
                                                           cmMakefile* mf)
 {
-  if (!this->PlatformInGeneratorName) {
-    this->GeneratorPlatform = p;
-    return this->cmGlobalVisualStudio7Generator::SetGeneratorPlatform("", mf);
-  } else {
+  if (this->PlatformInGeneratorName) {
+    // This is an old-style generator name that contains the platform name.
+    // No explicit platform specification is supported, so pass it through
+    // to our base class implementation, which errors on non-empty platforms.
     return this->cmGlobalVisualStudio7Generator::SetGeneratorPlatform(p, mf);
   }
+
+  this->GeneratorPlatform = p;
+
+  // FIXME: Add CMAKE_GENERATOR_PLATFORM field to set the framework.
+  // For now, just report the generator's default, if any.
+  if (cm::optional<std::string> const& targetFrameworkVersion =
+        this->GetTargetFrameworkVersion()) {
+    mf->AddDefinition("CMAKE_VS_TARGET_FRAMEWORK_VERSION",
+                      *targetFrameworkVersion);
+  }
+  if (cm::optional<std::string> const& targetFrameworkIdentifier =
+        this->GetTargetFrameworkIdentifier()) {
+    mf->AddDefinition("CMAKE_VS_TARGET_FRAMEWORK_IDENTIFIER",
+                      *targetFrameworkIdentifier);
+  }
+  if (cm::optional<std::string> const& targetFrameworkTargetsVersion =
+        this->GetTargetFrameworkTargetsVersion()) {
+    mf->AddDefinition("CMAKE_VS_TARGET_FRAMEWORK_TARGETS_VERSION",
+                      *targetFrameworkTargetsVersion);
+  }
+
+  // The generator name does not contain the platform name, and so supports
+  // explicit platform specification.  We handled that above, so pass an
+  // empty platform name to our base class implementation so it does not error.
+  return this->cmGlobalVisualStudio7Generator::SetGeneratorPlatform("", mf);
+}
+
+cm::optional<std::string> const&
+cmGlobalVisualStudio8Generator::GetTargetFrameworkVersion() const
+{
+  return this->DefaultTargetFrameworkVersion;
+}
+
+cm::optional<std::string> const&
+cmGlobalVisualStudio8Generator::GetTargetFrameworkIdentifier() const
+{
+  return this->DefaultTargetFrameworkIdentifier;
+}
+
+cm::optional<std::string> const&
+cmGlobalVisualStudio8Generator::GetTargetFrameworkTargetsVersion() const
+{
+  return this->DefaultTargetFrameworkTargetsVersion;
 }
 
 std::string cmGlobalVisualStudio8Generator::GetGenerateStampList()

+ 10 - 0
Source/cmGlobalVisualStudio8Generator.h

@@ -2,6 +2,8 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #pragma once
 
+#include <cm/optional>
+
 #include "cmGlobalVisualStudio71Generator.h"
 
 /** \class cmGlobalVisualStudio8Generator
@@ -24,6 +26,10 @@ public:
 
   bool SetGeneratorPlatform(std::string const& p, cmMakefile* mf) override;
 
+  cm::optional<std::string> const& GetTargetFrameworkVersion() const;
+  cm::optional<std::string> const& GetTargetFrameworkIdentifier() const;
+  cm::optional<std::string> const& GetTargetFrameworkTargetsVersion() const;
+
   /**
    * Override Configure and Generate to add the build-system check
    * target.
@@ -76,4 +82,8 @@ protected:
 
   std::string Name;
   std::string WindowsCEVersion;
+
+  cm::optional<std::string> DefaultTargetFrameworkVersion;
+  cm::optional<std::string> DefaultTargetFrameworkIdentifier;
+  cm::optional<std::string> DefaultTargetFrameworkTargetsVersion;
 };

+ 6 - 0
Source/cmGlobalVisualStudioVersionedGenerator.cxx

@@ -401,6 +401,12 @@ cmGlobalVisualStudioVersionedGenerator::cmGlobalVisualStudioVersionedGenerator(
     this->DefaultPlatformName = VSHostPlatformName();
     this->DefaultPlatformToolsetHostArchitecture = VSHostArchitecture();
   }
+  if (this->Version >= cmGlobalVisualStudioGenerator::VS17) {
+    // FIXME: Search for an existing framework?  Under '%ProgramFiles(x86)%',
+    // see 'Reference Assemblies\Microsoft\Framework\.NETFramework'.
+    // Use a version installed by VS 2022 without a separate component.
+    this->DefaultTargetFrameworkVersion = "v4.7.2";
+  }
 }
 
 bool cmGlobalVisualStudioVersionedGenerator::MatchesGeneratorName(

+ 54 - 35
Source/cmVisualStudio10TargetGenerator.cxx

@@ -6,6 +6,7 @@
 #include <set>
 
 #include <cm/memory>
+#include <cm/optional>
 #include <cm/string_view>
 #include <cm/vector>
 #include <cmext/algorithm>
@@ -492,50 +493,68 @@ void cmVisualStudio10TargetGenerator::Generate()
       cmValue projLabel = this->GeneratorTarget->GetProperty("PROJECT_LABEL");
       e1.Element("ProjectName", projLabel ? projLabel : this->Name);
       {
-        cmValue targetFramework =
-          this->GeneratorTarget->GetProperty("DOTNET_TARGET_FRAMEWORK");
+        cm::optional<std::string> targetFramework;
+        cm::optional<std::string> targetFrameworkVersion;
+        cm::optional<std::string> targetFrameworkIdentifier;
+        cm::optional<std::string> targetFrameworkTargetsVersion;
+        if (cmValue tf =
+              this->GeneratorTarget->GetProperty("DOTNET_TARGET_FRAMEWORK")) {
+          targetFramework = *tf;
+        } else if (cmValue vstfVer = this->GeneratorTarget->GetProperty(
+                     "VS_DOTNET_TARGET_FRAMEWORK_VERSION")) {
+          // FIXME: Someday, add a deprecation warning for VS_* property.
+          targetFrameworkVersion = *vstfVer;
+        } else if (cmValue tfVer = this->GeneratorTarget->GetProperty(
+                     "DOTNET_TARGET_FRAMEWORK_VERSION")) {
+          targetFrameworkVersion = *tfVer;
+        } else if (this->ProjectType == csproj) {
+          targetFrameworkVersion =
+            this->GlobalGenerator->GetTargetFrameworkVersion();
+        }
+        if (this->ProjectType == vcxproj &&
+            this->GlobalGenerator->TargetsWindowsCE()) {
+          e1.Element("EnableRedirectPlatform", "true");
+          e1.Element("RedirectPlatformValue", this->Platform);
+        }
+        if (this->ProjectType == csproj) {
+          if (this->GlobalGenerator->TargetsWindowsCE()) {
+            // FIXME: These target VS_TARGET_FRAMEWORK* target properties
+            // are undocumented settings only ever supported for WinCE.
+            // We need a better way to control these in general.
+            if (cmValue tfId = this->GeneratorTarget->GetProperty(
+                  "VS_TARGET_FRAMEWORK_IDENTIFIER")) {
+              targetFrameworkIdentifier = *tfId;
+            }
+            if (cmValue tfTargetsVer = this->GeneratorTarget->GetProperty(
+                  "VS_TARGET_FRAMEWORKS_TARGET_VERSION")) {
+              targetFrameworkTargetsVersion = *tfTargetsVer;
+            }
+          }
+          if (!targetFrameworkIdentifier) {
+            targetFrameworkIdentifier =
+              this->GlobalGenerator->GetTargetFrameworkIdentifier();
+          }
+          if (!targetFrameworkTargetsVersion) {
+            targetFrameworkTargetsVersion =
+              this->GlobalGenerator->GetTargetFrameworkTargetsVersion();
+          }
+        }
         if (targetFramework) {
           if (targetFramework->find(';') != std::string::npos) {
             e1.Element("TargetFrameworks", *targetFramework);
           } else {
             e1.Element("TargetFramework", *targetFramework);
           }
-        } else {
-          // TODO: add deprecation warning for VS_* property?
-          cmValue p = this->GeneratorTarget->GetProperty(
-            "VS_DOTNET_TARGET_FRAMEWORK_VERSION");
-          if (!p) {
-            p = this->GeneratorTarget->GetProperty(
-              "DOTNET_TARGET_FRAMEWORK_VERSION");
-          }
-          std::string targetFrameworkVersion = p;
-          if (targetFrameworkVersion.empty() && this->ProjectType == csproj &&
-              this->GlobalGenerator->TargetsWindowsCE() &&
-              this->GlobalGenerator->GetVersion() ==
-                cmGlobalVisualStudioGenerator::VS12) {
-            // VS12 .NETCF default to .NET framework 3.9
-            targetFrameworkVersion = "v3.9";
-          }
-          if (!targetFrameworkVersion.empty()) {
-            e1.Element("TargetFrameworkVersion", targetFrameworkVersion);
-          }
         }
-        if (this->ProjectType == vcxproj &&
-            this->GlobalGenerator->TargetsWindowsCE()) {
-          e1.Element("EnableRedirectPlatform", "true");
-          e1.Element("RedirectPlatformValue", this->Platform);
+        if (targetFrameworkVersion) {
+          e1.Element("TargetFrameworkVersion", *targetFrameworkVersion);
         }
-        if (this->ProjectType == csproj &&
-            this->GlobalGenerator->TargetsWindowsCE()) {
-          cmValue targetFrameworkId = this->GeneratorTarget->GetProperty(
-            "VS_TARGET_FRAMEWORK_IDENTIFIER");
-          e1.Element("TargetFrameworkIdentifier",
-                     targetFrameworkId ? *targetFrameworkId
-                                       : "WindowsEmbeddedCompact");
-          cmValue targetFrameworkVer = this->GeneratorTarget->GetProperty(
-            "VS_TARGET_FRAMEWORKS_TARGET_VERSION");
+        if (targetFrameworkIdentifier) {
+          e1.Element("TargetFrameworkIdentifier", *targetFrameworkIdentifier);
+        }
+        if (targetFrameworkTargetsVersion) {
           e1.Element("TargetFrameworkTargetsVersion",
-                     targetFrameworkVer ? *targetFrameworkVer : "v8.0");
+                     *targetFrameworkTargetsVersion);
         }
         if (!this->GlobalGenerator->GetPlatformToolsetCudaCustomDirString()
                .empty()) {