ProjectExplorer: Factor out function to compare toolchain suitability

... and use in ToolchainKitAspect in addition to KitManager.

Change-Id: I4c9221735a660697baab667877cc335ee0ee3e78
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Christian Kandeler
2024-08-08 15:24:49 +02:00
parent 077de5aab6
commit b6299edf1f
4 changed files with 44 additions and 38 deletions

View File

@@ -460,22 +460,20 @@ static void setToolchainsFromAbis(Kit *k, const LanguagesAndAbis &abisByLanguage
// Set a matching bundle for each LanguageCategory/Abi pair, if possible. // Set a matching bundle for each LanguageCategory/Abi pair, if possible.
for (auto it = abisByCategory.cbegin(); it != abisByCategory.cend(); ++it) { for (auto it = abisByCategory.cbegin(); it != abisByCategory.cend(); ++it) {
QList<ToolchainBundle> matchingBundles const QList<ToolchainBundle> matchingBundles
= Utils::filtered(bundles, [&it](const ToolchainBundle &b) { = Utils::filtered(bundles, [&it](const ToolchainBundle &b) {
return b.factory()->languageCategory() == it.key() && b.targetAbi() == it.value(); return b.factory()->languageCategory() == it.key() && b.targetAbi() == it.value();
}); });
// FIXME: Re-use the algorithm from KitManager if (matchingBundles.isEmpty()) {
Utils::sort(matchingBundles, [](const ToolchainBundle &b1, const ToolchainBundle &b2) {
return b1.get(&Toolchain::priority) > b2.get(&Toolchain::priority);
});
if (!matchingBundles.isEmpty()) {
ToolchainKitAspect::setBundle(k, matchingBundles.first());
} else {
for (const Id language : it.key()) for (const Id language : it.key())
ToolchainKitAspect::clearToolchain(k, language); ToolchainKitAspect::clearToolchain(k, language);
continue;
} }
const auto bestBundle
= std::min_element(bundles.begin(), bundles.end(), &ToolchainManager::isBetterToolchain);
ToolchainKitAspect::setBundle(k, *bestBundle);
} }
} }

View File

@@ -300,9 +300,6 @@ void KitManager::restoreKits()
// No kits exist yet, so let's try to autoconfigure some from the toolchains we know. // No kits exist yet, so let's try to autoconfigure some from the toolchains we know.
QHash<Abi, QHash<LanguageCategory, std::optional<ToolchainBundle>>> uniqueToolchains; QHash<Abi, QHash<LanguageCategory, std::optional<ToolchainBundle>>> uniqueToolchains;
// On Linux systems, we usually detect a plethora of same-ish toolchains. The following
// algorithm gives precedence to icecc and ccache and otherwise simply chooses the one with
// the shortest path.
const QList<ToolchainBundle> bundles = ToolchainBundle::collectBundles( const QList<ToolchainBundle> bundles = ToolchainBundle::collectBundles(
ToolchainBundle::AutoRegister::On); ToolchainBundle::AutoRegister::On);
for (const ToolchainBundle &bundle : bundles) { for (const ToolchainBundle &bundle : bundles) {
@@ -313,32 +310,7 @@ void KitManager::restoreKits()
continue; continue;
} }
const int bestPriority = bestBundle->get(&Toolchain::priority); if (ToolchainManager::isBetterToolchain(bundle, *bestBundle))
const int currentPriority = bundle.get(&Toolchain::priority);
if (bestPriority > currentPriority)
continue;
if (bestPriority < currentPriority) {
bestBundle = bundle;
continue;
}
const QString bestFilePath = bestBundle->get(&Toolchain::compilerCommand).toString();
const QString currentFilePath = bundle.get(&Toolchain::compilerCommand).toString();
if (bestFilePath.contains("icecc"))
continue;
if (currentFilePath.contains("icecc")) {
bestBundle = bundle;
continue;
}
if (bestFilePath.contains("ccache"))
continue;
if (currentFilePath.contains("ccache")) {
bestBundle = bundle;
continue;
}
if (bestFilePath.length() > currentFilePath.length())
bestBundle = bundle; bestBundle = bundle;
} }

View File

@@ -331,4 +331,38 @@ void ToolchainManager::addBadToolchain(const Utils::FilePath &toolchain)
d->m_badToolchains.toolchains << toolchain; d->m_badToolchains.toolchains << toolchain;
} }
// Use as a tie-breaker for toolchains that match the strong requirements like toolchain type
// and ABI.
// For toolchains with the same priority, gives precedence to icecc and ccache
// and otherwise simply chooses the one with the shortest path.
bool ToolchainManager::isBetterToolchain(
const ToolchainBundle &bundle1, const ToolchainBundle &bundle2)
{
const int priority1 = bundle1.get(&Toolchain::priority);
const int priority2 = bundle2.get(&Toolchain::priority);
if (priority1 > priority2)
return true;
if (priority1 < priority2)
return false;
const QString path1 = bundle1.get(&Toolchain::compilerCommand).path();
const QString path2 = bundle2.get(&Toolchain::compilerCommand).path();
const bool b1IsIcecc = path1.contains("icecc");
const bool b2IsIcecc = path2.contains("icecc");
if (b1IsIcecc)
return !b2IsIcecc;
if (b2IsIcecc)
return false;
const bool b1IsCCache = path1.contains("ccache");
const bool b2IsCcache = path2.contains("ccache");
if (b1IsCCache)
return !b2IsCcache;
if (b2IsCcache)
return false;
return path1.size() < path2.size();
}
} // namespace ProjectExplorer } // namespace ProjectExplorer

View File

@@ -67,6 +67,8 @@ public:
static bool isBadToolchain(const Utils::FilePath &toolchain); static bool isBadToolchain(const Utils::FilePath &toolchain);
static void addBadToolchain(const Utils::FilePath &toolchain); static void addBadToolchain(const Utils::FilePath &toolchain);
static bool isBetterToolchain(const ToolchainBundle &bundle1, const ToolchainBundle &bundle2);
void saveToolchains(); void saveToolchains();
signals: signals: