From 7dab5bd550c35d4bfdc70550b43e67837e3b7a0d Mon Sep 17 00:00:00 2001 From: David Schulz Date: Fri, 23 Apr 2021 12:00:49 +0200 Subject: [PATCH] ProjectExplorer: Fix msvc toolschain abi compatibility MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Reviewed-by: Alessandro Portale --- src/plugins/projectexplorer/abi.cpp | 8 ------ src/plugins/projectexplorer/abi.h | 1 - src/plugins/projectexplorer/msvctoolchain.cpp | 27 +++++++++++++++++++ src/plugins/projectexplorer/msvctoolchain.h | 1 + src/plugins/qtsupport/baseqtversion.cpp | 10 ++++--- src/plugins/qtsupport/qtkitinformation.cpp | 9 +++---- 6 files changed, 39 insertions(+), 17 deletions(-) diff --git a/src/plugins/projectexplorer/abi.cpp b/src/plugins/projectexplorer/abi.cpp index 6c88c4fe1a0..f60d584d564 100644 --- a/src/plugins/projectexplorer/abi.cpp +++ b/src/plugins/projectexplorer/abi.cpp @@ -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 diff --git a/src/plugins/projectexplorer/abi.h b/src/plugins/projectexplorer/abi.h index 3657c75d08d..fbc868cb5e3 100644 --- a/src/plugins/projectexplorer/abi.h +++ b/src/plugins/projectexplorer/abi.h @@ -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; diff --git a/src/plugins/projectexplorer/msvctoolchain.cpp b/src/plugins/projectexplorer/msvctoolchain.cpp index 8e70a2330c4..bd1087a84c6 100644 --- a/src/plugins/projectexplorer/msvctoolchain.cpp +++ b/src/plugins/projectexplorer/msvctoolchain.cpp @@ -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(); diff --git a/src/plugins/projectexplorer/msvctoolchain.h b/src/plugins/projectexplorer/msvctoolchain.h index b74911c9dba..f81566a0fc5 100644 --- a/src/plugins/projectexplorer/msvctoolchain.h +++ b/src/plugins/projectexplorer/msvctoolchain.h @@ -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; diff --git a/src/plugins/qtsupport/baseqtversion.cpp b/src/plugins/qtsupport/baseqtversion.cpp index c2d37968b25..454c0d7b01f 100644 --- a/src/plugins/qtsupport/baseqtversion.cpp +++ b/src/plugins/qtsupport/baseqtversion.cpp @@ -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; diff --git a/src/plugins/qtsupport/qtkitinformation.cpp b/src/plugins/qtsupport/qtkitinformation.cpp index a1411598f27..d6aca91001a 100644 --- a/src/plugins/qtsupport/qtkitinformation.cpp +++ b/src/plugins/qtsupport/qtkitinformation.cpp @@ -222,11 +222,10 @@ void QtKitAspect::fix(Kit *k) const QString spec = version->mkspec(); QList 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.