diff options
author | Brad King <brad.king@kitware.com> | 2022-04-14 13:33:42 (GMT) |
---|---|---|
committer | Kitware Robot <kwrobot@kitware.com> | 2022-04-14 13:33:49 (GMT) |
commit | 3eb9f69ffe3bf9a8a69195a54d147abfc6146cf5 (patch) | |
tree | 075955e52996e7e05946fa571a2f6d980f5faf59 | |
parent | f011557f0eff1fe08b54cfb30a1b74beefe37456 (diff) | |
parent | f85913fa088f03532ac791735c24d25937b93c7b (diff) | |
download | CMake-3eb9f69ffe3bf9a8a69195a54d147abfc6146cf5.zip CMake-3eb9f69ffe3bf9a8a69195a54d147abfc6146cf5.tar.gz CMake-3eb9f69ffe3bf9a8a69195a54d147abfc6146cf5.tar.bz2 |
Merge topic 'vswhere-support'
f85913fa08 VS: Add support for enumerating VS instances with vswhere
069cff63f6 VS: refactor EnumerateAndChooseVSInstance
Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !7159
-rw-r--r-- | Source/cmVSSetupHelper.cxx | 182 | ||||
-rw-r--r-- | Source/cmVSSetupHelper.h | 3 |
2 files changed, 129 insertions, 56 deletions
diff --git a/Source/cmVSSetupHelper.cxx b/Source/cmVSSetupHelper.cxx index cbd241b..1a3e72e 100644 --- a/Source/cmVSSetupHelper.cxx +++ b/Source/cmVSSetupHelper.cxx @@ -4,6 +4,11 @@ #include <utility> +#if !defined(CMAKE_BOOTSTRAP) +# include <cm3p/json/reader.h> +# include <cm3p/json/value.h> +#endif + #include "cmsys/Encoding.hxx" #include "cmsys/FStream.hxx" @@ -295,6 +300,87 @@ bool cmVSSetupAPIHelper::IsEWDKEnabled() return false; } +bool cmVSSetupAPIHelper::EnumerateVSInstancesWithVswhere( + std::vector<VSInstanceInfo>& VSInstances) +{ +#if !defined(CMAKE_BOOTSTRAP) + // Construct vswhere command to get installed VS instances in JSON format + std::string vswhereExe = getenv("ProgramFiles(x86)") + + std::string(R"(\Microsoft Visual Studio\Installer\vswhere.exe)"); + std::vector<std::string> vswhereCmd = { vswhereExe, "-format", "json" }; + + // Execute vswhere command and capture JSON output + std::string json_output; + int retVal = 1; + if (!cmSystemTools::RunSingleCommand(vswhereCmd, &json_output, &json_output, + &retVal, nullptr, + cmSystemTools::OUTPUT_NONE)) { + return false; + } + + // Parse JSON output and iterate over elements + Json::CharReaderBuilder builder; + auto jsonReader = std::unique_ptr<Json::CharReader>(builder.newCharReader()); + Json::Value json; + std::string error; + + if (!jsonReader->parse(json_output.data(), + json_output.data() + json_output.size(), &json, + &error)) { + return false; + } + + for (const auto& item : json) { + VSInstanceInfo instance; + instance.Version = item["installationVersion"].asString(); + instance.VSInstallLocation = item["installationPath"].asString(); + instance.IsWin10SDKInstalled = true; + instance.IsWin81SDKInstalled = false; + cmSystemTools::ConvertToUnixSlashes(instance.VSInstallLocation); + if (LoadVSInstanceVCToolsetVersion(instance)) { + VSInstances.push_back(instance); + } + } + return true; +#else + static_cast<void>(VSInstances); + return false; +#endif +} + +bool cmVSSetupAPIHelper::EnumerateVSInstancesWithCOM( + std::vector<VSInstanceInfo>& VSInstances) +{ + if (initializationFailure || setupConfig == NULL || setupConfig2 == NULL || + setupHelper == NULL) + return false; + + SmartCOMPtr<IEnumSetupInstances> enumInstances = NULL; + if (FAILED( + setupConfig2->EnumInstances((IEnumSetupInstances**)&enumInstances)) || + !enumInstances) { + return false; + } + + SmartCOMPtr<ISetupInstance> instance; + while (SUCCEEDED(enumInstances->Next(1, &instance, NULL)) && instance) { + SmartCOMPtr<ISetupInstance2> instance2 = NULL; + if (FAILED( + instance->QueryInterface(IID_ISetupInstance2, (void**)&instance2)) || + !instance2) { + instance = NULL; + continue; + } + + VSInstanceInfo instanceInfo; + bool isInstalled = GetVSInstanceInfo(instance2, instanceInfo); + instance = instance2 = NULL; + if (isInstalled) + VSInstances.push_back(instanceInfo); + } + return true; +} + bool cmVSSetupAPIHelper::EnumerateAndChooseVSInstance() { bool isVSInstanceExists = false; @@ -321,10 +407,6 @@ bool cmVSSetupAPIHelper::EnumerateAndChooseVSInstance() return true; } - if (initializationFailure || setupConfig == NULL || setupConfig2 == NULL || - setupHelper == NULL) - return false; - std::string envVSCommonToolsDir; std::string envVSCommonToolsDirEnvName = "VS" + std::to_string(this->Version) + "0COMNTOOLS"; @@ -334,72 +416,60 @@ bool cmVSSetupAPIHelper::EnumerateAndChooseVSInstance() cmSystemTools::ConvertToUnixSlashes(envVSCommonToolsDir); } - std::vector<VSInstanceInfo> vecVSInstances; - SmartCOMPtr<IEnumSetupInstances> enumInstances = NULL; - if (FAILED( - setupConfig2->EnumInstances((IEnumSetupInstances**)&enumInstances)) || - !enumInstances) { - return false; - } - std::string const wantVersion = std::to_string(this->Version) + '.'; bool specifiedLocationNotSpecifiedVersion = false; SmartCOMPtr<ISetupInstance> instance; - while (SUCCEEDED(enumInstances->Next(1, &instance, NULL)) && instance) { - SmartCOMPtr<ISetupInstance2> instance2 = NULL; - if (FAILED( - instance->QueryInterface(IID_ISetupInstance2, (void**)&instance2)) || - !instance2) { - instance = NULL; + + std::vector<VSInstanceInfo> vecVSInstancesAll; + + // Enumerate VS instances with either COM interface or Vswhere + if (!EnumerateVSInstancesWithCOM(vecVSInstancesAll) && + !EnumerateVSInstancesWithVswhere(vecVSInstancesAll)) { + return false; + } + + std::vector<VSInstanceInfo> vecVSInstances; + for (const auto& instanceInfo : vecVSInstancesAll) { + // We are looking for a specific major version. + if (instanceInfo.Version.size() < wantVersion.size() || + instanceInfo.Version.substr(0, wantVersion.size()) != wantVersion) { continue; } - VSInstanceInfo instanceInfo; - bool isInstalled = GetVSInstanceInfo(instance2, instanceInfo); - instance = instance2 = NULL; - - if (isInstalled) { - // We are looking for a specific major version. - if (instanceInfo.Version.size() < wantVersion.size() || - instanceInfo.Version.substr(0, wantVersion.size()) != wantVersion) { - continue; + if (!this->SpecifiedVSInstallLocation.empty()) { + // We are looking for a specific instance. + 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; } - - if (!this->SpecifiedVSInstallLocation.empty()) { - // We are looking for a specific instance. - std::string currentVSLocation = instanceInfo.GetInstallLocation(); + } else if (!this->SpecifiedVSInstallVersion.empty()) { + // We are looking for a specific version. + if (instanceInfo.Version == this->SpecifiedVSInstallVersion) { + chosenInstanceInfo = instanceInfo; + return true; + } + } else { + // We are not looking for a specific instance. + // If we've been given a hint then use it. + if (!envVSCommonToolsDir.empty()) { + std::string currentVSLocation = + cmStrCat(instanceInfo.GetInstallLocation(), "/Common7/Tools"); 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) { + envVSCommonToolsDir)) { chosenInstanceInfo = instanceInfo; return true; } - } else { - // We are not looking for a specific instance. - // If we've been given a hint then use it. - if (!envVSCommonToolsDir.empty()) { - std::string currentVSLocation = - cmStrCat(instanceInfo.GetInstallLocation(), "/Common7/Tools"); - if (cmSystemTools::ComparePath(currentVSLocation, - envVSCommonToolsDir)) { - chosenInstanceInfo = instanceInfo; - return true; - } - } - // Otherwise, add this to the list of candidates. - vecVSInstances.push_back(instanceInfo); } + // Otherwise, add this to the list of candidates. + vecVSInstances.push_back(instanceInfo); } } diff --git a/Source/cmVSSetupHelper.h b/Source/cmVSSetupHelper.h index 44c883b..a16f00b 100644 --- a/Source/cmVSSetupHelper.h +++ b/Source/cmVSSetupHelper.h @@ -118,6 +118,9 @@ private: int ChooseVSInstance(const std::vector<VSInstanceInfo>& vecVSInstances); bool EnumerateAndChooseVSInstance(); bool LoadSpecifiedVSInstanceFromDisk(); + bool EnumerateVSInstancesWithVswhere( + std::vector<VSInstanceInfo>& VSInstances); + bool EnumerateVSInstancesWithCOM(std::vector<VSInstanceInfo>& VSInstances); unsigned int Version; |