summaryrefslogtreecommitdiffstats
path: root/Source/cmGlobalVisualStudioVersionedGenerator.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'Source/cmGlobalVisualStudioVersionedGenerator.cxx')
-rw-r--r--Source/cmGlobalVisualStudioVersionedGenerator.cxx162
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
{