mirror of
https://github.com/Kitware/CMake.git
synced 2026-02-21 14:40:26 -06:00
Merge topic 'vs-instance'
195d47e213VS: Allow CMAKE_GENERATOR_INSTANCE to specify portable instanceec8d37b3b1VS: Support version specification in CMAKE_GENERATOR_INSTANCE8e6d930e8cVS: Parse comma-separated fields from CMAKE_GENERATOR_INSTANCE5d1f377737cmVSSetupHelper: Factor out helper to load MSVC toolset version006fe1e919cmVSSetupHelper: Convert wide to narrow strings earlyf5dfc788b8cmVSSetupHelper: Drop unused InstanceId field3213e2595dcmVSSetupHelper: Drop unused ullVersion field152f9978ddHelp: De-duplicate VS instance selection documentation Acked-by: Kitware Robot <kwrobot@kitware.com> Merge-request: !6651
This commit is contained in:
@@ -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
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
@@ -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
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
@@ -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
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
6
Help/release/dev/vs-instance.rst
Normal file
6
Help/release/dev/vs-instance.rst
Normal 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.
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -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'\.$
|
||||
1
Tests/RunCMake/GeneratorInstance/BadFieldDuplicate.cmake
Normal file
1
Tests/RunCMake/GeneratorInstance/BadFieldDuplicate.cmake
Normal file
@@ -0,0 +1 @@
|
||||
message(FATAL_ERROR "This should not be reached!")
|
||||
@@ -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!")
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -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]+\.$
|
||||
1
Tests/RunCMake/GeneratorInstance/BadVersionFormat1.cmake
Normal file
1
Tests/RunCMake/GeneratorInstance/BadVersionFormat1.cmake
Normal file
@@ -0,0 +1 @@
|
||||
message(FATAL_ERROR "This should not be reached!")
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -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]+\.$
|
||||
1
Tests/RunCMake/GeneratorInstance/BadVersionFormat2.cmake
Normal file
1
Tests/RunCMake/GeneratorInstance/BadVersionFormat2.cmake
Normal file
@@ -0,0 +1 @@
|
||||
message(FATAL_ERROR "This should not be reached!")
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -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$
|
||||
1
Tests/RunCMake/GeneratorInstance/BadVersionNumber.cmake
Normal file
1
Tests/RunCMake/GeneratorInstance/BadVersionNumber.cmake
Normal file
@@ -0,0 +1 @@
|
||||
message(FATAL_ERROR "This should not be reached!")
|
||||
@@ -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}")
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -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\.$
|
||||
1
Tests/RunCMake/GeneratorInstance/PortableNoVersion.cmake
Normal file
1
Tests/RunCMake/GeneratorInstance/PortableNoVersion.cmake
Normal file
@@ -0,0 +1 @@
|
||||
message(FATAL_ERROR "This should not be reached!")
|
||||
@@ -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)
|
||||
|
||||
1
Tests/RunCMake/GeneratorInstance/WrongVersion-result.txt
Normal file
1
Tests/RunCMake/GeneratorInstance/WrongVersion-result.txt
Normal file
@@ -0,0 +1 @@
|
||||
1
|
||||
10
Tests/RunCMake/GeneratorInstance/WrongVersion-stderr.txt
Normal file
10
Tests/RunCMake/GeneratorInstance/WrongVersion-stderr.txt
Normal 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$
|
||||
1
Tests/RunCMake/GeneratorInstance/WrongVersion.cmake
Normal file
1
Tests/RunCMake/GeneratorInstance/WrongVersion.cmake
Normal file
@@ -0,0 +1 @@
|
||||
message(FATAL_ERROR "This should not be reached!")
|
||||
Reference in New Issue
Block a user