ProjectExplorer: Give Xcode clang higher priority than "bare" clang

If Xcode is present, we want its toolchain in the default kit, rather
than a generic compiler from /usr/bin.

Change-Id: If5d1dc02b6abcfff580162a19f07706d58681b7e
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
This commit is contained in:
Christian Kandeler
2022-08-17 11:14:11 +02:00
parent 2b64232eba
commit f49f9b43da
5 changed files with 45 additions and 14 deletions

View File

@@ -587,6 +587,7 @@ Toolchains IosToolChainFactory::autoDetect(const ToolchainDetector &detector) co
auto createOrAdd = [&](ClangToolChain *toolChain, Id l) {
if (!toolChain) {
toolChain = new ClangToolChain;
toolChain->setPriority(ToolChain::PriorityHigh);
toolChain->setDetection(ToolChain::AutoDetection);
toolChain->setLanguage(l);
toolChain->setDisplayName(target.name);

View File

@@ -111,6 +111,7 @@ const char targetAbiKeyC[] = "ProjectExplorer.GccToolChain.TargetAbi";
const char originalTargetTripleKeyC[] = "ProjectExplorer.GccToolChain.OriginalTargetTriple";
const char supportedAbisKeyC[] = "ProjectExplorer.GccToolChain.SupportedAbis";
const char parentToolChainIdKeyC[] = "ProjectExplorer.ClangToolChain.ParentToolChainId";
const char priorityKeyC[] = "ProjectExplorer.ClangToolChain.Priority";
const char binaryRegexp[] = "(?:^|-|\\b)(?:gcc|g\\+\\+|clang(?:\\+\\+)?)(?:-([\\d.]+))?$";
static QString runGcc(const FilePath &gcc, const QStringList &arguments, const Environment &env)
@@ -1715,6 +1716,7 @@ QVariantMap ClangToolChain::toMap() const
{
QVariantMap data = GccToolChain::toMap();
data.insert(parentToolChainIdKeyC, m_parentToolChainId);
data.insert(priorityKeyC, m_priority);
return data;
}
@@ -1724,6 +1726,7 @@ bool ClangToolChain::fromMap(const QVariantMap &data)
return false;
m_parentToolChainId = data.value(parentToolChainIdKeyC).toByteArray();
m_priority = data.value(priorityKeyC, PriorityNormal).toInt();
syncAutodetectedWithParentToolchains();
return true;
}

View File

@@ -209,6 +209,9 @@ public:
QVariantMap toMap() const override;
bool fromMap(const QVariantMap &data) override;
void setPriority(int priority) { m_priority = priority; }
int priority() const override { return m_priority; }
protected:
Utils::LanguageExtensions defaultLanguageExtensions() const override;
void syncAutodetectedWithParentToolchains();
@@ -218,6 +221,7 @@ private:
// which is used for comparison with matchesCompileCommand
mutable std::optional<Utils::FilePath> m_resolvedCompilerCommand;
QByteArray m_parentToolChainId;
int m_priority = PriorityNormal;
QMetaObject::Connection m_mingwToolchainAddedConnection;
QMetaObject::Connection m_thisToolchainRemovedConnection;

View File

@@ -268,6 +268,14 @@ void KitManager::restoreKits()
bestTc = tc;
continue;
}
if (bestTc->priority() > tc->priority())
continue;
if (bestTc->priority() < tc->priority()) {
bestTc = tc;
continue;
}
const QString bestFilePath = bestTc->compilerCommand().toString();
const QString currentFilePath = tc->compilerCommand().toString();
if (bestFilePath.contains("icecc"))
@@ -283,6 +291,7 @@ void KitManager::restoreKits()
bestTc = tc;
continue;
}
if (bestFilePath.length() > currentFilePath.length())
bestTc = tc;
}

View File

@@ -208,7 +208,8 @@ void QtKitAspect::fix(Kit *k)
// Prefer exact matches.
// TODO: We should probably prefer the compiler with the highest version number instead,
// but this information is currently not exposed by the ToolChain class.
sort(possibleTcs, [version](const ToolChain *tc1, const ToolChain *tc2) {
const FilePaths envPathVar = Environment::systemEnvironment().path();
sort(possibleTcs, [version, &envPathVar](const ToolChain *tc1, const ToolChain *tc2) {
const QVector<Abi> &qtAbis = version->qtAbis();
const bool tc1ExactMatch = qtAbis.contains(tc1->targetAbi());
const bool tc2ExactMatch = qtAbis.contains(tc2->targetAbi());
@@ -216,24 +217,37 @@ void QtKitAspect::fix(Kit *k)
return true;
if (!tc1ExactMatch && tc2ExactMatch)
return false;
return tc1->priority() > tc2->priority();
// For a multi-arch Qt that support the host ABI, prefer toolchains that match
// the host ABI.
if (qtAbis.size() > 1 && qtAbis.contains(Abi::hostAbi())) {
const bool tc1HasHostAbi = tc1->targetAbi() == Abi::hostAbi();
const bool tc2HasHostAbi = tc2->targetAbi() == Abi::hostAbi();
if (tc1HasHostAbi && !tc2HasHostAbi)
return true;
if (!tc1HasHostAbi && tc2HasHostAbi)
return false;
}
if (tc1->priority() > tc2->priority())
return true;
if (tc1->priority() < tc2->priority())
return false;
// Hack to prefer a tool chain from PATH (e.g. autodetected) over other matches.
// This improves the situation a bit if a cross-compilation tool chain has the
// same ABI as the host.
const bool tc1IsInPath = envPathVar.contains(tc1->compilerCommand().parentDir());
const bool tc2IsInPath = envPathVar.contains(tc2->compilerCommand().parentDir());
return tc1IsInPath && !tc2IsInPath;
});
// TODO: Why is this not done during sorting?
const Toolchains goodTcs = Utils::filtered(possibleTcs, [&spec](const ToolChain *t) {
return t->suggestedMkspecList().contains(spec);
});
// Hack to prefer a tool chain from PATH (e.g. autodetected) over other matches.
// This improves the situation a bit if a cross-compilation tool chain has the
// same ABI as the host.
const Environment systemEnvironment = Environment::systemEnvironment();
ToolChain *bestTc = Utils::findOrDefault(goodTcs,
[&systemEnvironment](const ToolChain *t) {
return systemEnvironment.path().contains(t->compilerCommand().parentDir());
});
if (!bestTc) {
bestTc = goodTcs.isEmpty() ? possibleTcs.first() : goodTcs.first();
}
if (bestTc)
if (ToolChain * const bestTc = goodTcs.isEmpty() ? possibleTcs.first() : goodTcs.first())
ToolChainKitAspect::setAllToolChainsToMatch(k, bestTc);
}
}