1
0
mirror of https://github.com/Kitware/CMake.git synced 2025-10-15 20:46:37 +08:00

VS: Handle build target correct for .NET SDK style projects with Any CPU

* Extend Visual Studio solution parser for reading build target
* Map solution build target to project build target (especially for Any CPU)
* Use C++ <optional> template instead of pointer return value for cmSlnData::GetProjectByGUID
This commit is contained in:
Florian Schweiger
2022-02-02 18:23:35 +01:00
parent 309191052c
commit 5cdd774d51
4 changed files with 119 additions and 32 deletions

View File

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

View File

@@ -5,24 +5,39 @@
#include <cstddef> #include <cstddef>
#include <utility> #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 const std::string& projectGUID) const
{ {
ProjectStorage::const_iterator it(ProjectsByGUID.find(projectGUID)); ProjectStorage::const_iterator it(ProjectsByGUID.find(projectGUID));
if (it != ProjectsByGUID.end()) if (it != ProjectsByGUID.end())
return &it->second; return it->second;
else else
return NULL; return cm::nullopt;
} }
const cmSlnProjectEntry* cmSlnData::GetProjectByName( const cm::optional<cmSlnProjectEntry> cmSlnData::GetProjectByName(
const std::string& projectName) const const std::string& projectName) const
{ {
ProjectStringIndex::const_iterator it(ProjectNameIndex.find(projectName)); ProjectStringIndex::const_iterator it(ProjectNameIndex.find(projectName));
if (it != ProjectNameIndex.end()) if (it != ProjectNameIndex.end())
return &it->second->second; return it->second->second;
else else
return NULL; return cm::nullopt;
} }
std::vector<cmSlnProjectEntry> cmSlnData::GetProjects() const std::vector<cmSlnProjectEntry> cmSlnData::GetProjects() const
@@ -50,3 +65,24 @@ cmSlnProjectEntry* cmSlnData::AddProject(
ProjectNameIndex[projectName] = it; ProjectNameIndex[projectName] = it;
return &it->second; 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];
}

View File

@@ -8,6 +8,8 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <cm/optional>
class cmSlnProjectEntry class cmSlnProjectEntry
{ {
public: public:
@@ -24,8 +26,15 @@ public:
std::string GetName() const { return Name; } std::string GetName() const { return Name; }
std::string GetRelativePath() const { return RelativePath; } std::string GetRelativePath() const { return RelativePath; }
void AddProjectConfiguration(const std::string& solutionConfiguration,
const std::string& projectConfiguration);
std::string GetProjectConfiguration(
const std::string& solutionConfiguration);
private: private:
std::string Guid, Name, RelativePath; std::string Guid, Name, RelativePath;
std::map<std::string, std::string> projectConfigurationMap;
}; };
class cmSlnData class cmSlnData
@@ -47,10 +56,10 @@ public:
minimumVisualStudioVersion = version; minimumVisualStudioVersion = version;
} }
const cmSlnProjectEntry* GetProjectByGUID( const cm::optional<cmSlnProjectEntry> GetProjectByGUID(
const std::string& projectGUID) const; const std::string& projectGUID) const;
const cmSlnProjectEntry* GetProjectByName( const cm::optional<cmSlnProjectEntry> GetProjectByName(
const std::string& projectName) const; const std::string& projectName) const;
std::vector<cmSlnProjectEntry> GetProjects() const; std::vector<cmSlnProjectEntry> GetProjects() const;
@@ -59,10 +68,20 @@ public:
const std::string& projectName, const std::string& projectName,
const std::string& projectRelativePath); 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: private:
std::string visualStudioVersion, minimumVisualStudioVersion; std::string visualStudioVersion, minimumVisualStudioVersion;
using ProjectStorage = std::map<std::string, cmSlnProjectEntry>; using ProjectStorage = std::map<std::string, cmSlnProjectEntry>;
ProjectStorage ProjectsByGUID; ProjectStorage ProjectsByGUID;
using ProjectStringIndex = std::map<std::string, ProjectStorage::iterator>; using ProjectStringIndex = std::map<std::string, ProjectStorage::iterator>;
ProjectStringIndex ProjectNameIndex; ProjectStringIndex ProjectNameIndex;
std::vector<std::string> solutionConfigurations;
}; };

View File

@@ -11,6 +11,7 @@
#include "cmsys/FStream.hxx" #include "cmsys/FStream.hxx"
#include "cmStringAlgorithms.h" #include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmVisualStudioSlnData.h" #include "cmVisualStudioSlnData.h"
namespace { namespace {
@@ -294,10 +295,9 @@ bool cmVisualStudioSlnParser::State::Process(
case FileStateSolutionConfigurations: case FileStateSolutionConfigurations:
if (line.GetTag().compare("EndGlobalSection") == 0) if (line.GetTag().compare("EndGlobalSection") == 0)
this->Stack.pop(); this->Stack.pop();
else if (line.IsKeyValuePair()) else if (line.IsKeyValuePair()) {
// implement configuration storing here, once needed output.AddConfiguration(line.GetValue(0));
; } else {
else {
result.SetError(ResultErrorInputStructure, this->GetCurrentLine()); result.SetError(ResultErrorInputStructure, this->GetCurrentLine());
return false; return false;
} }
@@ -305,10 +305,30 @@ bool cmVisualStudioSlnParser::State::Process(
case FileStateProjectConfigurations: case FileStateProjectConfigurations:
if (line.GetTag().compare("EndGlobalSection") == 0) if (line.GetTag().compare("EndGlobalSection") == 0)
this->Stack.pop(); this->Stack.pop();
else if (line.IsKeyValuePair()) else if (line.IsKeyValuePair()) {
// implement configuration storing here, once needed std::vector<std::string> tagElements =
; cmSystemTools::SplitString(line.GetTag(), '.');
else { 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()); result.SetError(ResultErrorInputStructure, this->GetCurrentLine());
return false; return false;
} }
@@ -459,8 +479,7 @@ bool cmVisualStudioSlnParser::GetParseHadBOM() const
bool cmVisualStudioSlnParser::IsDataGroupSetSupported( bool cmVisualStudioSlnParser::IsDataGroupSetSupported(
DataGroupSet dataGroups) const DataGroupSet dataGroups) const
{ {
return (dataGroups & DataGroupProjects) == dataGroups; return (dataGroups & DataGroupProjects) != 0;
// only supporting DataGroupProjects for now
} }
bool cmVisualStudioSlnParser::ParseImpl(std::istream& input, cmSlnData& output, bool cmVisualStudioSlnParser::ParseImpl(std::istream& input, cmSlnData& output,