forked from qt-creator/qt-creator
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:
@@ -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:
|
||||
|
@@ -85,6 +85,7 @@ public:
|
||||
WindowsMsvc2012Flavor,
|
||||
WindowsMsvc2013Flavor,
|
||||
WindowsMsvc2015Flavor,
|
||||
WindowsMsvc2017Flavor,
|
||||
WindowsMSysFlavor,
|
||||
WindowsCEFlavor,
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
Reference in New Issue
Block a user