mirror of
https://github.com/Kitware/CMake.git
synced 2026-01-09 07:11:05 -06:00
VS: Parse comma-separated fields from CMAKE_GENERATOR_INSTANCE
This commit is contained in:
@@ -26,7 +26,18 @@ Visual Studio Instance Selection
|
||||
:ref:`Visual Studio Generators` support instance specification for
|
||||
Visual Studio 2017 and above. The ``CMAKE_GENERATOR_INSTANCE`` variable
|
||||
may be set as a cache entry selecting an instance of Visual Studio
|
||||
via the absolute path to the top-level directory of the VS installation.
|
||||
via one of the following forms:
|
||||
|
||||
* ``location``
|
||||
* ``location[,key=value]*``
|
||||
* ``key=value[,key=value]*``
|
||||
|
||||
The ``location`` specifies the absolute path to the top-level directory
|
||||
of the VS installation.
|
||||
|
||||
The ``key=value`` pairs form a comma-separated list of options to
|
||||
specify details of the instance selection.
|
||||
There are no supported pairs: this syntax is reserved for future use.
|
||||
|
||||
If the value of ``CMAKE_GENERATOR_INSTANCE`` is not specified explicitly
|
||||
by the user or a toolchain file, CMake queries the Visual Studio Installer
|
||||
|
||||
@@ -441,8 +441,12 @@ bool cmGlobalVisualStudioVersionedGenerator::SetGeneratorInstance(
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!i.empty()) {
|
||||
if (!this->vsSetupAPIHelper.SetVSInstance(i)) {
|
||||
if (!this->ParseGeneratorInstance(i, mf)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!this->GeneratorInstance.empty()) {
|
||||
if (!this->vsSetupAPIHelper.SetVSInstance(this->GeneratorInstance)) {
|
||||
std::ostringstream e;
|
||||
/* clang-format off */
|
||||
e <<
|
||||
@@ -485,6 +489,85 @@ bool cmGlobalVisualStudioVersionedGenerator::SetGeneratorInstance(
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cmGlobalVisualStudioVersionedGenerator::ParseGeneratorInstance(
|
||||
std::string const& is, cmMakefile* mf)
|
||||
{
|
||||
this->GeneratorInstance.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)
|
||||
{
|
||||
static_cast<void>(key);
|
||||
static_cast<void>(value);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cmGlobalVisualStudioVersionedGenerator::GetVSInstance(
|
||||
std::string& dir) const
|
||||
{
|
||||
|
||||
@@ -65,6 +65,9 @@ protected:
|
||||
|
||||
std::string GetWindows10SDKMaxVersionDefault(cmMakefile*) const override;
|
||||
|
||||
virtual bool ProcessGeneratorInstanceField(std::string const& key,
|
||||
std::string const& value);
|
||||
|
||||
std::string FindMSBuildCommand() override;
|
||||
std::string FindDevEnvCommand() override;
|
||||
|
||||
@@ -76,5 +79,9 @@ private:
|
||||
class Factory17;
|
||||
friend class Factory17;
|
||||
mutable cmVSSetupAPIHelper vsSetupAPIHelper;
|
||||
|
||||
bool ParseGeneratorInstance(std::string const& is, cmMakefile* mf);
|
||||
|
||||
std::string GeneratorInstance;
|
||||
cm::optional<std::string> LastGeneratorInstanceString;
|
||||
};
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
11
Tests/RunCMake/GeneratorInstance/BadFieldNoComma-stderr.txt
Normal file
11
Tests/RunCMake/GeneratorInstance/BadFieldNoComma-stderr.txt
Normal file
@@ -0,0 +1,11 @@
|
||||
^CMake Error at CMakeLists.txt:[0-9]+ \(project\):
|
||||
Generator
|
||||
|
||||
Visual Studio [^
|
||||
]+
|
||||
|
||||
given instance specification
|
||||
|
||||
Test Instance,nocomma
|
||||
|
||||
that contains a field after the first ',' with no '='\.$
|
||||
1
Tests/RunCMake/GeneratorInstance/BadFieldNoComma.cmake
Normal file
1
Tests/RunCMake/GeneratorInstance/BadFieldNoComma.cmake
Normal file
@@ -0,0 +1 @@
|
||||
message(FATAL_ERROR "This should not be reached!")
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
11
Tests/RunCMake/GeneratorInstance/BadFieldUnknown-stderr.txt
Normal file
11
Tests/RunCMake/GeneratorInstance/BadFieldUnknown-stderr.txt
Normal file
@@ -0,0 +1,11 @@
|
||||
^CMake Error at CMakeLists.txt:[0-9]+ \(project\):
|
||||
Generator
|
||||
|
||||
Visual Studio [^
|
||||
]+
|
||||
|
||||
given instance specification
|
||||
|
||||
Test Instance,unknown=
|
||||
|
||||
that contains invalid field 'unknown='\.$
|
||||
1
Tests/RunCMake/GeneratorInstance/BadFieldUnknown.cmake
Normal file
1
Tests/RunCMake/GeneratorInstance/BadFieldUnknown.cmake
Normal file
@@ -0,0 +1 @@
|
||||
message(FATAL_ERROR "This should not be reached!")
|
||||
@@ -9,6 +9,11 @@ if("${RunCMake_GENERATOR}" MATCHES "^Visual Studio 1[56789]")
|
||||
set(RunCMake_TEST_OPTIONS -DCMAKE_TOOLCHAIN_FILE=${RunCMake_SOURCE_DIR}/MissingInstance-toolchain.cmake)
|
||||
run_cmake(MissingInstanceToolchain)
|
||||
unset(RunCMake_TEST_OPTIONS)
|
||||
|
||||
set(RunCMake_GENERATOR_INSTANCE "Test Instance,nocomma")
|
||||
run_cmake(BadFieldNoComma)
|
||||
set(RunCMake_GENERATOR_INSTANCE "Test Instance,unknown=")
|
||||
run_cmake(BadFieldUnknown)
|
||||
else()
|
||||
set(RunCMake_GENERATOR_INSTANCE "")
|
||||
run_cmake(NoInstance)
|
||||
|
||||
Reference in New Issue
Block a user