ProjectExplorer: Fix msvc toolschain abi compatibility

According to MSDN: "You can mix binaries built by different versions of
the v140, v141, and v142 toolsets. However, you must link by using a
toolset at least as recent as the most recent binary in your app. Here's
an example: you can link an app compiled using any 2017 toolset (v141,
versions 15.0 through 15.9) to a static library compiled using, say,
Visual Studio 2019 version 16.2 (v142), if they're linked using a
version 16.2 or later toolset. You can link a version 16.2 library to a
version 16.4 app as long as you use a 16.4 or later toolset."

https://docs.microsoft.com/en-us/cpp/porting/binary-compat-2015-2017?
view=msvc-160

So don't try to assign an older msvc toolchain to a kit that contains a
Qt build with a newer version of msvc.

Fixes: QTCREATORBUG-25618
Change-Id: If58676da5f61add1eed7e786862ee475e180b7dc
Reviewed-by: Robert Löhning <robert.loehning@qt.io>
Reviewed-by: Alessandro Portale <alessandro.portale@qt.io>
This commit is contained in:
David Schulz
2021-04-23 12:00:49 +02:00
parent b3e0074126
commit 7dab5bd550
6 changed files with 39 additions and 17 deletions

View File

@@ -726,14 +726,6 @@ bool Abi::isCompatibleWith(const Abi &other) const
return isCompat; return isCompat;
} }
bool Abi::isFullyCompatibleWith(const Abi &other) const
{
return *this == other
|| (wordWidth() == other.wordWidth()
&& architecture() == other.architecture()
&& compatibleMSVCFlavors(osFlavor(), other.osFlavor()));
}
bool Abi::isValid() const bool Abi::isValid() const
{ {
return m_architecture != UnknownArchitecture return m_architecture != UnknownArchitecture

View File

@@ -148,7 +148,6 @@ public:
bool operator != (const Abi &other) const; bool operator != (const Abi &other) const;
bool operator == (const Abi &other) const; bool operator == (const Abi &other) const;
bool isCompatibleWith(const Abi &other) const; bool isCompatibleWith(const Abi &other) const;
bool isFullyCompatibleWith(const Abi &other) const;
bool isValid() const; bool isValid() const;
bool isNull() const; bool isNull() const;

View File

@@ -908,6 +908,33 @@ QStringList MsvcToolChain::suggestedMkspecList() const
return {}; return {};
} }
Abis MsvcToolChain::supportedAbis() const
{
Abi abi = targetAbi();
Abis abis = {abi};
switch (abi.osFlavor()) {
case Abi::WindowsMsvc2019Flavor:
abis << Abi(abi.architecture(),
abi.os(),
Abi::WindowsMsvc2017Flavor,
abi.binaryFormat(),
abi.wordWidth(),
abi.param());
Q_FALLTHROUGH();
case Abi::WindowsMsvc2017Flavor:
abis << Abi(abi.architecture(),
abi.os(),
Abi::WindowsMsvc2015Flavor,
abi.binaryFormat(),
abi.wordWidth(),
abi.param());
break;
default:
break;
}
return abis;
}
QVariantMap MsvcToolChain::toMap() const QVariantMap MsvcToolChain::toMap() const
{ {
QVariantMap data = ToolChain::toMap(); QVariantMap data = ToolChain::toMap();

View File

@@ -67,6 +67,7 @@ public:
QString originalTargetTriple() const override; QString originalTargetTriple() const override;
QStringList suggestedMkspecList() const override; QStringList suggestedMkspecList() const override;
Abis supportedAbis() const override;
QVariantMap toMap() const override; QVariantMap toMap() const override;
bool fromMap(const QVariantMap &data) override; bool fromMap(const QVariantMap &data) override;

View File

@@ -516,6 +516,7 @@ Tasks BaseQtVersion::validateKit(const Kit *k)
if (ToolChain *tc = ToolChainKitAspect::cxxToolChain(k)) { if (ToolChain *tc = ToolChainKitAspect::cxxToolChain(k)) {
Abi targetAbi = tc->targetAbi(); Abi targetAbi = tc->targetAbi();
Abis supportedAbis = tc->supportedAbis();
bool fuzzyMatch = false; bool fuzzyMatch = false;
bool fullMatch = false; bool fullMatch = false;
@@ -526,9 +527,12 @@ Tasks BaseQtVersion::validateKit(const Kit *k)
qtAbiString.append(qtAbi.toString()); qtAbiString.append(qtAbi.toString());
if (!fullMatch) if (!fullMatch)
fullMatch = targetAbi.isFullyCompatibleWith(qtAbi); fullMatch = supportedAbis.contains(qtAbi);
if (!fuzzyMatch) if (!fuzzyMatch && !fullMatch) {
fuzzyMatch = targetAbi.isCompatibleWith(qtAbi); fuzzyMatch = Utils::anyOf(supportedAbis, [&](const Abi &abi) {
return qtAbi.isCompatibleWith(abi);
});
}
} }
QString message; QString message;

View File

@@ -222,11 +222,10 @@ void QtKitAspect::fix(Kit *k)
const QString spec = version->mkspec(); const QString spec = version->mkspec();
QList<ToolChain *> possibleTcs = ToolChainManager::toolChains([version](const ToolChain *t) { QList<ToolChain *> possibleTcs = ToolChainManager::toolChains([version](const ToolChain *t) {
return t->isValid() if (!t->isValid() || t->language() != ProjectExplorer::Constants::CXX_LANGUAGE_ID)
&& t->language() == ProjectExplorer::Constants::CXX_LANGUAGE_ID return false;
&& contains(version->qtAbis(), [t](const Abi &qtAbi) { return Utils::anyOf(version->qtAbis(),
return qtAbi.isFullyCompatibleWith(t->targetAbi()); [t](const Abi &qtAbi) { return t->supportedAbis().contains(qtAbi); });
});
}); });
if (!possibleTcs.isEmpty()) { if (!possibleTcs.isEmpty()) {
// Prefer exact matches. // Prefer exact matches.