Merge topic 'vs-instance'

195d47e213 VS: Allow CMAKE_GENERATOR_INSTANCE to specify portable instance
ec8d37b3b1 VS: Support version specification in CMAKE_GENERATOR_INSTANCE
8e6d930e8c VS: Parse comma-separated fields from CMAKE_GENERATOR_INSTANCE
5d1f377737 cmVSSetupHelper: Factor out helper to load MSVC toolset version
006fe1e919 cmVSSetupHelper: Convert wide to narrow strings early
f5dfc788b8 cmVSSetupHelper: Drop unused InstanceId field
3213e2595d cmVSSetupHelper: Drop unused ullVersion field
152f9978dd Help: De-duplicate VS instance selection documentation

Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !6651
This commit is contained in:
Brad King
2021-11-01 20:24:36 +00:00
committed by Kitware Robot
35 changed files with 426 additions and 95 deletions

View File

@@ -17,18 +17,8 @@ Instance Selection
.. versionadded:: 3.11
VS 2017 supports multiple installations on the same machine.
The :variable:`CMAKE_GENERATOR_INSTANCE` variable may be set as a
cache entry containing the absolute path to a Visual Studio instance.
If the value is not specified explicitly by the user or a toolchain file,
CMake queries the Visual Studio Installer to locate VS instances, chooses
one, and sets the variable as a cache entry to hold the value persistently.
When CMake first chooses an instance, if the ``VS150COMNTOOLS`` environment
variable is set and points to the ``Common7/Tools`` directory within
one of the instances, that instance will be used. Otherwise, if more
than one instance is installed we do not define which one is chosen
by default.
VS 2017 supports multiple installations on the same machine. The
:variable:`CMAKE_GENERATOR_INSTANCE` variable may be used to select one.
Platform Selection
^^^^^^^^^^^^^^^^^^

View File

@@ -15,18 +15,8 @@ Powershell, Python, etc.) are not supported.
Instance Selection
^^^^^^^^^^^^^^^^^^
VS 2019 supports multiple installations on the same machine.
The :variable:`CMAKE_GENERATOR_INSTANCE` variable may be set as a
cache entry containing the absolute path to a Visual Studio instance.
If the value is not specified explicitly by the user or a toolchain file,
CMake queries the Visual Studio Installer to locate VS instances, chooses
one, and sets the variable as a cache entry to hold the value persistently.
When CMake first chooses an instance, if the ``VS160COMNTOOLS`` environment
variable is set and points to the ``Common7/Tools`` directory within
one of the instances, that instance will be used. Otherwise, if more
than one instance is installed we do not define which one is chosen
by default.
VS 2019 supports multiple installations on the same machine. The
:variable:`CMAKE_GENERATOR_INSTANCE` variable may be used to select one.
Platform Selection
^^^^^^^^^^^^^^^^^^

View File

@@ -15,18 +15,8 @@ Powershell, Python, etc.) are not supported.
Instance Selection
^^^^^^^^^^^^^^^^^^
VS 2022 supports multiple installations on the same machine.
The :variable:`CMAKE_GENERATOR_INSTANCE` variable may be set as a
cache entry containing the absolute path to a Visual Studio instance.
If the value is not specified explicitly by the user or a toolchain file,
CMake queries the Visual Studio Installer to locate VS instances, chooses
one, and sets the variable as a cache entry to hold the value persistently.
When CMake first chooses an instance, if the ``VS170COMNTOOLS`` environment
variable is set and points to the ``Common7/Tools`` directory within
one of the instances, that instance will be used. Otherwise, if more
than one instance is installed we do not define which one is chosen
by default.
VS 2022 supports multiple installations on the same machine. The
:variable:`CMAKE_GENERATOR_INSTANCE` variable may be used to select one.
Platform Selection
^^^^^^^^^^^^^^^^^^

View File

@@ -0,0 +1,6 @@
vs-instance
-----------
* The :ref:`Visual Studio Generators` for VS 2017 and above learned to
use portable instances of Visual Studio not known to the VS installer.
See the :variable:`CMAKE_GENERATOR_INSTANCE` variable.

View File

@@ -18,10 +18,43 @@ variable may initialize ``CMAKE_GENERATOR_INSTANCE`` as a cache entry.
Once a given build tree has been initialized with a particular value
for this variable, changing the value has undefined behavior.
Instance specification is supported only on specific generators:
Instance specification is supported only on specific generators.
* For the :generator:`Visual Studio 15 2017` generator (and above)
this specifies the absolute path to the VS installation directory
of the selected VS instance.
Visual Studio Instance Selection
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
See native build system documentation for allowed instance values.
: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 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.
Supported pairs are:
``version=<major>.<minor>.<MMMDD>.<BBB>``
.. versionadded:: 3.23
Specify the 4-component VS Build Version.
.. versionadded:: 3.23
A portable VS instance may be specified that is not known to the
Visual Studio Installer tool. The ``location`` and ``version=``
values must both be provided.
If the value of ``CMAKE_GENERATOR_INSTANCE`` is not specified explicitly
by the user or a toolchain file, CMake queries the Visual Studio Installer
to locate VS instances, chooses one, and sets the variable as a cache entry
to hold the value persistently. If an environment variable of the form
``VS##0COMNTOOLS``, where ``##`` the Visual Studio major version number,
is set and points to the ``Common7/Tools`` directory within one of the
VS instances, that instance will be used. Otherwise, if more than one
VS instance is installed we do not define which one is chosen by default.

View File

@@ -6,6 +6,7 @@
#include "cmsys/FStream.hxx"
#include "cmsys/Glob.hxx"
#include "cmsys/RegularExpression.hxx"
#include "cmAlgorithms.h"
#include "cmDocumentationEntry.h"
@@ -109,6 +110,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)
{
@@ -441,8 +466,36 @@ bool cmGlobalVisualStudioVersionedGenerator::SetGeneratorInstance(
return true;
}
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"
"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;
}
}
std::string vsInstance;
if (!i.empty()) {
if (!this->vsSetupAPIHelper.SetVSInstance(i)) {
vsInstance = i;
if (!this->vsSetupAPIHelper.SetVSInstance(
this->GeneratorInstance, this->GeneratorInstanceVersion)) {
std::ostringstream e;
/* clang-format off */
e <<
@@ -451,13 +504,17 @@ bool cmGlobalVisualStudioVersionedGenerator::SetGeneratorInstance(
"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;
}
}
std::string vsInstance;
if (!this->vsSetupAPIHelper.GetVSInstanceInfo(vsInstance)) {
} else if (!this->vsSetupAPIHelper.GetVSInstanceInfo(vsInstance)) {
std::ostringstream e;
/* clang-format off */
e <<
@@ -485,6 +542,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
{

View File

@@ -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,10 @@ private:
class Factory17;
friend class Factory17;
mutable cmVSSetupAPIHelper vsSetupAPIHelper;
bool ParseGeneratorInstance(std::string const& is, cmMakefile* mf);
std::string GeneratorInstance;
std::string GeneratorInstanceVersion;
cm::optional<std::string> LastGeneratorInstanceString;
};

View File

@@ -2,6 +2,8 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmVSSetupHelper.h"
#include <utility>
#include "cmsys/Encoding.hxx"
#include "cmsys/FStream.hxx"
@@ -46,17 +48,36 @@ const CLSID CLSID_SetupConfiguration = {
/* clang-format on */
#endif
namespace {
const WCHAR* Win10SDKComponent =
L"Microsoft.VisualStudio.Component.Windows10SDK";
const WCHAR* Win81SDKComponent =
L"Microsoft.VisualStudio.Component.Windows81SDK";
const WCHAR* ComponentType = L"Component";
bool LoadVSInstanceVCToolsetVersion(VSInstanceInfo& vsInstanceInfo)
{
std::string const vcRoot = vsInstanceInfo.GetInstallLocation();
std::string vcToolsVersionFile =
vcRoot + "/VC/Auxiliary/Build/Microsoft.VCToolsVersion.default.txt";
std::string vcToolsVersion;
cmsys::ifstream fin(vcToolsVersionFile.c_str());
if (!fin || !cmSystemTools::GetLineFromStream(fin, vcToolsVersion)) {
return false;
}
vcToolsVersion = cmTrimWhitespace(vcToolsVersion);
std::string const vcToolsDir = vcRoot + "/VC/Tools/MSVC/" + vcToolsVersion;
if (!cmSystemTools::FileIsDirectory(vcToolsDir)) {
return false;
}
vsInstanceInfo.VCToolsetVersion = vcToolsVersion;
return true;
}
}
std::string VSInstanceInfo::GetInstallLocation() const
{
std::string loc = cmsys::Encoding::ToNarrow(this->VSInstallLocation);
cmSystemTools::ConvertToUnixSlashes(loc);
return loc;
return this->VSInstallLocation;
}
cmVSSetupAPIHelper::cmVSSetupAPIHelper(unsigned int version)
@@ -83,10 +104,12 @@ cmVSSetupAPIHelper::~cmVSSetupAPIHelper()
CoUninitialize();
}
bool cmVSSetupAPIHelper::SetVSInstance(std::string const& vsInstallLocation)
bool cmVSSetupAPIHelper::SetVSInstance(std::string const& vsInstallLocation,
std::string const& vsInstallVersion)
{
this->SpecifiedVSInstallLocation = vsInstallLocation;
cmSystemTools::ConvertToUnixSlashes(this->SpecifiedVSInstallLocation);
this->SpecifiedVSInstallVersion = vsInstallVersion;
chosenInstanceInfo = VSInstanceInfo();
return this->EnumerateAndChooseVSInstance();
}
@@ -152,29 +175,17 @@ bool cmVSSetupAPIHelper::GetVSInstanceInfo(
if (pInstance == NULL)
return false;
SmartBSTR bstrId;
if (SUCCEEDED(pInstance->GetInstanceId(&bstrId))) {
vsInstanceInfo.InstanceId = std::wstring(bstrId);
} else {
return false;
}
InstanceState state;
if (FAILED(pInstance->GetState(&state))) {
return false;
}
ULONGLONG ullVersion = 0;
SmartBSTR bstrVersion;
if (FAILED(pInstance->GetInstallationVersion(&bstrVersion))) {
return false;
} else {
vsInstanceInfo.Version = std::wstring(bstrVersion);
if (FAILED(setupHelper->ParseVersion(bstrVersion, &ullVersion))) {
vsInstanceInfo.ullVersion = 0;
} else {
vsInstanceInfo.ullVersion = ullVersion;
}
vsInstanceInfo.Version =
cmsys::Encoding::ToNarrow(std::wstring(bstrVersion));
}
// Reboot may have been required before the installation path was created.
@@ -183,26 +194,15 @@ bool cmVSSetupAPIHelper::GetVSInstanceInfo(
if (FAILED(pInstance->GetInstallationPath(&bstrInstallationPath))) {
return false;
} else {
vsInstanceInfo.VSInstallLocation = std::wstring(bstrInstallationPath);
vsInstanceInfo.VSInstallLocation =
cmsys::Encoding::ToNarrow(std::wstring(bstrInstallationPath));
cmSystemTools::ConvertToUnixSlashes(vsInstanceInfo.VSInstallLocation);
}
}
// Check if a compiler is installed with this instance.
{
std::string const vcRoot = vsInstanceInfo.GetInstallLocation();
std::string vcToolsVersionFile =
vcRoot + "/VC/Auxiliary/Build/Microsoft.VCToolsVersion.default.txt";
std::string vcToolsVersion;
cmsys::ifstream fin(vcToolsVersionFile.c_str());
if (!fin || !cmSystemTools::GetLineFromStream(fin, vcToolsVersion)) {
return false;
}
vcToolsVersion = cmTrimWhitespace(vcToolsVersion);
std::string const vcToolsDir = vcRoot + "/VC/Tools/MSVC/" + vcToolsVersion;
if (!cmSystemTools::FileIsDirectory(vcToolsDir)) {
return false;
}
vsInstanceInfo.VCToolsetVersion = vcToolsVersion;
if (!LoadVSInstanceVCToolsetVersion(vsInstanceInfo)) {
return false;
}
// Reboot may have been required before the product package was registered
@@ -264,7 +264,7 @@ bool cmVSSetupAPIHelper::GetVSInstanceVersion(std::string& vsInstanceVersion)
bool isInstalled = this->EnumerateAndChooseVSInstance();
if (isInstalled) {
vsInstanceVersion = cmsys::Encoding::ToNarrow(chosenInstanceInfo.Version);
vsInstanceVersion = chosenInstanceInfo.Version;
}
return isInstalled;
@@ -298,7 +298,7 @@ bool cmVSSetupAPIHelper::IsEWDKEnabled()
bool cmVSSetupAPIHelper::EnumerateAndChooseVSInstance()
{
bool isVSInstanceExists = false;
if (chosenInstanceInfo.VSInstallLocation.compare(L"") != 0) {
if (chosenInstanceInfo.VSInstallLocation.compare("") != 0) {
return true;
}
@@ -311,12 +311,11 @@ bool cmVSSetupAPIHelper::EnumerateAndChooseVSInstance()
if (envVSVersion.empty() || envVsInstallDir.empty())
return false;
chosenInstanceInfo.VSInstallLocation =
std::wstring(envVsInstallDir.begin(), envVsInstallDir.end());
chosenInstanceInfo.Version =
std::wstring(envVSVersion.begin(), envVSVersion.end());
chosenInstanceInfo.VCToolsetVersion = envVSVersion;
chosenInstanceInfo.ullVersion = std::stoi(envVSVersion);
chosenInstanceInfo.VSInstallLocation = envVsInstallDir;
chosenInstanceInfo.Version = envVSVersion;
if (!LoadVSInstanceVCToolsetVersion(chosenInstanceInfo)) {
return false;
}
chosenInstanceInfo.IsWin10SDKInstalled = true;
chosenInstanceInfo.IsWin81SDKInstalled = !envWindowsSdkDir81.empty();
return true;
@@ -343,7 +342,9 @@ bool cmVSSetupAPIHelper::EnumerateAndChooseVSInstance()
return false;
}
std::wstring const wantVersion = std::to_wstring(this->Version) + L'.';
std::string const wantVersion = std::to_string(this->Version) + '.';
bool specifiedLocationNotSpecifiedVersion = false;
SmartCOMPtr<ISetupInstance> instance;
while (SUCCEEDED(enumInstances->Next(1, &instance, NULL)) && instance) {
@@ -371,6 +372,16 @@ bool cmVSSetupAPIHelper::EnumerateAndChooseVSInstance()
std::string currentVSLocation = instanceInfo.GetInstallLocation();
if (cmSystemTools::ComparePath(currentVSLocation,
this->SpecifiedVSInstallLocation)) {
if (this->SpecifiedVSInstallVersion.empty() ||
instanceInfo.Version == this->SpecifiedVSInstallVersion) {
chosenInstanceInfo = instanceInfo;
return true;
}
specifiedLocationNotSpecifiedVersion = true;
}
} else if (!this->SpecifiedVSInstallVersion.empty()) {
// We are looking for a specific version.
if (instanceInfo.Version == this->SpecifiedVSInstallVersion) {
chosenInstanceInfo = instanceInfo;
return true;
}
@@ -392,6 +403,13 @@ bool cmVSSetupAPIHelper::EnumerateAndChooseVSInstance()
}
}
if (!this->SpecifiedVSInstallLocation.empty() &&
!specifiedLocationNotSpecifiedVersion) {
// The VS Installer does not know about the specified location.
// Check for one directly on disk.
return this->LoadSpecifiedVSInstanceFromDisk();
}
if (vecVSInstances.size() > 0) {
isVSInstanceExists = true;
int index = ChooseVSInstance(vecVSInstances);
@@ -454,6 +472,32 @@ int cmVSSetupAPIHelper::ChooseVSInstance(
return chosenIndex;
}
bool cmVSSetupAPIHelper::LoadSpecifiedVSInstanceFromDisk()
{
if (!cmSystemTools::FileIsDirectory(this->SpecifiedVSInstallLocation)) {
return false;
}
VSInstanceInfo vsInstanceInfo;
vsInstanceInfo.VSInstallLocation = this->SpecifiedVSInstallLocation;
// FIXME: Is there a better way to get SDK information?
vsInstanceInfo.IsWin10SDKInstalled = true;
vsInstanceInfo.IsWin81SDKInstalled = false;
if (!this->SpecifiedVSInstallVersion.empty()) {
// Assume the version specified by the user is correct.
vsInstanceInfo.Version = this->SpecifiedVSInstallVersion;
} else {
return false;
}
if (!LoadVSInstanceVCToolsetVersion(vsInstanceInfo)) {
return false;
}
chosenInstanceInfo = std::move(vsInstanceInfo);
return true;
}
bool cmVSSetupAPIHelper::Initialize()
{
if (initializationFailure)

View File

@@ -84,11 +84,9 @@ private:
struct VSInstanceInfo
{
std::wstring InstanceId;
std::wstring VSInstallLocation;
std::wstring Version;
std::string VSInstallLocation;
std::string Version;
std::string VCToolsetVersion;
ULONGLONG ullVersion = 0; // A.B.C.D = (A<<48)|(B<<32)|(C<<16)|D
bool IsWin10SDKInstalled = false;
bool IsWin81SDKInstalled = false;
@@ -101,7 +99,8 @@ public:
cmVSSetupAPIHelper(unsigned int version);
~cmVSSetupAPIHelper();
bool SetVSInstance(std::string const& vsInstallLocation);
bool SetVSInstance(std::string const& vsInstallLocation,
std::string const& vsInstallVersion);
bool IsVSInstalled();
bool GetVSInstanceInfo(std::string& vsInstallLocation);
@@ -118,6 +117,7 @@ private:
bool& bWin10SDK, bool& bWin81SDK);
int ChooseVSInstance(const std::vector<VSInstanceInfo>& vecVSInstances);
bool EnumerateAndChooseVSInstance();
bool LoadSpecifiedVSInstanceFromDisk();
unsigned int Version;
@@ -134,4 +134,5 @@ private:
bool IsEWDKEnabled();
std::string SpecifiedVSInstallLocation;
std::string SpecifiedVSInstallVersion;
};

View File

@@ -0,0 +1 @@
1

View File

@@ -0,0 +1,11 @@
^CMake Error at CMakeLists.txt:[0-9]+ \(project\):
Generator
Visual Studio [^
]+
given instance specification
Test Instance,version=1\.2\.3\.4,version=1\.2\.3\.4
that contains duplicate field key 'version'\.$

View File

@@ -0,0 +1 @@
message(FATAL_ERROR "This should not be reached!")

View File

@@ -0,0 +1 @@
1

View 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 '='\.$

View File

@@ -0,0 +1 @@
message(FATAL_ERROR "This should not be reached!")

View File

@@ -0,0 +1 @@
1

View 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='\.$

View File

@@ -0,0 +1 @@
message(FATAL_ERROR "This should not be reached!")

View File

@@ -0,0 +1 @@
1

View File

@@ -0,0 +1,11 @@
^CMake Error at CMakeLists.txt:[0-9]+ \(project\):
Generator
Visual Studio [^
]+
given instance specification
version=1\.2\.3
but the version field is not 4 integer components starting in [0-9]+\.$

View File

@@ -0,0 +1 @@
message(FATAL_ERROR "This should not be reached!")

View File

@@ -0,0 +1 @@
1

View File

@@ -0,0 +1,11 @@
^CMake Error at CMakeLists.txt:[0-9]+ \(project\):
Generator
Visual Studio [^
]+
given instance specification
version=1\.2\.3\.x
but the version field is not 4 integer components starting in [0-9]+\.$

View File

@@ -0,0 +1 @@
message(FATAL_ERROR "This should not be reached!")

View File

@@ -0,0 +1 @@
1

View File

@@ -0,0 +1,9 @@
^CMake Error at CMakeLists.txt:[0-9] \(project\):
Generator
Visual Studio [^
]+
could not find specified instance of Visual Studio:
version=[0-9]+\.999\.99999\.999$

View File

@@ -0,0 +1 @@
message(FATAL_ERROR "This should not be reached!")

View File

@@ -11,3 +11,4 @@ elseif(NOT IS_DIRECTORY "${CMAKE_GENERATOR_INSTANCE}")
" ${CMAKE_GENERATOR_INSTANCE}\n"
"which is not an existing directory.")
endif()
file(WRITE "${CMAKE_BINARY_DIR}/instance.txt" "${CMAKE_GENERATOR_INSTANCE}")

View File

@@ -0,0 +1 @@
1

View File

@@ -0,0 +1,13 @@
^CMake Error at CMakeLists.txt:[0-9]+ \(project\):
Generator
Visual Studio [^
]+
could not find specified instance of Visual Studio:
[^
]+/Tests/RunCMake/GeneratorInstance
The directory exists, but the instance is not known to the Visual Studio
Installer, and no 'version=' field was given\.$

View File

@@ -0,0 +1 @@
message(FATAL_ERROR "This should not be reached!")

View File

@@ -1,14 +1,40 @@
include(RunCMake)
if("${RunCMake_GENERATOR}" MATCHES "^Visual Studio 1[56789]")
if("${RunCMake_GENERATOR}" MATCHES "^Visual Studio (1[56789])")
set(vs_major "${CMAKE_MATCH_1}")
set(RunCMake_GENERATOR_INSTANCE "")
run_cmake(DefaultInstance)
set(instance_txt "${RunCMake_BINARY_DIR}/DefaultInstance-build/instance.txt")
if(EXISTS "${instance_txt}")
file(READ "${instance_txt}" default_instance)
endif()
set(RunCMake_GENERATOR_INSTANCE "${RunCMake_SOURCE_DIR}/instance_does_not_exist")
run_cmake(MissingInstance)
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)
set(RunCMake_GENERATOR_INSTANCE "Test Instance,version=1.2.3.4,version=1.2.3.4")
run_cmake(BadFieldDuplicate)
set(RunCMake_GENERATOR_INSTANCE "version=1.2.3")
run_cmake(BadVersionFormat1)
set(RunCMake_GENERATOR_INSTANCE "version=1.2.3.x")
run_cmake(BadVersionFormat2)
set(RunCMake_GENERATOR_INSTANCE "version=${vs_major}.999.99999.999")
run_cmake(BadVersionNumber)
if(IS_DIRECTORY "${default_instance}")
set(RunCMake_GENERATOR_INSTANCE "${default_instance},version=${vs_major}.999.99999.999")
run_cmake(WrongVersion)
endif()
set(RunCMake_GENERATOR_INSTANCE "${RunCMake_SOURCE_DIR}")
run_cmake(PortableNoVersion)
else()
set(RunCMake_GENERATOR_INSTANCE "")
run_cmake(NoInstance)

View File

@@ -0,0 +1 @@
1

View File

@@ -0,0 +1,10 @@
^CMake Error at CMakeLists.txt:[0-9] \(project\):
Generator
Visual Studio [^
]+
could not find specified instance of Visual Studio:
[^,
]+,version=[0-9]+\.999\.99999\.999$

View File

@@ -0,0 +1 @@
message(FATAL_ERROR "This should not be reached!")