diff options
Diffstat (limited to 'Source/cmGlobalVisualStudioVersionedGenerator.cxx')
-rw-r--r-- | Source/cmGlobalVisualStudioVersionedGenerator.cxx | 162 |
1 files changed, 155 insertions, 7 deletions
diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.cxx b/Source/cmGlobalVisualStudioVersionedGenerator.cxx index b5a6b9f..ef8fee1 100644 --- a/Source/cmGlobalVisualStudioVersionedGenerator.cxx +++ b/Source/cmGlobalVisualStudioVersionedGenerator.cxx @@ -2,16 +2,26 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmGlobalVisualStudioVersionedGenerator.h" +#include <cstring> +#include <set> +#include <sstream> +#include <utility> +#include <vector> + #include <cmext/string_view> #include "cmsys/FStream.hxx" #include "cmsys/Glob.hxx" +#include "cmsys/RegularExpression.hxx" -#include "cmAlgorithms.h" #include "cmDocumentationEntry.h" -#include "cmLocalVisualStudio10Generator.h" +#include "cmGlobalGenerator.h" +#include "cmGlobalGeneratorFactory.h" #include "cmMakefile.h" +#include "cmMessageType.h" +#include "cmStateTypes.h" #include "cmStringAlgorithms.h" +#include "cmSystemTools.h" #include "cmVSSetupHelper.h" #include "cmake.h" @@ -109,6 +119,30 @@ static const char* VSVersionToToolset( return ""; } +static std::string VSVersionToMajorString( + cmGlobalVisualStudioGenerator::VSVersion v) +{ + switch (v) { + case cmGlobalVisualStudioGenerator::VS9: + return "9"; + case cmGlobalVisualStudioGenerator::VS10: + return "10"; + case cmGlobalVisualStudioGenerator::VS11: + return "11"; + case cmGlobalVisualStudioGenerator::VS12: + return "12"; + case cmGlobalVisualStudioGenerator::VS14: + return "14"; + case cmGlobalVisualStudioGenerator::VS15: + return "15"; + case cmGlobalVisualStudioGenerator::VS16: + return "16"; + case cmGlobalVisualStudioGenerator::VS17: + return "17"; + } + return ""; +} + static const char* VSVersionToAndroidToolset( cmGlobalVisualStudioGenerator::VSVersion v) { @@ -447,15 +481,25 @@ bool cmGlobalVisualStudioVersionedGenerator::SetGeneratorInstance( return true; } - if (!i.empty()) { - if (!this->vsSetupAPIHelper.SetVSInstance(i)) { + if (!this->ParseGeneratorInstance(i, mf)) { + return false; + } + + if (!this->GeneratorInstanceVersion.empty()) { + std::string const majorStr = VSVersionToMajorString(this->Version); + cmsys::RegularExpression versionRegex( + cmStrCat("^", majorStr, "\\.[0-9]+\\.[0-9]+\\.[0-9]+$")); + if (!versionRegex.find(this->GeneratorInstanceVersion)) { std::ostringstream e; /* clang-format off */ e << "Generator\n" " " << this->GetName() << "\n" - "could not find specified instance of Visual Studio:\n" - " " << i; + "given instance specification\n" + " " << i << "\n" + "but the version field is not 4 integer components" + " starting in " << majorStr << "." + ; /* clang-format on */ mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; @@ -463,7 +507,29 @@ bool cmGlobalVisualStudioVersionedGenerator::SetGeneratorInstance( } std::string vsInstance; - if (!this->vsSetupAPIHelper.GetVSInstanceInfo(vsInstance)) { + if (!i.empty()) { + vsInstance = i; + if (!this->vsSetupAPIHelper.SetVSInstance( + this->GeneratorInstance, this->GeneratorInstanceVersion)) { + std::ostringstream e; + /* clang-format off */ + e << + "Generator\n" + " " << this->GetName() << "\n" + "could not find specified instance of Visual Studio:\n" + " " << i; + /* clang-format on */ + if (!this->GeneratorInstance.empty() && + this->GeneratorInstanceVersion.empty() && + cmSystemTools::FileIsDirectory(this->GeneratorInstance)) { + e << "\n" + "The directory exists, but the instance is not known to the " + "Visual Studio Installer, and no 'version=' field was given."; + } + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); + return false; + } + } else if (!this->vsSetupAPIHelper.GetVSInstanceInfo(vsInstance)) { std::ostringstream e; /* clang-format off */ e << @@ -491,6 +557,88 @@ bool cmGlobalVisualStudioVersionedGenerator::SetGeneratorInstance( return true; } +bool cmGlobalVisualStudioVersionedGenerator::ParseGeneratorInstance( + std::string const& is, cmMakefile* mf) +{ + this->GeneratorInstance.clear(); + this->GeneratorInstanceVersion.clear(); + + std::vector<std::string> const fields = cmTokenize(is, ","); + std::vector<std::string>::const_iterator fi = fields.begin(); + if (fi == fields.end()) { + return true; + } + + // The first field may be the VS instance. + if (fi->find('=') == fi->npos) { + this->GeneratorInstance = *fi; + ++fi; + } + + std::set<std::string> handled; + + // The rest of the fields must be key=value pairs. + for (; fi != fields.end(); ++fi) { + std::string::size_type pos = fi->find('='); + if (pos == fi->npos) { + std::ostringstream e; + /* clang-format off */ + e << + "Generator\n" + " " << this->GetName() << "\n" + "given instance specification\n" + " " << is << "\n" + "that contains a field after the first ',' with no '='." + ; + /* clang-format on */ + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); + return false; + } + std::string const key = fi->substr(0, pos); + std::string const value = fi->substr(pos + 1); + if (!handled.insert(key).second) { + std::ostringstream e; + /* clang-format off */ + e << + "Generator\n" + " " << this->GetName() << "\n" + "given instance specification\n" + " " << is << "\n" + "that contains duplicate field key '" << key << "'." + ; + /* clang-format on */ + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); + return false; + } + if (!this->ProcessGeneratorInstanceField(key, value)) { + std::ostringstream e; + /* clang-format off */ + e << + "Generator\n" + " " << this->GetName() << "\n" + "given instance specification\n" + " " << is << "\n" + "that contains invalid field '" << *fi << "'." + ; + /* clang-format on */ + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); + return false; + } + } + + return true; +} + +bool cmGlobalVisualStudioVersionedGenerator::ProcessGeneratorInstanceField( + std::string const& key, std::string const& value) +{ + if (key == "version") { + this->GeneratorInstanceVersion = value; + return true; + } + return false; +} + bool cmGlobalVisualStudioVersionedGenerator::GetVSInstance( std::string& dir) const { |