diff options
author | Eike Ziller <eike.ziller@theqtcompany.com> | 2015-10-09 09:50:07 +0200 |
---|---|---|
committer | Eike Ziller <eike.ziller@theqtcompany.com> | 2015-10-19 07:20:53 +0000 |
commit | e3f770a50cf0c41ccec10d209ef0af9e6590b119 (patch) | |
tree | d213898811d1ee8bee37f582213999ca41575a91 | |
parent | 09bc8af64568ea5e3f50784a541eb64c185ea95c (diff) | |
download | qt-creator-e3f770a50cf0c41ccec10d209ef0af9e6590b119.tar.gz |
iOS: Refactor iOS tool chain and kit auto detection
It was all done in one huge, unreadable method.
The refactoring along-side fixes the following:
- iOS tool chains were demoted to manual at start up because there
was no tool chain factory that would auto detect them
- a QTC_CHECK failed because single Qt Versions could appear multiple
times in the architecture->Qt version map, because each architecture
is present in two abis (32-bit and 64-bit)
The refactoring also removes unneeded automatic conversion
from non-iOS Qt version to iOS Qt version, and removes considering GCC
toolchains (which were not handled anyhow, because only Clang
"platforms" were considered).
Change-Id: Ic9ae797646f159ed45959fc797990aa98f2136fb
Reviewed-by: Tobias Hunger <tobias.hunger@theqtcompany.com>
-rw-r--r-- | src/plugins/ios/iosconfigurations.cpp | 501 | ||||
-rw-r--r-- | src/plugins/ios/iosconfigurations.h | 10 | ||||
-rw-r--r-- | src/plugins/ios/iosplugin.cpp | 1 | ||||
-rw-r--r-- | src/plugins/ios/iosprobe.cpp | 20 | ||||
-rw-r--r-- | src/plugins/ios/iosprobe.h | 6 |
5 files changed, 250 insertions, 288 deletions
diff --git a/src/plugins/ios/iosconfigurations.cpp b/src/plugins/ios/iosconfigurations.cpp index 01ecfb5713..362160018a 100644 --- a/src/plugins/ios/iosconfigurations.cpp +++ b/src/plugins/ios/iosconfigurations.cpp @@ -35,6 +35,7 @@ #include "iosprobe.h" #include <coreplugin/icore.h> +#include <utils/algorithm.h> #include <utils/qtcassert.h> #include <projectexplorer/kitmanager.h> #include <projectexplorer/kitinformation.h> @@ -52,8 +53,8 @@ #include <qtsupport/qtversionfactory.h> #include <QFileInfo> +#include <QHash> #include <QList> -#include <QMap> #include <QSettings> #include <QStringList> #include <QTimer> @@ -73,307 +74,204 @@ namespace Internal { const QLatin1String SettingsGroup("IosConfigurations"); const QLatin1String ignoreAllDevicesKey("IgnoreAllDevices"); -void IosConfigurations::updateAutomaticKitList() +static Core::Id deviceId(const Platform &platform) { - QMap<QString, Platform> platforms = IosProbe::detectPlatforms(); - if (!platforms.isEmpty()) - setDeveloperPath(platforms.begin().value().developerPath); - // filter out all non iphone, non base, non clang or cxx11 platforms, as we don't set up kits for those - { - QMap<QString, Platform>::iterator iter(platforms.begin()); - while (iter != platforms.end()) { - const Platform &p = iter.value(); - if (!p.name.startsWith(QLatin1String("iphone")) || (p.platformKind & Platform::BasePlatform) == 0 - || (p.platformKind & Platform::Cxx11Support) != 0 - || !p.compilerPath.toString().contains(QLatin1String("clang"))) - iter = platforms.erase(iter); - else { - qCDebug(kitSetupLog) << "keeping" << p.name << " " << p.compilerPath.toString() << " " - << p.backendFlags; - ++iter; - } - } - } + if (platform.name.startsWith(QLatin1String("iphoneos-"))) + return Constants::IOS_DEVICE_TYPE; + else if (platform.name.startsWith(QLatin1String("iphonesimulator-"))) + return Constants::IOS_SIMULATOR_TYPE; + return Core::Id(); +} - QMap<QString, GccToolChain *> platformToolchainMap; - // check existing toolchains (and remove old ones) - foreach (ToolChain *tc, ToolChainManager::toolChains()) { - if (!tc->isAutoDetected()) // use also user toolchains? - continue; - if (tc->typeId() != ProjectExplorer::Constants::CLANG_TOOLCHAIN_TYPEID - && tc->typeId() != ProjectExplorer::Constants::GCC_TOOLCHAIN_TYPEID) - continue; - GccToolChain *toolchain = static_cast<GccToolChain *>(tc); - QMapIterator<QString, Platform> iter(platforms); - bool found = false; - while (iter.hasNext()) { - iter.next(); - const Platform &p = iter.value(); - if (p.compilerPath == toolchain->compilerCommand() - && p.backendFlags == toolchain->platformCodeGenFlags() - && !platformToolchainMap.contains(p.name)) { - platformToolchainMap[p.name] = toolchain; - found = true; - } - } - iter.toFront(); - while (iter.hasNext()) { - iter.next(); - const Platform &p = iter.value(); - if (p.platformKind) - continue; - if (p.compilerPath == toolchain->compilerCommand() - && p.backendFlags == toolchain->platformCodeGenFlags()) { - found = true; - if ((p.architecture == QLatin1String("i386") - && toolchain->targetAbi().wordWidth() != 32) || - (p.architecture == QLatin1String("x86_64") - && toolchain->targetAbi().wordWidth() != 64)) { - qCDebug(kitSetupLog) << "resetting api of " << toolchain->displayName(); - toolchain->setTargetAbi(Abi(Abi::X86Architecture, - Abi::MacOS, Abi::GenericMacFlavor, - Abi::MachOFormat, - p.architecture.endsWith(QLatin1String("64")) - ? 64 : 32)); - } - platformToolchainMap[p.name] = toolchain; - qCDebug(kitSetupLog) << p.name << " -> " << toolchain->displayName(); - } - } - if (!found && (tc->displayName().startsWith(QLatin1String("iphone")) - || tc->displayName().startsWith(QLatin1String("mac")))) { - qCWarning(kitSetupLog) << "removing toolchain" << tc->displayName(); - ToolChainManager::deregisterToolChain(tc); - } - } - // add missing toolchains - { - QMapIterator<QString, Platform> iter(platforms); - while (iter.hasNext()) { - iter.next(); - const Platform &p = iter.value(); - if (platformToolchainMap.contains(p.name)) - continue; - GccToolChain *toolchain; - if (p.compilerPath.toFileInfo().baseName().startsWith(QLatin1String("clang"))) - toolchain = new ClangToolChain(ToolChain::AutoDetection); - else - toolchain = new GccToolChain(ProjectExplorer::Constants::GCC_TOOLCHAIN_TYPEID, - ToolChain::AutoDetection); - QString baseDisplayName = p.name; - QString displayName = baseDisplayName; - for (int iVers = 1; iVers < 100; ++iVers) { - bool unique = true; - foreach (ToolChain *existingTC, ToolChainManager::toolChains()) { - if (existingTC->displayName() == displayName) { - unique = false; - break; - } - } - if (unique) break; - displayName = baseDisplayName + QLatin1Char('-') + QString::number(iVers); - } - toolchain->setDisplayName(displayName); - toolchain->setPlatformCodeGenFlags(p.backendFlags); - toolchain->setPlatformLinkerFlags(p.backendFlags); - toolchain->resetToolChain(p.compilerPath); - if (p.architecture == QLatin1String("i386") - || p.architecture == QLatin1String("x86_64")) { - qCDebug(kitSetupLog) << "setting toolchain Abi for " << toolchain->displayName(); - toolchain->setTargetAbi(Abi(Abi::X86Architecture,Abi::MacOS, Abi::GenericMacFlavor, - Abi::MachOFormat, - p.architecture.endsWith(QLatin1String("64")) - ? 64 : 32)); - } - qCDebug(kitSetupLog) << "adding toolchain " << p.name; - ToolChainManager::registerToolChain(toolchain); - platformToolchainMap.insert(p.name, toolchain); - QMapIterator<QString, Platform> iter2(iter); - while (iter2.hasNext()) { - iter2.next(); - const Platform &p2 = iter2.value(); - if (!platformToolchainMap.contains(p2.name) - && p2.compilerPath == toolchain->compilerCommand() - && p2.backendFlags == toolchain->platformCodeGenFlags()) { - platformToolchainMap[p2.name] = toolchain; - } - } - } +static bool handledPlatform(const Platform &platform) +{ + // do not want platforms that + // - are not iphone (e.g. watchos) + // - are not base + // - are C++11 + // - are not clang + return deviceId(platform).isValid() + && (platform.platformKind & Platform::BasePlatform) != 0 + && (platform.platformKind & Platform::Cxx11Support) == 0 + && platform.compilerPath.toString().contains(QLatin1String("clang")); +} + +static QList<Platform> handledPlatforms() +{ + QList<Platform> platforms = IosProbe::detectPlatforms().values(); + return Utils::filtered(platforms, handledPlatform); +} + +static QList<ClangToolChain *> clangToolChains(const QList<ToolChain *> &toolChains) +{ + QList<ClangToolChain *> clangToolChains; + foreach (ToolChain *toolChain, toolChains) + if (toolChain->typeId() == ProjectExplorer::Constants::CLANG_TOOLCHAIN_TYPEID) + clangToolChains.append(static_cast<ClangToolChain *>(toolChain)); + return clangToolChains; +} + +static QList<ClangToolChain *> autoDetectedIosToolChains() +{ + const QList<ClangToolChain *> toolChains = clangToolChains(ToolChainManager::toolChains()); + return Utils::filtered(toolChains, [](ClangToolChain *toolChain) { + return toolChain->isAutoDetected() + && toolChain->displayName().startsWith(QLatin1String("iphone")); // TODO tool chains should be marked directly + }); +} + +static ClangToolChain *findToolChainForPlatform(const Platform &platform, const QList<ClangToolChain *> &toolChains) +{ + return Utils::findOrDefault(toolChains, [&platform](ClangToolChain *toolChain) { + return platform.compilerPath == toolChain->compilerCommand() + && platform.backendFlags == toolChain->platformCodeGenFlags() + && platform.backendFlags == toolChain->platformLinkerFlags(); + }); +} + +static QHash<Platform, ClangToolChain *> findToolChains(const QList<Platform> &platforms) +{ + QHash<Platform, ClangToolChain *> platformToolChainHash; + const QList<ClangToolChain *> toolChains = autoDetectedIosToolChains(); + foreach (const Platform &platform, platforms) { + ClangToolChain *toolChain = findToolChainForPlatform(platform, toolChains); + if (toolChain) + platformToolChainHash.insert(platform, toolChain); } - QMap<Abi::Architecture, QList<BaseQtVersion *> > qtVersionsForArch; + return platformToolChainHash; +} + +static QHash<Abi::Architecture, QSet<BaseQtVersion *>> iosQtVersions() +{ + QHash<Abi::Architecture, QSet<BaseQtVersion *>> versions; foreach (BaseQtVersion *qtVersion, QtVersionManager::versions()) { - qCDebug(kitSetupLog) << "qt type " << qtVersion->type(); - if (qtVersion->type() != QLatin1String(Constants::IOSQT)) { - if (qtVersion->qmakeProperty("QMAKE_PLATFORM").contains(QLatin1String("ios")) - || qtVersion->qmakeProperty("QMAKE_XSPEC").contains(QLatin1String("ios"))) { - // replace with an ios version - BaseQtVersion *iosVersion = - QtVersionFactory::createQtVersionFromQMakePath( - qtVersion->qmakeCommand(), - qtVersion->isAutodetected(), - qtVersion->autodetectionSource()); - if (iosVersion && iosVersion->type() == QLatin1String(Constants::IOSQT)) { - qCDebug(kitSetupLog) << "converting QT to iOS QT for " << qtVersion->qmakeCommand().toUserOutput(); - QtVersionManager::removeVersion(qtVersion); - QtVersionManager::addVersion(iosVersion); - qtVersion = iosVersion; - } else { - continue; - } - } else { - continue; - } - } - if (!qtVersion->isValid()) - continue; - QList<Abi> qtAbis = qtVersion->qtAbis(); - if (qtAbis.empty()) + if (!qtVersion->isValid() || qtVersion->type() != QLatin1String(Constants::IOSQT)) continue; - qCDebug(kitSetupLog) << "qt arch " << qtAbis.first().architecture(); - foreach (const Abi &abi, qtAbis) - qtVersionsForArch[abi.architecture()].append(qtVersion); + foreach (const Abi &abi, qtVersion->qtAbis()) + versions[abi.architecture()].insert(qtVersion); + } + return versions; +} + +static void printQtVersions(const QHash<Abi::Architecture, QSet<BaseQtVersion *> > &map) +{ + foreach (const Abi::Architecture &arch, map.keys()) { + qCDebug(kitSetupLog) << "-" << Abi::toString(arch); + foreach (const BaseQtVersion *version, map.value(arch)) + qCDebug(kitSetupLog) << " -" << version->displayName() << version; } +} + +static QSet<Kit *> existingAutoDetectedIosKits() +{ + return Utils::filtered(KitManager::kits(), [](Kit *kit) -> bool { + Core::Id deviceKind = DeviceTypeKitInformation::deviceTypeId(kit); + return kit->isAutoDetected() && (deviceKind == Constants::IOS_DEVICE_TYPE + || deviceKind == Constants::IOS_SIMULATOR_TYPE); + }).toSet(); +} + +static void printKits(const QSet<Kit *> &kits) +{ + foreach (const Kit *kit, kits) + qCDebug(kitSetupLog) << " -" << kit->displayName(); +} + +static void setupKit(Kit *kit, Core::Id pDeviceType, ClangToolChain *pToolchain, + const QVariant &debuggerId, const Utils::FileName &sdkPath, BaseQtVersion *qtVersion) +{ + kit->setIconPath(FileName::fromString(QLatin1String(Constants::IOS_SETTINGS_CATEGORY_ICON))); + DeviceTypeKitInformation::setDeviceTypeId(kit, pDeviceType); + ToolChainKitInformation::setToolChain(kit, pToolchain); + QtKitInformation::setQtVersion(kit, qtVersion); + // only replace debugger with the default one if we find an unusable one here + // (since the user could have changed it) + if ((!DebuggerKitInformation::debugger(kit) + || !DebuggerKitInformation::debugger(kit)->isValid() + || DebuggerKitInformation::debugger(kit)->engineType() != LldbEngineType) + && debuggerId.isValid()) + DebuggerKitInformation::setDebugger(kit, debuggerId); + + kit->setMutable(DeviceKitInformation::id(), true); + kit->setSticky(QtKitInformation::id(), true); + kit->setSticky(ToolChainKitInformation::id(), true); + kit->setSticky(DeviceTypeKitInformation::id(), true); + kit->setSticky(SysRootKitInformation::id(), true); + kit->setSticky(DebuggerKitInformation::id(), false); + + SysRootKitInformation::setSysRoot(kit, sdkPath); +} + +void IosConfigurations::updateAutomaticKitList() +{ + const QList<Platform> platforms = handledPlatforms(); + qCDebug(kitSetupLog) << "Used platforms:" << platforms; + if (!platforms.isEmpty()) + setDeveloperPath(platforms.first().developerPath); + qCDebug(kitSetupLog) << "Developer path:" << developerPath(); + + // platform name -> tool chain + const QHash<Platform, ClangToolChain *> platformToolChainHash = findToolChains(platforms); + + const QHash<Abi::Architecture, QSet<BaseQtVersion *> > qtVersionsForArch = iosQtVersions(); + qCDebug(kitSetupLog) << "iOS Qt versions:"; + printQtVersions(qtVersionsForArch); const DebuggerItem *possibleDebugger = DebuggerItemManager::findByEngineType(LldbEngineType); - QVariant debuggerId = (possibleDebugger ? possibleDebugger->id() : QVariant()); - - QList<Kit *> existingKits; - QList<bool> kitMatched; - foreach (Kit *k, KitManager::kits()) { - Core::Id deviceKind = DeviceTypeKitInformation::deviceTypeId(k); - if (deviceKind != Constants::IOS_DEVICE_TYPE - && deviceKind != Constants::IOS_SIMULATOR_TYPE) { - qCDebug(kitSetupLog) << "skipping existing kit with deviceKind " << deviceKind.toString(); + const QVariant debuggerId = (possibleDebugger ? possibleDebugger->id() : QVariant()); + + QSet<Kit *> existingKits = existingAutoDetectedIosKits(); + qCDebug(kitSetupLog) << "Existing auto-detected iOS kits:"; + printKits(existingKits); + QSet<Kit *> resultingKits; + // match existing kits and create missing kits + foreach (const Platform &platform, platforms) { + qCDebug(kitSetupLog) << "Guaranteeing kits for " << platform.name ; + ClangToolChain *pToolchain = platformToolChainHash.value(platform); + if (!pToolchain) { + qCDebug(kitSetupLog) << " - No tool chain found"; continue; } - if (!k->isAutoDetected()) - continue; - existingKits << k; - kitMatched << false; - } - // create missing kits - { - QMapIterator<QString, Platform> iter(platforms); - while (iter.hasNext()) { - iter.next(); - const Platform &p = iter.value(); - GccToolChain *pToolchain = platformToolchainMap.value(p.name, 0); - if (!pToolchain) - continue; - Core::Id pDeviceType; - qCDebug(kitSetupLog) << "guaranteeing kit for " << p.name ; - if (p.name.startsWith(QLatin1String("iphoneos-"))) { - pDeviceType = Constants::IOS_DEVICE_TYPE; - } else if (p.name.startsWith(QLatin1String("iphonesimulator-"))) { - pDeviceType = Constants::IOS_SIMULATOR_TYPE; - qCDebug(kitSetupLog) << "pDeviceType " << pDeviceType.toString(); + Core::Id pDeviceType = deviceId(platform); + QTC_ASSERT(pDeviceType.isValid(), continue); + Abi::Architecture arch = pToolchain->targetAbi().architecture(); + + QSet<BaseQtVersion *> qtVersions = qtVersionsForArch.value(arch); + foreach (BaseQtVersion *qtVersion, qtVersions) { + qCDebug(kitSetupLog) << " - Qt version:" << qtVersion->displayName(); + Kit *kit = Utils::findOrDefault(existingKits, [&pDeviceType, &pToolchain, &qtVersion](const Kit *kit) { + // we do not compare the sdk (thus automatically upgrading it in place if a + // new Xcode is used). Change? + return DeviceTypeKitInformation::deviceTypeId(kit) == pDeviceType + && ToolChainKitInformation::toolChain(kit) == pToolchain + && QtKitInformation::qtVersion(kit) == qtVersion; + }); + QTC_ASSERT(!resultingKits.contains(kit), continue); + if (kit) { + qCDebug(kitSetupLog) << " - Kit matches:" << kit->displayName(); + kit->blockNotification(); + setupKit(kit, pDeviceType, pToolchain, debuggerId, platform.sdkPath, qtVersion); + kit->unblockNotification(); } else { - qCDebug(kitSetupLog) << "skipping non ios kit " << p.name; - // we looked up only the ios qt build above... - continue; - //pDeviceType = Constants::DESKTOP_DEVICE_TYPE; - } - Abi::Architecture arch = pToolchain->targetAbi().architecture(); - - QList<BaseQtVersion *> qtVersions = qtVersionsForArch.value(arch); - foreach (BaseQtVersion *qt, qtVersions) { - Kit *kitAtt = 0; - bool kitExists = false; - for (int i = 0; i < existingKits.size(); ++i) { - Kit *k = existingKits.at(i); - if (DeviceTypeKitInformation::deviceTypeId(k) == pDeviceType - && ToolChainKitInformation::toolChain(k) == pToolchain - && QtKitInformation::qtVersion(k) == qt) - { - QTC_CHECK(!kitMatched.value(i, true)); - // as we generate only two kits per qt (one for device and one for simulator) - // we do not compare the sdk (thus automatically upgrading it in place if a - // new Xcode is used). Change? - kitExists = true; - kitAtt = k; - qCDebug(kitSetupLog) << "found existing kit " << k->displayName() << " for " << p.name - << "," << qt->displayName(); - if (i<kitMatched.size()) - kitMatched.replace(i, true); - break; - } - } - if (kitExists) { - kitAtt->blockNotification(); - // TODO: this is just to fix up broken display names from before - QString baseDisplayName = tr("%1 %2").arg(p.name, qt->unexpandedDisplayName()); - QString displayName = baseDisplayName; - for (int iVers = 1; iVers < 100; ++iVers) { - bool unique = true; - foreach (const Kit *k, existingKits) { - if (k == kitAtt) - continue; - if (k->displayName() == displayName) { - unique = false; - break; - } - } - if (unique) break; - displayName = baseDisplayName + QLatin1Char('-') + QString::number(iVers); - } - kitAtt->setUnexpandedDisplayName(displayName); - } else { - qCDebug(kitSetupLog) << "setting up new kit for " << p.name; - kitAtt = new Kit; - kitAtt->setAutoDetected(true); - QString baseDisplayName = tr("%1 %2").arg(p.name, qt->unexpandedDisplayName()); - QString displayName = baseDisplayName; - for (int iVers = 1; iVers < 100; ++iVers) { - bool unique = true; - foreach (const Kit *k, existingKits) { - if (k->displayName() == displayName) { - unique = false; - break; - } - } - if (unique) break; - displayName = baseDisplayName + QLatin1Char('-') + QString::number(iVers); - } - kitAtt->setUnexpandedDisplayName(displayName); - } - kitAtt->setIconPath(FileName::fromString( - QLatin1String(Constants::IOS_SETTINGS_CATEGORY_ICON))); - DeviceTypeKitInformation::setDeviceTypeId(kitAtt, pDeviceType); - ToolChainKitInformation::setToolChain(kitAtt, pToolchain); - QtKitInformation::setQtVersion(kitAtt, qt); - if ((!DebuggerKitInformation::debugger(kitAtt) - || !DebuggerKitInformation::debugger(kitAtt)->isValid() - || DebuggerKitInformation::debugger(kitAtt)->engineType() != LldbEngineType) - && debuggerId.isValid()) - DebuggerKitInformation::setDebugger(kitAtt, - debuggerId); - - kitAtt->setMutable(DeviceKitInformation::id(), true); - kitAtt->setSticky(QtKitInformation::id(), true); - kitAtt->setSticky(ToolChainKitInformation::id(), true); - kitAtt->setSticky(DeviceTypeKitInformation::id(), true); - kitAtt->setSticky(SysRootKitInformation::id(), true); - kitAtt->setSticky(DebuggerKitInformation::id(), false); - - SysRootKitInformation::setSysRoot(kitAtt, p.sdkPath); - // QmakeProjectManager::QmakeKitInformation::setMkspec(newKit, - // Utils::FileName::fromLatin1("macx-ios-clang"))); - if (kitExists) { - kitAtt->unblockNotification(); - } else { - KitManager::registerKit(kitAtt); - existingKits << kitAtt; - } + qCDebug(kitSetupLog) << " - Setting up new kit"; + kit = new Kit; + kit->blockNotification(); + kit->setAutoDetected(true); + const QString baseDisplayName = tr("%1 %2").arg(platform.name, qtVersion->unexpandedDisplayName()); + kit->setUnexpandedDisplayName(baseDisplayName); + setupKit(kit, pDeviceType, pToolchain, debuggerId, platform.sdkPath, qtVersion); + kit->unblockNotification(); + KitManager::registerKit(kit); } + resultingKits.insert(kit); } } - for (int i = 0; i < kitMatched.size(); ++i) { - // deleting extra (old) kits - if (!kitMatched.at(i)) { - qCWarning(kitSetupLog) << "deleting kit " << existingKits.at(i)->displayName(); - KitManager::deregisterKit(existingKits.at(i)); - } - } + // remove unused kits + existingKits.subtract(resultingKits); + qCDebug(kitSetupLog) << "Removing unused kits:"; + printKits(existingKits); + foreach (Kit *kit, existingKits) + KitManager::deregisterKit(kit); } static IosConfigurations *m_instance = 0; @@ -458,5 +356,32 @@ void IosConfigurations::setDeveloperPath(const FileName &devPath) } } +static ClangToolChain *createToolChain(const Platform &platform) +{ + ClangToolChain *toolChain = new ClangToolChain(ToolChain::AutoDetection); + toolChain->setDisplayName(platform.name); + toolChain->setPlatformCodeGenFlags(platform.backendFlags); + toolChain->setPlatformLinkerFlags(platform.backendFlags); + toolChain->resetToolChain(platform.compilerPath); + return toolChain; +} + +QList<ToolChain *> IosToolChainFactory::autoDetect(const QList<ToolChain *> &existingToolChains) +{ + QList<ClangToolChain *> existingClangToolChains = clangToolChains(existingToolChains); + const QList<Platform> platforms = handledPlatforms(); + QList<ClangToolChain *> toolChains; + toolChains.reserve(platforms.size()); + foreach (const Platform &platform, platforms) { + ClangToolChain *toolChain = findToolChainForPlatform(platform, existingClangToolChains); + if (!toolChain) { + ClangToolChain *newToolChain = createToolChain(platform); + toolChains.append(newToolChain); + existingClangToolChains.append(newToolChain); + } + } + return Utils::transform(toolChains, [](ClangToolChain *tc) -> ToolChain * { return tc; }); +} + } // namespace Internal } // namespace Ios diff --git a/src/plugins/ios/iosconfigurations.h b/src/plugins/ios/iosconfigurations.h index 9d9fea2df8..3bf7b3036a 100644 --- a/src/plugins/ios/iosconfigurations.h +++ b/src/plugins/ios/iosconfigurations.h @@ -31,6 +31,7 @@ #define IOSCONFIGURATIONS_H #include <projectexplorer/abi.h> +#include <projectexplorer/toolchain.h> #include <utils/fileutils.h> #include <QObject> @@ -44,6 +45,15 @@ QT_END_NAMESPACE namespace Ios { namespace Internal { +class IosToolChainFactory : public ProjectExplorer::ToolChainFactory +{ + Q_OBJECT + +public: + QList<ProjectExplorer::ToolChain *> autoDetect(const QList<ProjectExplorer::ToolChain *> &existingToolChains) override; +}; + + class IosConfigurations : public QObject { Q_OBJECT diff --git a/src/plugins/ios/iosplugin.cpp b/src/plugins/ios/iosplugin.cpp index a3412057d9..5ac0b11b0c 100644 --- a/src/plugins/ios/iosplugin.cpp +++ b/src/plugins/ios/iosplugin.cpp @@ -69,6 +69,7 @@ bool IosPlugin::initialize(const QStringList &arguments, QString *errorMessage) Internal::IosConfigurations::initialize(); + addAutoReleasedObject(new Internal::IosToolChainFactory); addAutoReleasedObject(new Internal::IosRunControlFactory); addAutoReleasedObject(new Internal::IosRunConfigurationFactory); addAutoReleasedObject(new Internal::IosSettingsPage); diff --git a/src/plugins/ios/iosprobe.cpp b/src/plugins/ios/iosprobe.cpp index 49634dcfbc..d48e97a4a5 100644 --- a/src/plugins/ios/iosprobe.cpp +++ b/src/plugins/ios/iosprobe.cpp @@ -290,4 +290,24 @@ QMap<QString, Platform> IosProbe::detectedPlatforms() return m_platforms; } +QDebug operator<<(QDebug debug, const Platform &platform) +{ + QDebugStateSaver saver(debug); Q_UNUSED(saver) + debug.nospace() << "(name=" << platform.name + << ", compiler=" << platform.compilerPath.toString() + << ", flags=" << platform.backendFlags + << ")"; + return debug; +} + +bool Platform::operator==(const Platform &other) const +{ + return name == other.name; +} + +uint qHash(const Platform &platform) +{ + return qHash(platform.name); +} + } diff --git a/src/plugins/ios/iosprobe.h b/src/plugins/ios/iosprobe.h index 8f70f1fa8e..2459c7c1e3 100644 --- a/src/plugins/ios/iosprobe.h +++ b/src/plugins/ios/iosprobe.h @@ -54,8 +54,14 @@ public: Utils::FileName compilerPath; QString architecture; QStringList backendFlags; + + // ignores anything besides name + bool operator==(const Platform &other) const; }; +uint qHash(const Platform &platform); +QDebug operator<<(QDebug debug, const Platform &platform); + class IosProbe { public: |