diff options
Diffstat (limited to 'src/plugins/projectexplorer/kitmanager.cpp')
-rw-r--r-- | src/plugins/projectexplorer/kitmanager.cpp | 159 |
1 files changed, 137 insertions, 22 deletions
diff --git a/src/plugins/projectexplorer/kitmanager.cpp b/src/plugins/projectexplorer/kitmanager.cpp index c9597844af..ecb8c52ae7 100644 --- a/src/plugins/projectexplorer/kitmanager.cpp +++ b/src/plugins/projectexplorer/kitmanager.cpp @@ -38,6 +38,11 @@ #include <coreplugin/icore.h> +#include <android/androidconstants.h> +#include <baremetal/baremetalconstants.h> +#include <qnx/qnxconstants.h> +#include <remotelinux/remotelinux_constants.h> + #include <utils/environment.h> #include <utils/persistentsettings.h> #include <utils/pointeralgorithm.h> @@ -114,11 +119,16 @@ public: return m_aspectList; } + void setBinaryForKit(const FilePath &fp) { m_binaryForKit = fp; } + FilePath binaryForKit() const { return m_binaryForKit; } + private: // Sorted by priority, in descending order... QList<KitAspect *> m_aspectList; // ... if this here is set: bool m_aspectListIsSorted = true; + + FilePath m_binaryForKit; }; } // namespace Internal @@ -225,17 +235,33 @@ void KitManager::restoreKits() // Delete all loaded autodetected kits that were not rediscovered: kitsToCheck.clear(); - if (resultList.empty()) { - // No kits exist yet, so let's try to autoconfigure some from the toolchains we know. - // We consider only host toolchains, because for other ones we lack the knowledge how to - // map them to their respective device type. - static const auto isHostToolchain = [](const ToolChain *tc) { - static const Abi hostAbi = Abi::hostAbi(); + static const auto kitMatchesAbiList = [](const Kit *kit, const Abis &abis) { + const QList<ToolChain *> toolchains = ToolChainKitAspect::toolChains(kit); + for (const ToolChain * const tc : toolchains) { const Abi tcAbi = tc->targetAbi(); - return tcAbi.os() == hostAbi.os() && tcAbi.architecture() == hostAbi.architecture() - && (tcAbi.os() != Abi::LinuxOS || tcAbi.osFlavor() == hostAbi.osFlavor()); - }; - const QList<ToolChain *> allToolchains = ToolChainManager::toolChains(isHostToolchain); + for (const Abi &abi : abis) { + if (tcAbi.os() == abi.os() && tcAbi.architecture() == abi.architecture() + && (tcAbi.os() != Abi::LinuxOS || tcAbi.osFlavor() == abi.osFlavor())) { + return true; + } + } + } + return false; + }; + + const Abis abisOfBinary = d->binaryForKit().isEmpty() + ? Abis() : Abi::abisOfBinary(d->binaryForKit()); + const auto kitMatchesAbiOfBinary = [&abisOfBinary](const Kit *kit) { + return kitMatchesAbiList(kit, abisOfBinary); + }; + const bool haveKitForBinary = abisOfBinary.isEmpty() + || contains(resultList, [&kitMatchesAbiOfBinary](const std::unique_ptr<Kit> &kit) { + return kitMatchesAbiOfBinary(kit.get()); + }); + Kit *kitForBinary = nullptr; + + if (resultList.empty() || !haveKitForBinary) { + // No kits exist yet, so let's try to autoconfigure some from the toolchains we know. QHash<Abi, QHash<Core::Id, ToolChain *>> uniqueToolchains; // On Linux systems, we usually detect a plethora of same-ish toolchains. The following @@ -244,7 +270,7 @@ void KitManager::restoreKits() // TODO: This should not need to be done here. Instead, it should be a convenience // operation on some lower level, e.g. in the toolchain class(es). // Also, we shouldn't detect so many doublets in the first place. - for (ToolChain * const tc : allToolchains) { + for (ToolChain * const tc : ToolChainManager::toolChains()) { ToolChain *&bestTc = uniqueToolchains[tc->targetAbi()][tc->language()]; if (!bestTc) { bestTc = tc; @@ -269,28 +295,111 @@ void KitManager::restoreKits() bestTc = tc; } - int maxWeight = 0; + static const auto isHostKit = [](const Kit *kit) { + return kitMatchesAbiList(kit, {Abi::hostAbi()}); + }; + + static const auto deviceTypeForKit = [](const Kit *kit) { + if (isHostKit(kit)) + return Constants::DESKTOP_DEVICE_TYPE; + const QList<ToolChain *> toolchains = ToolChainKitAspect::toolChains(kit); + for (const ToolChain * const tc : toolchains) { + const Abi tcAbi = tc->targetAbi(); + switch (tcAbi.os()) { + case Abi::BareMetalOS: + return BareMetal::Constants::BareMetalOsType; + case Abi::BsdOS: + case Abi::DarwinOS: + case Abi::UnixOS: + return RemoteLinux::Constants::GenericLinuxOsType; + case Abi::LinuxOS: + if (tcAbi.osFlavor() == Abi::AndroidLinuxFlavor) + return Android::Constants::ANDROID_DEVICE_TYPE; + return RemoteLinux::Constants::GenericLinuxOsType; + case Abi::QnxOS: + return Qnx::Constants::QNX_QNX_OS_TYPE; + case Abi::VxWorks: + return "VxWorks.Device.Type"; + default: + break; + } + } + return Constants::DESKTOP_DEVICE_TYPE; + }; + + // Create temporary kits for all toolchains found. + decltype(resultList) tempList; for (auto it = uniqueToolchains.cbegin(); it != uniqueToolchains.cend(); ++it) { auto kit = std::make_unique<Kit>(); kit->setSdkProvided(false); kit->setAutoDetected(false); // TODO: Why false? What does autodetected mean here? for (ToolChain * const tc : it.value()) ToolChainKitAspect::setToolChain(kit.get(), tc); - kit->setUnexpandedDisplayName(tr("Desktop (%1)").arg(it.key().toString())); - kit->setup(); - if (kit->weight() < maxWeight) + if (contains(resultList, [&kit](const std::unique_ptr<Kit> &existingKit) { + return ToolChainKitAspect::toolChains(kit.get()) + == ToolChainKitAspect::toolChains(existingKit.get()); + })) { continue; - if (kit->weight() > maxWeight) { - maxWeight = kit->weight(); - resultList.clear(); } - resultList.emplace_back(std::move(kit)); + if (isHostKit(kit.get())) + kit->setUnexpandedDisplayName(tr("Desktop (%1)").arg(it.key().toString())); + else + kit->setUnexpandedDisplayName(it.key().toString()); + DeviceTypeKitAspect::setDeviceTypeId(kit.get(), deviceTypeForKit(kit.get())); + kit->setup(); + tempList.emplace_back(std::move(kit)); } - if (resultList.size() == 1) - resultList.front()->setUnexpandedDisplayName(tr("Desktop")); + + // Now make the "best" temporary kits permanent. The logic is as follows: + // - If the user has requested a kit for a given binary and one or more kits + // with a matching ABI exist, then we randomly choose exactly one among those with + // the highest weight. + // - If the user has not requested a kit for a given binary or no such kit could + // be created, we choose all kits with the highest weight. If none of these + // is a host kit, then we also add the host kit with the highest weight. + Utils::sort(tempList, [](const std::unique_ptr<Kit> &k1, const std::unique_ptr<Kit> &k2) { + return k1->weight() > k2->weight(); + }); + if (!abisOfBinary.isEmpty()) { + for (auto it = tempList.begin(); it != tempList.end(); ++it) { + if (kitMatchesAbiOfBinary(it->get())) { + kitForBinary = it->get(); + resultList.emplace_back(std::move(*it)); + tempList.erase(it); + break; + } + } + } + QList<Kit *> hostKits; + if (!kitForBinary && !tempList.empty()) { + const int maxWeight = tempList.front()->weight(); + for (auto it = tempList.begin(); it != tempList.end(); it = tempList.erase(it)) { + if ((*it)->weight() < maxWeight) + break; + if (isHostKit(it->get())) + hostKits << it->get(); + resultList.emplace_back(std::move(*it)); + } + if (!contains(resultList, [](const std::unique_ptr<Kit> &kit) { + return isHostKit(kit.get());})) { + QTC_ASSERT(hostKits.isEmpty(), hostKits.clear()); + for (auto &kit : tempList) { + if (isHostKit(kit.get())) { + hostKits << kit.get(); + resultList.emplace_back(std::move(kit)); + break; + } + } + } + } + + if (hostKits.size() == 1) + hostKits.first()->setUnexpandedDisplayName(tr("Desktop")); } - Kit *k = Utils::findOrDefault(resultList, Utils::equal(&Kit::id, defaultUserKit)); + Kit *k = kitForBinary; + if (!k) + k = Utils::findOrDefault(resultList, Utils::equal(&Kit::id, defaultUserKit)); if (!k) k = Utils::findOrDefault(resultList, &Kit::isValid); std::swap(resultList, d->m_kitList); @@ -359,6 +468,12 @@ void KitManager::deregisterKitAspect(KitAspect *ki) d->removeKitAspect(ki); } +void KitManager::setBinaryForKit(const FilePath &binary) +{ + QTC_ASSERT(d, return); + d->setBinaryForKit(binary); +} + QList<Kit *> KitManager::sortKits(const QList<Kit *> &kits) { // This method was added to delay the sorting of kits as long as possible. |