From 4c29f5fc8fb88dfaff6b0bc1984925c2da51a09c Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 18 Nov 2016 16:27:25 +0100 Subject: [PATCH] Add support for Visual Studio 15.0 (MSVC2017) Extend ABI by flavor and add look-up. As with each major update, rewrite the the MSVC toolchain autodetection. Previously, the detection looped over the entries in "VC" registry section and checked in the "VS" section whether a valid installation belonged to the entry. MSVC2017 no longer has an entry in the "VC" section. Introduce a struct describing the installation including version number and rewrite the loop to run over the "VS" section and retrieve the VC path from the "VC" section only for versions <= 14.0. Also, the various .bat files for the target architecture are now in a single folder instead of spread around various bin/XXX subfolders. Introduce an array of structs for the platform that has the prefix and .bat name and uses the prefix only for versions <= 14.0. Task-number: QTBUG-57086 Change-Id: I947edd885c0a379f196440041c07d60cd4244d9c Reviewed-by: Eike Ziller Reviewed-by: Joerg Bornemann Reviewed-by: David Schulz Reviewed-by: Tobias Hunger --- src/plugins/projectexplorer/abi.cpp | 2 + src/plugins/projectexplorer/abi.h | 1 + src/plugins/projectexplorer/msvctoolchain.cpp | 245 ++++++++++-------- src/plugins/projectexplorer/msvctoolchain.h | 6 +- 4 files changed, 150 insertions(+), 104 deletions(-) diff --git a/src/plugins/projectexplorer/abi.cpp b/src/plugins/projectexplorer/abi.cpp index 783e40664bc..7000b2b402b 100644 --- a/src/plugins/projectexplorer/abi.cpp +++ b/src/plugins/projectexplorer/abi.cpp @@ -695,6 +695,8 @@ QString Abi::toString(const OSFlavor &of) return QLatin1String("msvc2013"); case Abi::WindowsMsvc2015Flavor: return QLatin1String("msvc2015"); + case Abi::WindowsMsvc2017Flavor: + return QLatin1String("msvc2017"); case Abi::WindowsMSysFlavor: return QLatin1String("msys"); case Abi::WindowsCEFlavor: diff --git a/src/plugins/projectexplorer/abi.h b/src/plugins/projectexplorer/abi.h index 0e12adf0540..8c4e285b607 100644 --- a/src/plugins/projectexplorer/abi.h +++ b/src/plugins/projectexplorer/abi.h @@ -85,6 +85,7 @@ public: WindowsMsvc2012Flavor, WindowsMsvc2013Flavor, WindowsMsvc2015Flavor, + WindowsMsvc2017Flavor, WindowsMSysFlavor, WindowsCEFlavor, diff --git a/src/plugins/projectexplorer/msvctoolchain.cpp b/src/plugins/projectexplorer/msvctoolchain.cpp index fab0226c40b..a2a9c64d5c6 100644 --- a/src/plugins/projectexplorer/msvctoolchain.cpp +++ b/src/plugins/projectexplorer/msvctoolchain.cpp @@ -38,6 +38,8 @@ #include #include #include +#include +#include #include #include @@ -56,28 +58,39 @@ namespace Internal { // Helpers: // -------------------------------------------------------------------------- +struct MsvcPlatform { + MsvcToolChain::Platform platform; + const char *name; + const char *prefix; // VS up until 14.0 (MSVC2015) + const char *bat; +}; + +const MsvcPlatform platforms[] = +{ + { MsvcToolChain::x86, "x86", "/bin", "vcvars32.bat" }, + { MsvcToolChain::amd64, "amd64", "/bin/amd64", "vcvars64.bat" }, + { MsvcToolChain::x86_amd64, "x86_amd64", "/bin/x86_amd64", "vcvarsx86_amd64.bat" }, + { MsvcToolChain::ia64, "ia64", "/bin/ia64", "vcvars64.bat" }, + { MsvcToolChain::x86_ia64, "x86_ia64", "/bin/x86_ia64", "vcvarsx86_ia64.bat" }, + { MsvcToolChain::arm, "arm", "/bin/arm", "vcvarsarm.bat" }, + { MsvcToolChain::x86_arm, "x86_arm", "/bin/x86_arm", "vcvarsx86_arm.bat" }, + { MsvcToolChain::amd64_arm, "amd64_arm", "/bin/amd64_arm", "vcvarsamd64_arm.bat" }, + { MsvcToolChain::amd64_x86, "amd64_x86", "/bin/amd64_x86", "vcvarsamd64_x86.bat" } +}; + +static const MsvcPlatform *platformEntry(MsvcToolChain::Platform t) +{ + for (const MsvcPlatform &p : platforms) { + if (p.platform == t) + return &p; + } + return nullptr; +} + static QString platformName(MsvcToolChain::Platform t) { - switch (t) { - case MsvcToolChain::x86: - return QLatin1String("x86"); - case MsvcToolChain::amd64_x86: - return QLatin1String("amd64_x86"); - case MsvcToolChain::amd64: - return QLatin1String("amd64"); - case MsvcToolChain::x86_amd64: - return QLatin1String("x86_amd64"); - case MsvcToolChain::ia64: - return QLatin1String("ia64"); - case MsvcToolChain::x86_ia64: - return QLatin1String("x86_ia64"); - case MsvcToolChain::arm: - return QLatin1String("arm"); - case MsvcToolChain::x86_arm: - return QLatin1String("x86_arm"); - case MsvcToolChain::amd64_arm: - return QLatin1String("amd64_arm"); - } + if (const MsvcPlatform *p = platformEntry(t)) + return QLatin1String(p->name); return QString(); } @@ -101,6 +114,78 @@ static bool hostSupportsPlatform(MsvcToolChain::Platform platform) } } +static QString fixRegistryPath(const QString &path) +{ + QString result = QDir::fromNativeSeparators(path); + if (result.endsWith(QLatin1Char('/'))) + result.chop(1); + return result; +} + +struct VisualStudioInstallation +{ + QString vsName; + QVersionNumber version; + QString path; // Main installation path + QString vcVarsPath; // Path under which the various vc..bat are to be found + QString vcVarsAll; +}; + +QDebug operator<<(QDebug d, const VisualStudioInstallation &i) +{ + QDebugStateSaver saver(d); + d.noquote(); + d.nospace(); + d << "VisualStudioInstallation(\"" << i.vsName << "\", v=" << i.version + << ", path=\"" << QDir::toNativeSeparators(i.path) + << "\", vcVarsPath=\"" << QDir::toNativeSeparators(i.vcVarsPath) + << "\", vcVarsAll=\"" << QDir::toNativeSeparators(i.vcVarsAll) << "\")"; + return d; +} + +static QVector detectVisualStudio() +{ + QVector result; +#ifdef Q_OS_WIN64 + const QString keyRoot = QStringLiteral("HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\VisualStudio\\SxS\\"); +#else + const QString keyRoot = QStringLiteral("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\SxS\\"); +#endif + QSettings vsRegistry(keyRoot + QStringLiteral("VS7"), QSettings::NativeFormat); + QScopedPointer vcRegistry; + const QString vcvarsall = QStringLiteral("/vcvarsall.bat"); + foreach (const QString &vsName, vsRegistry.allKeys()) { + const QVersionNumber version = QVersionNumber::fromString(vsName); + if (!version.isNull()) { + VisualStudioInstallation installation; + installation.vsName = vsName; + installation.version = version; + if (version.majorVersion() > 14) { + // Starting with 15 (MSVC2017): There are no more VC entries, + // build path from VS installation + installation.path = fixRegistryPath(vsRegistry.value(vsName).toString()); + installation.vcVarsPath = installation.path + QStringLiteral("/VC/Auxiliary/Build"); + installation.vcVarsAll = installation.vcVarsPath + vcvarsall; + } else { + // Up to 14 (MSVC2015): Look up via matching VC entry + if (vcRegistry.isNull()) + vcRegistry.reset(new QSettings(keyRoot + QStringLiteral("VC7"), QSettings::NativeFormat)); + installation.path = fixRegistryPath(vcRegistry->value(vsName).toString()); + installation.vcVarsPath = installation.path; + installation.vcVarsAll = installation.vcVarsPath + vcvarsall; + } + if (QFileInfo(installation.vcVarsAll).isFile()) { + result.append(installation); + } else { + qWarning().noquote() << "Unable to find MSVC setup script " + << QDir::toNativeSeparators(installation.vcVarsPath) << " in version " + << version; + } + } + } + return result; +} + static Abi findAbiOfMsvc(MsvcToolChain::Type type, MsvcToolChain::Platform platform, const QString &version) { Abi::Architecture arch = Abi::X86Architecture; @@ -135,7 +220,9 @@ static Abi findAbiOfMsvc(MsvcToolChain::Type type, MsvcToolChain::Platform platf else if (version == QLatin1String("v7.0A") || version == QLatin1String("v7.1")) msvcVersionString = QLatin1String("10.0"); } - if (msvcVersionString.startsWith(QLatin1String("14."))) + if (msvcVersionString.startsWith(QLatin1String("15."))) + flavor = Abi::WindowsMsvc2017Flavor; + else if (msvcVersionString.startsWith(QLatin1String("14."))) flavor = Abi::WindowsMsvc2015Flavor; else if (msvcVersionString.startsWith(QLatin1String("12."))) flavor = Abi::WindowsMsvc2013Flavor; @@ -384,6 +471,9 @@ Utils::FileNameList MsvcToolChain::suggestedMkspecList() const << Utils::FileName::fromLatin1("winrt-arm-msvc2015") << Utils::FileName::fromLatin1("winrt-x86-msvc2015") << Utils::FileName::fromLatin1("winrt-x64-msvc2015"); + case Abi::WindowsMsvc2017Flavor: + return Utils::FileNameList() + << Utils::FileName::fromLatin1("win32-msvc2017"); default: break; } @@ -576,45 +666,19 @@ QSet MsvcToolChainFactory::supportedLanguages() const return { ToolChain::Language::C, ToolChain::Language::Cxx }; } -bool MsvcToolChainFactory::checkForVisualStudioInstallation(const QString &vsName) +QString MsvcToolChainFactory::vcVarsBatFor(const QString &basePath, MsvcToolChain::Platform platform, + const QVersionNumber &v) { - const QSettings vsRegistry( -#ifdef Q_OS_WIN64 - QLatin1String("HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\VisualStudio\\SxS\\VS7"), -#else - QLatin1String("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\SxS\\VS7"), -#endif - QSettings::NativeFormat); - - return vsRegistry.contains(vsName); -} - -QString MsvcToolChainFactory::vcVarsBatFor(const QString &basePath, MsvcToolChain::Platform platform) -{ - const QString toolchainName = platformName(platform); - - if (toolchainName.startsWith(QLatin1Char('/'))) // windows sdk case, all use SetEnv.cmd - return basePath + QLatin1String("/SetEnv.cmd"); - if (toolchainName == QLatin1String("x86")) - return basePath + QLatin1String("/bin/vcvars32.bat"); - if (toolchainName == QLatin1String("amd64_arm")) - return basePath + QLatin1String("/bin/amd64_arm/vcvarsamd64_arm.bat"); - if (toolchainName == QLatin1String("x86_amd64")) - return basePath + QLatin1String("/bin/x86_amd64/vcvarsx86_amd64.bat"); - if (toolchainName == QLatin1String("amd64")) - return basePath + QLatin1String("/bin/amd64/vcvars64.bat"); - if (toolchainName == QLatin1String("x86_arm")) - return basePath + QLatin1String("/bin/x86_arm/vcvarsx86_arm.bat"); - if (toolchainName == QLatin1String("arm")) - return basePath + QLatin1String("/bin/arm/vcvarsarm.bat"); - if (toolchainName == QLatin1String("ia64")) - return basePath + QLatin1String("/bin/ia64/vcvars64.bat"); - if (toolchainName == QLatin1String("x86_ia64")) - return basePath + QLatin1String("/bin/x86_ia64/vcvarsx86_ia64.bat"); - if (toolchainName == QLatin1String("amd64_x86")) - return basePath + QLatin1String("/bin/amd64_x86/vcvarsamd64_x86.bat"); - - return QString(); + QString result; + if (const MsvcPlatform *p = platformEntry(platform)) { + result += basePath; + // Starting with 15.0 (MSVC2017), the .bat are in one folder. + if (v.majorVersion() <= 14) + result += QLatin1String(p->prefix); + result += QLatin1Char('/'); + result += QLatin1String(p->bat); + } + return result; } static QList findOrCreateToolChain( @@ -773,50 +837,29 @@ QList MsvcToolChainFactory::autoDetect(const QList &al } // 2) Installed MSVCs - const QSettings vsRegistry( -#ifdef Q_OS_WIN64 - QLatin1String("HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\VisualStudio\\SxS\\VC7"), -#else - QLatin1String("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\SxS\\VC7"), -#endif - QSettings::NativeFormat); - foreach (const QString &vsName, vsRegistry.allKeys()) { - // Scan for version major.minor - const int dotPos = vsName.indexOf(QLatin1Char('.')); - if (dotPos == -1) - continue; - if (!checkForVisualStudioInstallation(vsName)) - continue; + // prioritized list. + // x86_arm was put before amd64_arm as a workaround for auto detected windows phone + // toolchains. As soon as windows phone builds support x64 cross builds, this change + // can be reverted. + const MsvcToolChain::Platform platforms[] = { + MsvcToolChain::x86, MsvcToolChain::amd64_x86, + MsvcToolChain::amd64, MsvcToolChain::x86_amd64, + MsvcToolChain::arm, MsvcToolChain::x86_arm, MsvcToolChain::amd64_arm, + MsvcToolChain::ia64, MsvcToolChain::x86_ia64 + }; - QString path = QDir::fromNativeSeparators(vsRegistry.value(vsName).toString()); - if (path.endsWith(QLatin1Char('/'))) - path.chop(1); - const int version = vsName.leftRef(dotPos).toInt(); - const QString vcvarsAllbat = path + QLatin1String("/vcvarsall.bat"); - if (QFileInfo(vcvarsAllbat).isFile()) { - // prioritized list. - // x86_arm was put before amd64_arm as a workaround for auto detected windows phone - // toolchains. As soon as windows phone builds support x64 cross builds, this change - // can be reverted. - const QVector platforms = { - MsvcToolChain::x86, MsvcToolChain::amd64_x86, - MsvcToolChain::amd64, MsvcToolChain::x86_amd64, - MsvcToolChain::arm, MsvcToolChain::x86_arm, MsvcToolChain::amd64_arm, - MsvcToolChain::ia64, MsvcToolChain::x86_ia64 - }; - foreach (const MsvcToolChain::Platform &platform, platforms) { - const bool toolchainInstalled = QFileInfo(vcVarsBatFor(path, platform)).isFile(); - if (hostSupportsPlatform(platform) && toolchainInstalled) { - results.append(findOrCreateToolChain( - alreadyKnown, - generateDisplayName(vsName, MsvcToolChain::VS, platform), - findAbiOfMsvc(MsvcToolChain::VS, platform, vsName), - vcvarsAllbat, platformName(platform), - ToolChain::AutoDetection)); - } + foreach (const VisualStudioInstallation &i, detectVisualStudio()) { + for (MsvcToolChain::Platform platform : platforms) { + const bool toolchainInstalled = + QFileInfo(vcVarsBatFor(i.vcVarsPath, platform, i.version)).isFile(); + if (hostSupportsPlatform(platform) && toolchainInstalled) { + results.append(findOrCreateToolChain( + alreadyKnown, + generateDisplayName(i.vsName, MsvcToolChain::VS, platform), + findAbiOfMsvc(MsvcToolChain::VS, platform, i.vsName), + i.vcVarsAll, platformName(platform), + ToolChain::AutoDetection)); } - } else { - qWarning("Unable to find MSVC setup script %s in version %d", qPrintable(vcvarsAllbat), version); } } diff --git a/src/plugins/projectexplorer/msvctoolchain.h b/src/plugins/projectexplorer/msvctoolchain.h index 8f8ead3546d..3f04053dacf 100644 --- a/src/plugins/projectexplorer/msvctoolchain.h +++ b/src/plugins/projectexplorer/msvctoolchain.h @@ -30,6 +30,7 @@ #include "toolchainconfigwidget.h" QT_FORWARD_DECLARE_CLASS(QLabel) +QT_FORWARD_DECLARE_CLASS(QVersionNumber) namespace ProjectExplorer { namespace Internal { @@ -133,9 +134,8 @@ public: ToolChain *restore(const QVariantMap &data) override; ToolChainConfigWidget *configurationWidget(ToolChain *); - static QString vcVarsBatFor(const QString &basePath, MsvcToolChain::Platform platform); -private: - static bool checkForVisualStudioInstallation(const QString &vsName); + static QString vcVarsBatFor(const QString &basePath, MsvcToolChain::Platform platform, + const QVersionNumber &v); }; // --------------------------------------------------------------------------