summaryrefslogtreecommitdiff
path: root/src/plugins/projectexplorer/kitmanager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/projectexplorer/kitmanager.cpp')
-rw-r--r--src/plugins/projectexplorer/kitmanager.cpp159
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.