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 <eike.ziller@qt.io>
Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
Reviewed-by: David Schulz <david.schulz@qt.io>
Reviewed-by: Tobias Hunger <tobias.hunger@qt.io>
This commit is contained in:
Friedemann Kleint
2016-11-18 16:27:25 +01:00
parent e7d6f8e514
commit 4c29f5fc8f
4 changed files with 150 additions and 104 deletions

View File

@@ -695,6 +695,8 @@ QString Abi::toString(const OSFlavor &of)
return QLatin1String("msvc2013"); return QLatin1String("msvc2013");
case Abi::WindowsMsvc2015Flavor: case Abi::WindowsMsvc2015Flavor:
return QLatin1String("msvc2015"); return QLatin1String("msvc2015");
case Abi::WindowsMsvc2017Flavor:
return QLatin1String("msvc2017");
case Abi::WindowsMSysFlavor: case Abi::WindowsMSysFlavor:
return QLatin1String("msys"); return QLatin1String("msys");
case Abi::WindowsCEFlavor: case Abi::WindowsCEFlavor:

View File

@@ -85,6 +85,7 @@ public:
WindowsMsvc2012Flavor, WindowsMsvc2012Flavor,
WindowsMsvc2013Flavor, WindowsMsvc2013Flavor,
WindowsMsvc2015Flavor, WindowsMsvc2015Flavor,
WindowsMsvc2017Flavor,
WindowsMSysFlavor, WindowsMSysFlavor,
WindowsCEFlavor, WindowsCEFlavor,

View File

@@ -38,6 +38,8 @@
#include <QFileInfo> #include <QFileInfo>
#include <QProcess> #include <QProcess>
#include <QSettings> #include <QSettings>
#include <QVector>
#include <QVersionNumber>
#include <QLabel> #include <QLabel>
#include <QFormLayout> #include <QFormLayout>
@@ -56,28 +58,39 @@ namespace Internal {
// Helpers: // 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) static QString platformName(MsvcToolChain::Platform t)
{ {
switch (t) { if (const MsvcPlatform *p = platformEntry(t))
case MsvcToolChain::x86: return QLatin1String(p->name);
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");
}
return QString(); 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<VisualStudioInstallation> detectVisualStudio()
{
QVector<VisualStudioInstallation> 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<QSettings> 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) static Abi findAbiOfMsvc(MsvcToolChain::Type type, MsvcToolChain::Platform platform, const QString &version)
{ {
Abi::Architecture arch = Abi::X86Architecture; 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")) else if (version == QLatin1String("v7.0A") || version == QLatin1String("v7.1"))
msvcVersionString = QLatin1String("10.0"); 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; flavor = Abi::WindowsMsvc2015Flavor;
else if (msvcVersionString.startsWith(QLatin1String("12."))) else if (msvcVersionString.startsWith(QLatin1String("12.")))
flavor = Abi::WindowsMsvc2013Flavor; flavor = Abi::WindowsMsvc2013Flavor;
@@ -384,6 +471,9 @@ Utils::FileNameList MsvcToolChain::suggestedMkspecList() const
<< Utils::FileName::fromLatin1("winrt-arm-msvc2015") << Utils::FileName::fromLatin1("winrt-arm-msvc2015")
<< Utils::FileName::fromLatin1("winrt-x86-msvc2015") << Utils::FileName::fromLatin1("winrt-x86-msvc2015")
<< Utils::FileName::fromLatin1("winrt-x64-msvc2015"); << Utils::FileName::fromLatin1("winrt-x64-msvc2015");
case Abi::WindowsMsvc2017Flavor:
return Utils::FileNameList()
<< Utils::FileName::fromLatin1("win32-msvc2017");
default: default:
break; break;
} }
@@ -576,45 +666,19 @@ QSet<ToolChain::Language> MsvcToolChainFactory::supportedLanguages() const
return { ToolChain::Language::C, ToolChain::Language::Cxx }; 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( QString result;
#ifdef Q_OS_WIN64 if (const MsvcPlatform *p = platformEntry(platform)) {
QLatin1String("HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\VisualStudio\\SxS\\VS7"), result += basePath;
#else // Starting with 15.0 (MSVC2017), the .bat are in one folder.
QLatin1String("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\SxS\\VS7"), if (v.majorVersion() <= 14)
#endif result += QLatin1String(p->prefix);
QSettings::NativeFormat); result += QLatin1Char('/');
result += QLatin1String(p->bat);
return vsRegistry.contains(vsName); }
} return result;
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();
} }
static QList<ToolChain *> findOrCreateToolChain( static QList<ToolChain *> findOrCreateToolChain(
@@ -773,50 +837,29 @@ QList<ToolChain *> MsvcToolChainFactory::autoDetect(const QList<ToolChain *> &al
} }
// 2) Installed MSVCs // 2) Installed MSVCs
const QSettings vsRegistry( // prioritized list.
#ifdef Q_OS_WIN64 // x86_arm was put before amd64_arm as a workaround for auto detected windows phone
QLatin1String("HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\VisualStudio\\SxS\\VC7"), // toolchains. As soon as windows phone builds support x64 cross builds, this change
#else // can be reverted.
QLatin1String("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\SxS\\VC7"), const MsvcToolChain::Platform platforms[] = {
#endif MsvcToolChain::x86, MsvcToolChain::amd64_x86,
QSettings::NativeFormat); MsvcToolChain::amd64, MsvcToolChain::x86_amd64,
foreach (const QString &vsName, vsRegistry.allKeys()) { MsvcToolChain::arm, MsvcToolChain::x86_arm, MsvcToolChain::amd64_arm,
// Scan for version major.minor MsvcToolChain::ia64, MsvcToolChain::x86_ia64
const int dotPos = vsName.indexOf(QLatin1Char('.')); };
if (dotPos == -1)
continue;
if (!checkForVisualStudioInstallation(vsName))
continue;
QString path = QDir::fromNativeSeparators(vsRegistry.value(vsName).toString()); foreach (const VisualStudioInstallation &i, detectVisualStudio()) {
if (path.endsWith(QLatin1Char('/'))) for (MsvcToolChain::Platform platform : platforms) {
path.chop(1); const bool toolchainInstalled =
const int version = vsName.leftRef(dotPos).toInt(); QFileInfo(vcVarsBatFor(i.vcVarsPath, platform, i.version)).isFile();
const QString vcvarsAllbat = path + QLatin1String("/vcvarsall.bat"); if (hostSupportsPlatform(platform) && toolchainInstalled) {
if (QFileInfo(vcvarsAllbat).isFile()) { results.append(findOrCreateToolChain(
// prioritized list. alreadyKnown,
// x86_arm was put before amd64_arm as a workaround for auto detected windows phone generateDisplayName(i.vsName, MsvcToolChain::VS, platform),
// toolchains. As soon as windows phone builds support x64 cross builds, this change findAbiOfMsvc(MsvcToolChain::VS, platform, i.vsName),
// can be reverted. i.vcVarsAll, platformName(platform),
const QVector<MsvcToolChain::Platform> platforms = { ToolChain::AutoDetection));
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));
}
} }
} else {
qWarning("Unable to find MSVC setup script %s in version %d", qPrintable(vcvarsAllbat), version);
} }
} }

View File

@@ -30,6 +30,7 @@
#include "toolchainconfigwidget.h" #include "toolchainconfigwidget.h"
QT_FORWARD_DECLARE_CLASS(QLabel) QT_FORWARD_DECLARE_CLASS(QLabel)
QT_FORWARD_DECLARE_CLASS(QVersionNumber)
namespace ProjectExplorer { namespace ProjectExplorer {
namespace Internal { namespace Internal {
@@ -133,9 +134,8 @@ public:
ToolChain *restore(const QVariantMap &data) override; ToolChain *restore(const QVariantMap &data) override;
ToolChainConfigWidget *configurationWidget(ToolChain *); ToolChainConfigWidget *configurationWidget(ToolChain *);
static QString vcVarsBatFor(const QString &basePath, MsvcToolChain::Platform platform); static QString vcVarsBatFor(const QString &basePath, MsvcToolChain::Platform platform,
private: const QVersionNumber &v);
static bool checkForVisualStudioInstallation(const QString &vsName);
}; };
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------