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