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;
}
bool Abi::isFullyCompatibleWith(const Abi &other) const
{
return *this == other
|| (wordWidth() == other.wordWidth()
&& architecture() == other.architecture()
&& compatibleMSVCFlavors(osFlavor(), other.osFlavor()));
}
bool Abi::isValid() const
{
return m_architecture != UnknownArchitecture

View File

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

View File

@@ -908,6 +908,33 @@ QStringList MsvcToolChain::suggestedMkspecList() const
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 data = ToolChain::toMap();

View File

@@ -67,6 +67,7 @@ public:
QString originalTargetTriple() const override;
QStringList suggestedMkspecList() const override;
Abis supportedAbis() const override;
QVariantMap toMap() const 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)) {
Abi targetAbi = tc->targetAbi();
Abis supportedAbis = tc->supportedAbis();
bool fuzzyMatch = false;
bool fullMatch = false;
@@ -526,9 +527,12 @@ Tasks BaseQtVersion::validateKit(const Kit *k)
qtAbiString.append(qtAbi.toString());
if (!fullMatch)
fullMatch = targetAbi.isFullyCompatibleWith(qtAbi);
if (!fuzzyMatch)
fuzzyMatch = targetAbi.isCompatibleWith(qtAbi);
fullMatch = supportedAbis.contains(qtAbi);
if (!fuzzyMatch && !fullMatch) {
fuzzyMatch = Utils::anyOf(supportedAbis, [&](const Abi &abi) {
return qtAbi.isCompatibleWith(abi);
});
}
}
QString message;

View File

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