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");
case Abi::WindowsMsvc2015Flavor:
return QLatin1String("msvc2015");
case Abi::WindowsMsvc2017Flavor:
return QLatin1String("msvc2017");
case Abi::WindowsMSysFlavor:
return QLatin1String("msys");
case Abi::WindowsCEFlavor:

View File

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

View File

@@ -38,6 +38,8 @@
#include <QFileInfo>
#include <QProcess>
#include <QSettings>
#include <QVector>
#include <QVersionNumber>
#include <QLabel>
#include <QFormLayout>
@@ -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<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)
{
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<ToolChain::Language> 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 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);
}
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();
return result;
}
static QList<ToolChain *> findOrCreateToolChain(
@@ -773,51 +837,30 @@ QList<ToolChain *> MsvcToolChainFactory::autoDetect(const QList<ToolChain *> &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;
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<MsvcToolChain::Platform> platforms = {
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
};
foreach (const MsvcToolChain::Platform &platform, platforms) {
const bool toolchainInstalled = QFileInfo(vcVarsBatFor(path, platform)).isFile();
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(vsName, MsvcToolChain::VS, platform),
findAbiOfMsvc(MsvcToolChain::VS, platform, vsName),
vcvarsAllbat, platformName(platform),
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);
}
}
detectCppBuildTools(&results);

View File

@@ -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);
};
// --------------------------------------------------------------------------