Browse Source

Merge topic 'dotnet_sdk' into release-3.23

5cdd774d51 VS: Handle build target correct for .NET SDK style projects with Any CPU
309191052c VS: Set Visual Studio versions read out from solution file
f7791698cb VS: Allow setting output directory in .NET SDK style projects

Acked-by: Kitware Robot <[email protected]>
Merge-request: !6944
Brad King 4 years ago
parent
commit
6e32db4fb3

+ 27 - 14
Source/cmGlobalVisualStudio10Generator.cxx

@@ -1134,7 +1134,7 @@ cmGlobalVisualStudio10Generator::GenerateBuildCommand(
     slnFile += ".sln";
     cmVisualStudioSlnParser parser;
     if (parser.ParseFile(slnFile, slnData,
-                         cmVisualStudioSlnParser::DataGroupProjects)) {
+                         cmVisualStudioSlnParser::DataGroupAll)) {
       std::vector<cmSlnProjectEntry> slnProjects = slnData.GetProjects();
       for (cmSlnProjectEntry const& project : slnProjects) {
         if (useDevEnv) {
@@ -1170,15 +1170,17 @@ cmGlobalVisualStudio10Generator::GenerateBuildCommand(
     GeneratedMakeCommand makeCommand;
     makeCommand.RequiresOutputForward = requiresOutputForward;
     makeCommand.Add(makeProgramSelected);
+    cm::optional<cmSlnProjectEntry> proj = cm::nullopt;
 
     if (tname == "clean") {
-      makeCommand.Add(std::string(projectName) + ".sln");
+      makeCommand.Add(cmStrCat(projectName, ".sln"));
       makeCommand.Add("/t:Clean");
     } else {
       std::string targetProject = cmStrCat(tname, ".vcxproj");
+      proj = slnData.GetProjectByName(tname);
       if (targetProject.find('/') == std::string::npos) {
         // it might be in a subdir
-        if (cmSlnProjectEntry const* proj = slnData.GetProjectByName(tname)) {
+        if (proj) {
           targetProject = proj->GetRelativePath();
           cmSystemTools::ConvertToUnixSlashes(targetProject);
         }
@@ -1243,22 +1245,33 @@ cmGlobalVisualStudio10Generator::GenerateBuildCommand(
       }
     }
 
-    std::string configArg = "/p:Configuration=";
-    if (!config.empty()) {
-      configArg += config;
-    } else {
-      configArg += "Debug";
+    std::string plainConfig = config;
+    if (config.empty()) {
+      plainConfig = "Debug";
     }
-    makeCommand.Add(configArg);
-    makeCommand.Add(std::string("/p:Platform=") + this->GetPlatformName());
-    makeCommand.Add(std::string("/p:VisualStudioVersion=") +
-                    this->GetIDEVersion());
+
+    std::string platform = GetPlatformName();
+    if (proj) {
+      std::string extension =
+        cmSystemTools::GetFilenameLastExtension(proj->GetRelativePath());
+      extension = cmSystemTools::LowerCase(extension);
+      if (extension.compare(".csproj") == 0) {
+        // Use correct platform name
+        platform =
+          slnData.GetConfigurationTarget(tname, plainConfig, platform);
+      }
+    }
+
+    makeCommand.Add(cmStrCat("/p:Configuration=", plainConfig));
+    makeCommand.Add(cmStrCat("/p:Platform=", platform));
+    makeCommand.Add(
+      cmStrCat("/p:VisualStudioVersion=", this->GetIDEVersion()));
 
     if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) {
       if (jobs == cmake::DEFAULT_BUILD_PARALLEL_LEVEL) {
         makeCommand.Add("/m");
       } else {
-        makeCommand.Add(std::string("/m:") + std::to_string(jobs));
+        makeCommand.Add(cmStrCat("/m:", std::to_string(jobs)));
       }
       // Having msbuild.exe and cl.exe using multiple jobs is discouraged
       makeCommand.Add("/p:CL_MPCount=1");
@@ -1266,7 +1279,7 @@ cmGlobalVisualStudio10Generator::GenerateBuildCommand(
 
     // Respect the verbosity: 'n' normal will show build commands
     //                        'm' minimal only the build step's title
-    makeCommand.Add(std::string("/v:") + ((verbose) ? "n" : "m"));
+    makeCommand.Add(cmStrCat("/v:", ((verbose) ? "n" : "m")));
     makeCommand.Add(makeOptions.begin(), makeOptions.end());
     makeCommands.emplace_back(std::move(makeCommand));
   }

+ 11 - 0
Source/cmVisualStudio10TargetGenerator.cxx

@@ -926,6 +926,17 @@ void cmVisualStudio10TargetGenerator::WriteSdkStyleProjectFile(
     e1.Element("OutputType", outputType);
   }
 
+  for (const std::string& config : this->Configurations) {
+    Elem e1(e0, "PropertyGroup");
+    e1.Attribute("Condition", "'$(Configuration)' == '" + config + "'");
+    e1.SetHasElements();
+    this->WriteEvents(e1, config);
+
+    std::string outDir = this->GeneratorTarget->GetDirectory(config) + "/";
+    ConvertToWindowsSlash(outDir);
+    e1.Element("OutputPath", outDir);
+  }
+
   this->WriteDotNetDocumentationFile(e0);
   this->WriteAllSources(e0);
   this->WriteDotNetReferences(e0);

+ 42 - 6
Source/cmVisualStudioSlnData.cxx

@@ -5,24 +5,39 @@
 #include <cstddef>
 #include <utility>
 
-const cmSlnProjectEntry* cmSlnData::GetProjectByGUID(
+#include "cmSystemTools.h"
+
+void cmSlnProjectEntry::AddProjectConfiguration(
+  const std::string& solutionConfiguration,
+  const std::string& projectConfiguration)
+{
+  projectConfigurationMap[solutionConfiguration] = projectConfiguration;
+}
+
+std::string cmSlnProjectEntry::GetProjectConfiguration(
+  const std::string& solutionConfiguration)
+{
+  return projectConfigurationMap[solutionConfiguration];
+}
+
+const cm::optional<cmSlnProjectEntry> cmSlnData::GetProjectByGUID(
   const std::string& projectGUID) const
 {
   ProjectStorage::const_iterator it(ProjectsByGUID.find(projectGUID));
   if (it != ProjectsByGUID.end())
-    return &it->second;
+    return it->second;
   else
-    return NULL;
+    return cm::nullopt;
 }
 
-const cmSlnProjectEntry* cmSlnData::GetProjectByName(
+const cm::optional<cmSlnProjectEntry> cmSlnData::GetProjectByName(
   const std::string& projectName) const
 {
   ProjectStringIndex::const_iterator it(ProjectNameIndex.find(projectName));
   if (it != ProjectNameIndex.end())
-    return &it->second->second;
+    return it->second->second;
   else
-    return NULL;
+    return cm::nullopt;
 }
 
 std::vector<cmSlnProjectEntry> cmSlnData::GetProjects() const
@@ -50,3 +65,24 @@ cmSlnProjectEntry* cmSlnData::AddProject(
   ProjectNameIndex[projectName] = it;
   return &it->second;
 }
+
+std::string cmSlnData::GetConfigurationTarget(
+  const std::string& projectName, const std::string& solutionConfiguration,
+  const std::string& platformName)
+{
+  std::string solutionTarget = solutionConfiguration + "|" + platformName;
+  cm::optional<cmSlnProjectEntry> project = GetProjectByName(projectName);
+  if (!project)
+    return platformName;
+
+  std::string projectTarget = project->GetProjectConfiguration(solutionTarget);
+  if (projectTarget.empty())
+    return platformName;
+
+  std::vector<std::string> targetElements =
+    cmSystemTools::SplitString(projectTarget, '|');
+  if (targetElements.size() != 2)
+    return platformName;
+
+  return targetElements[1];
+}

+ 38 - 2
Source/cmVisualStudioSlnData.h

@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include <cm/optional>
+
 class cmSlnProjectEntry
 {
 public:
@@ -24,17 +26,40 @@ public:
   std::string GetName() const { return Name; }
   std::string GetRelativePath() const { return RelativePath; }
 
+  void AddProjectConfiguration(const std::string& solutionConfiguration,
+                               const std::string& projectConfiguration);
+
+  std::string GetProjectConfiguration(
+    const std::string& solutionConfiguration);
+
 private:
   std::string Guid, Name, RelativePath;
+  std::map<std::string, std::string> projectConfigurationMap;
 };
 
 class cmSlnData
 {
 public:
-  const cmSlnProjectEntry* GetProjectByGUID(
+  std::string GetVisualStudioVersion() const { return visualStudioVersion; }
+  void SetVisualStudioVersion(const std::string& version)
+  {
+    visualStudioVersion = version;
+  }
+
+  std::string GetMinimumVisualStudioVersion() const
+  {
+    return minimumVisualStudioVersion;
+  }
+
+  void SetMinimumVisualStudioVersion(const std::string& version)
+  {
+    minimumVisualStudioVersion = version;
+  }
+
+  const cm::optional<cmSlnProjectEntry> GetProjectByGUID(
     const std::string& projectGUID) const;
 
-  const cmSlnProjectEntry* GetProjectByName(
+  const cm::optional<cmSlnProjectEntry> GetProjectByName(
     const std::string& projectName) const;
 
   std::vector<cmSlnProjectEntry> GetProjects() const;
@@ -43,9 +68,20 @@ public:
                                 const std::string& projectName,
                                 const std::string& projectRelativePath);
 
+  void AddConfiguration(const std::string& configuration)
+  {
+    solutionConfigurations.push_back(configuration);
+  }
+
+  std::string GetConfigurationTarget(const std::string& projectName,
+                                     const std::string& solutionConfiguration,
+                                     const std::string& platformName);
+
 private:
+  std::string visualStudioVersion, minimumVisualStudioVersion;
   using ProjectStorage = std::map<std::string, cmSlnProjectEntry>;
   ProjectStorage ProjectsByGUID;
   using ProjectStringIndex = std::map<std::string, ProjectStorage::iterator>;
   ProjectStringIndex ProjectNameIndex;
+  std::vector<std::string> solutionConfigurations;
 };

+ 36 - 12
Source/cmVisualStudioSlnParser.cxx

@@ -11,6 +11,7 @@
 #include "cmsys/FStream.hxx"
 
 #include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
 #include "cmVisualStudioSlnData.h"
 
 namespace {
@@ -219,9 +220,14 @@ bool cmVisualStudioSlnParser::State::Process(
           this->Stack.push(FileStateProject);
         } else
           this->IgnoreUntilTag("EndProject");
-      } else if (line.GetTag().compare("Global") == 0)
+      } else if (line.GetTag().compare("Global") == 0) {
+
         this->Stack.push(FileStateGlobal);
-      else {
+      } else if (line.GetTag().compare("VisualStudioVersion") == 0) {
+        output.SetVisualStudioVersion(line.GetValue(0));
+      } else if (line.GetTag().compare("MinimumVisualStudioVersion") == 0) {
+        output.SetMinimumVisualStudioVersion(line.GetValue(0));
+      } else {
         result.SetError(ResultErrorInputStructure, this->GetCurrentLine());
         return false;
       }
@@ -289,10 +295,9 @@ bool cmVisualStudioSlnParser::State::Process(
     case FileStateSolutionConfigurations:
       if (line.GetTag().compare("EndGlobalSection") == 0)
         this->Stack.pop();
-      else if (line.IsKeyValuePair())
-        // implement configuration storing here, once needed
-        ;
-      else {
+      else if (line.IsKeyValuePair()) {
+        output.AddConfiguration(line.GetValue(0));
+      } else {
         result.SetError(ResultErrorInputStructure, this->GetCurrentLine());
         return false;
       }
@@ -300,10 +305,30 @@ bool cmVisualStudioSlnParser::State::Process(
     case FileStateProjectConfigurations:
       if (line.GetTag().compare("EndGlobalSection") == 0)
         this->Stack.pop();
-      else if (line.IsKeyValuePair())
-        // implement configuration storing here, once needed
-        ;
-      else {
+      else if (line.IsKeyValuePair()) {
+        std::vector<std::string> tagElements =
+          cmSystemTools::SplitString(line.GetTag(), '.');
+        if (tagElements.size() != 3 && tagElements.size() != 4) {
+          result.SetError(ResultErrorInputStructure, this->GetCurrentLine());
+          return false;
+        }
+
+        std::string guid = tagElements[0];
+        std::string solutionConfiguration = tagElements[1];
+        std::string activeBuild = tagElements[2];
+        cm::optional<cmSlnProjectEntry> projectEntry =
+          output.GetProjectByGUID(guid);
+
+        if (!projectEntry) {
+          result.SetError(ResultErrorInputStructure, this->GetCurrentLine());
+          return false;
+        }
+
+        if (activeBuild.compare("ActiveCfg") == 0) {
+          projectEntry->AddProjectConfiguration(solutionConfiguration,
+                                                line.GetValue(0));
+        }
+      } else {
         result.SetError(ResultErrorInputStructure, this->GetCurrentLine());
         return false;
       }
@@ -454,8 +479,7 @@ bool cmVisualStudioSlnParser::GetParseHadBOM() const
 bool cmVisualStudioSlnParser::IsDataGroupSetSupported(
   DataGroupSet dataGroups) const
 {
-  return (dataGroups & DataGroupProjects) == dataGroups;
-  // only supporting DataGroupProjects for now
+  return (dataGroups & DataGroupProjects) != 0;
 }
 
 bool cmVisualStudioSlnParser::ParseImpl(std::istream& input, cmSlnData& output,