forked from qt-creator/qt-creator
ProjectExplorer: Improve ToolchainKitAspect::setup()
- Use toolchain bundles. - De-obfuscate the code. - Add explanatory comments. Change-Id: I19f4b5fde317ffabf06c762e1987b0314c52e646 Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
@@ -30,10 +30,13 @@
|
|||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
#include <QFontMetrics>
|
#include <QFontMetrics>
|
||||||
#include <QGridLayout>
|
#include <QGridLayout>
|
||||||
|
#include <QHash>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
using namespace Utils;
|
using namespace Utils;
|
||||||
|
|
||||||
namespace ProjectExplorer {
|
namespace ProjectExplorer {
|
||||||
@@ -383,30 +386,6 @@ ToolchainKitAspectFactory::ToolchainKitAspectFactory()
|
|||||||
setPriority(30000);
|
setPriority(30000);
|
||||||
}
|
}
|
||||||
|
|
||||||
// language id -> tool chain id
|
|
||||||
static QMap<Id, QByteArray> defaultToolChainIds()
|
|
||||||
{
|
|
||||||
QMap<Id, QByteArray> toolChains;
|
|
||||||
const Abi abi = Abi::hostAbi();
|
|
||||||
const Toolchains tcList = ToolchainManager::toolchains(equal(&Toolchain::targetAbi, abi));
|
|
||||||
const QList<Id> languages = ToolchainManager::allLanguages();
|
|
||||||
for (Id l : languages) {
|
|
||||||
Toolchain *tc = findOrDefault(tcList, equal(&Toolchain::language, l));
|
|
||||||
toolChains.insert(l, tc ? tc->id() : QByteArray());
|
|
||||||
}
|
|
||||||
return toolChains;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Store defaultToolchainValue()
|
|
||||||
{
|
|
||||||
const QMap<Id, QByteArray> toolChains = defaultToolChainIds();
|
|
||||||
Store result;
|
|
||||||
auto end = toolChains.end();
|
|
||||||
for (auto it = toolChains.begin(); it != end; ++it)
|
|
||||||
result.insert(it.key().toKey(), it.value());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
Tasks ToolchainKitAspectFactory::validate(const Kit *k) const
|
Tasks ToolchainKitAspectFactory::validate(const Kit *k) const
|
||||||
{
|
{
|
||||||
Tasks result;
|
Tasks result;
|
||||||
@@ -451,47 +430,116 @@ static Id findLanguage(const QString &ls)
|
|||||||
[lsUpper](Id l) { return lsUpper == l.toString().toUpper(); });
|
[lsUpper](Id l) { return lsUpper == l.toString().toUpper(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
void ToolchainKitAspectFactory::setup(Kit *k)
|
using LanguageAndAbi = std::pair<Id, Abi>;
|
||||||
|
using LanguagesAndAbis = QList<LanguageAndAbi>;
|
||||||
|
|
||||||
|
static void setToolchainsFromAbis(Kit *k, const LanguagesAndAbis &abisByLanguage)
|
||||||
{
|
{
|
||||||
QTC_ASSERT(ToolchainManager::isLoaded(), return);
|
if (abisByLanguage.isEmpty())
|
||||||
QTC_ASSERT(k, return);
|
return;
|
||||||
|
|
||||||
Store value = storeFromVariant(k->value(id()));
|
// First transform languages into categories, so we can work on the bundle level.
|
||||||
bool lockToolchains = k->isSdkProvided() && !value.isEmpty();
|
// Obviously, we assume that the caller does not specify different ABIs for
|
||||||
if (value.empty())
|
// languages from the same category.
|
||||||
value = defaultToolchainValue();
|
const QList<LanguageCategory> allCategories = ToolchainManager::languageCategories();
|
||||||
|
QHash<LanguageCategory, Abi> abisByCategory;
|
||||||
|
for (const LanguageAndAbi &langAndAbi : abisByLanguage) {
|
||||||
|
const auto category
|
||||||
|
= Utils::findOrDefault(allCategories, [&langAndAbi](const LanguageCategory &cat) {
|
||||||
|
return cat.contains(langAndAbi.first);
|
||||||
|
});
|
||||||
|
QTC_ASSERT(!category.isEmpty(), continue);
|
||||||
|
abisByCategory.insert(category, langAndAbi.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get bundles.
|
||||||
|
const QList<ToolchainBundle> bundles = ToolchainBundle::collectBundles();
|
||||||
|
for (const ToolchainBundle &b : bundles)
|
||||||
|
ToolchainManager::registerToolchains(b.createdToolchains());
|
||||||
|
|
||||||
|
// Set a matching bundle for each LanguageCategory/Abi pair, if possible.
|
||||||
|
for (auto it = abisByCategory.cbegin(); it != abisByCategory.cend(); ++it) {
|
||||||
|
QList<ToolchainBundle> matchingBundles
|
||||||
|
= Utils::filtered(bundles, [&it](const ToolchainBundle &b) {
|
||||||
|
return b.factory()->languageCategory() == it.key() && b.targetAbi() == it.value();
|
||||||
|
});
|
||||||
|
|
||||||
|
// FIXME: Re-use the algorithm from KitManager
|
||||||
|
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())
|
||||||
|
ToolchainKitAspect::clearToolchain(k, language);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setMissingToolchainsToHostAbi(Kit *k, const QList<Id> &languageBlacklist)
|
||||||
|
{
|
||||||
|
LanguagesAndAbis abisByLanguage;
|
||||||
|
for (const Id lang : ToolchainManager::allLanguages()) {
|
||||||
|
if (languageBlacklist.contains(lang) || ToolchainKitAspect::toolchain(k, lang))
|
||||||
|
continue;
|
||||||
|
abisByLanguage.emplaceBack(lang, Abi::hostAbi());
|
||||||
|
}
|
||||||
|
setToolchainsFromAbis(k, abisByLanguage);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setupForSdkKit(Kit *k)
|
||||||
|
{
|
||||||
|
const Store value = storeFromVariant(k->value(ToolchainKitAspect::id()));
|
||||||
|
bool lockToolchains = !value.isEmpty();
|
||||||
|
|
||||||
|
// The installer provides two kinds of entries for toolchains:
|
||||||
|
// a) An actual toolchain id, for e.g. Boot2Qt where the installer ships the toolchains.
|
||||||
|
// b) An ABI string, for Desktop Qt. In this case, it is our responsibility to find
|
||||||
|
// a matching toolchain on the host system.
|
||||||
|
LanguagesAndAbis abisByLanguage;
|
||||||
for (auto i = value.constBegin(); i != value.constEnd(); ++i) {
|
for (auto i = value.constBegin(); i != value.constEnd(); ++i) {
|
||||||
Id l = findLanguage(stringFromKey(i.key()));
|
const Id lang = findLanguage(stringFromKey(i.key()));
|
||||||
|
|
||||||
if (!l.isValid()) {
|
if (!lang.isValid()) {
|
||||||
lockToolchains = false;
|
lockToolchains = false;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QByteArray id = i.value().toByteArray();
|
const QByteArray id = i.value().toByteArray();
|
||||||
Toolchain *tc = ToolchainManager::findToolchain(id);
|
if (ToolchainManager::findToolchain(id))
|
||||||
if (tc)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// ID is not found: Might be an ABI string...
|
// No toolchain with this id exists. Check whether it's an ABI string.
|
||||||
lockToolchains = false;
|
lockToolchains = false;
|
||||||
const QString abi = QString::fromUtf8(id);
|
const Abi abi = Abi::fromString(QString::fromUtf8(id));
|
||||||
const Toolchains possibleTcs = ToolchainManager::toolchains([abi, l](const Toolchain *t) {
|
if (!abi.isValid())
|
||||||
return t->targetAbi().toString() == abi && t->language() == l;
|
continue;
|
||||||
});
|
|
||||||
Toolchain *bestTc = nullptr;
|
|
||||||
for (Toolchain *tc : possibleTcs) {
|
|
||||||
if (!bestTc || tc->priority() > bestTc->priority())
|
|
||||||
bestTc = tc;
|
|
||||||
}
|
|
||||||
if (bestTc)
|
|
||||||
ToolchainKitAspect::setToolchain(k, bestTc);
|
|
||||||
else
|
|
||||||
ToolchainKitAspect::clearToolchain(k, l);
|
|
||||||
}
|
|
||||||
|
|
||||||
k->setSticky(id(), lockToolchains);
|
abisByLanguage.emplaceBack(lang, abi);
|
||||||
|
}
|
||||||
|
setToolchainsFromAbis(k, abisByLanguage);
|
||||||
|
setMissingToolchainsToHostAbi(k, Utils::transform(abisByLanguage, &LanguageAndAbi::first));
|
||||||
|
|
||||||
|
k->setSticky(ToolchainKitAspect::id(), lockToolchains);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setupForNonSdkKit(Kit *k)
|
||||||
|
{
|
||||||
|
setMissingToolchainsToHostAbi(k, {});
|
||||||
|
k->setSticky(ToolchainKitAspect::id(), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ToolchainKitAspectFactory::setup(Kit *k)
|
||||||
|
{
|
||||||
|
QTC_ASSERT(ToolchainManager::isLoaded(), return);
|
||||||
|
QTC_ASSERT(k, return);
|
||||||
|
|
||||||
|
if (k->isSdkProvided())
|
||||||
|
setupForSdkKit(k);
|
||||||
|
else
|
||||||
|
setupForNonSdkKit(k);
|
||||||
}
|
}
|
||||||
|
|
||||||
KitAspect *ToolchainKitAspectFactory::createKitAspect(Kit *k) const
|
KitAspect *ToolchainKitAspectFactory::createKitAspect(Kit *k) const
|
||||||
|
|||||||
Reference in New Issue
Block a user