diff --git a/src/plugins/android/androidconfigurations.cpp b/src/plugins/android/androidconfigurations.cpp index d1de89ba31f..ac4bf5ead5f 100644 --- a/src/plugins/android/androidconfigurations.cpp +++ b/src/plugins/android/androidconfigurations.cpp @@ -779,6 +779,8 @@ void AndroidConfigurations::updateAutomaticKitList() foreach (AndroidToolChain *tc, toolchains) { QList qtVersions = qtVersionsForArch.value(tc->targetAbi().architecture()); foreach (QtSupport::BaseQtVersion *qt, qtVersions) { + if (tc->secondaryToolChain()) + continue; Kit *newKit = new Kit; newKit->setAutoDetected(true); newKit->setIconPath(Utils::FileName::fromString(QLatin1String(Constants::ANDROID_SETTINGS_CATEGORY_ICON))); @@ -809,8 +811,15 @@ void AndroidConfigurations::updateAutomaticKitList() } } - foreach (Kit *k, existingKits) - KitManager::deregisterKit(k); + foreach (Kit *k, existingKits) { + ProjectExplorer::ToolChain *tc = ToolChainKitInformation::toolChain(k); + if (tc && tc->type() == QLatin1String(Android::Constants::ANDROID_TOOLCHAIN_TYPE)) { + k->makeUnSticky(); + k->setAutoDetected(false); + } else { + KitManager::deregisterKit(k); + } + } foreach (Kit *kit, newKits) { AndroidToolChain *tc = static_cast(ToolChainKitInformation::toolChain(kit)); diff --git a/src/plugins/android/androidtoolchain.cpp b/src/plugins/android/androidtoolchain.cpp index f5ad4fe2bd5..58c1acf35b0 100644 --- a/src/plugins/android/androidtoolchain.cpp +++ b/src/plugins/android/androidtoolchain.cpp @@ -32,6 +32,8 @@ #include "androidconfigurations.h" #include "androidqtversion.h" +#include + #include #include @@ -61,9 +63,12 @@ using namespace Utils; static const char ANDROID_QT_VERSION_KEY[] = "Qt4ProjectManager.Android.QtVersion"; static const char ANDROID_NDK_TC_VERION[] = "Qt4ProjectManager.Android.NDK_TC_VERION"; +QMap > AndroidToolChainFactory::m_newestVersionForArch; +Utils::FileName AndroidToolChainFactory::m_ndkLocation; + AndroidToolChain::AndroidToolChain(Abi::Architecture arch, const QString &ndkToolChainVersion, bool autodetected) : GccToolChain(QLatin1String(Constants::ANDROID_TOOLCHAIN_ID), autodetected), - m_ndkToolChainVersion(ndkToolChainVersion) + m_ndkToolChainVersion(ndkToolChainVersion), m_secondaryToolChain(false) { ProjectExplorer::Abi abi = ProjectExplorer::Abi(arch, ProjectExplorer::Abi::LinuxOS, ProjectExplorer::Abi::AndroidLinuxFlavor, ProjectExplorer::Abi::ElfFormat, @@ -76,12 +81,14 @@ AndroidToolChain::AndroidToolChain(Abi::Architecture arch, const QString &ndkToo // for fromMap AndroidToolChain::AndroidToolChain() - : GccToolChain(QLatin1String(Constants::ANDROID_TOOLCHAIN_ID), false) + : GccToolChain(QLatin1String(Constants::ANDROID_TOOLCHAIN_ID), false), + m_secondaryToolChain(false) { } AndroidToolChain::AndroidToolChain(const AndroidToolChain &tc) : - GccToolChain(tc), m_ndkToolChainVersion(tc.m_ndkToolChainVersion) + GccToolChain(tc), m_ndkToolChainVersion(tc.m_ndkToolChainVersion), + m_secondaryToolChain(tc.m_secondaryToolChain) { } AndroidToolChain::~AndroidToolChain() @@ -194,6 +201,10 @@ bool AndroidToolChain::fromMap(const QVariantMap &data) m_ndkToolChainVersion = data.value(QLatin1String(ANDROID_NDK_TC_VERION)).toString(); } + AndroidToolChainFactory *factory = ExtensionSystem::PluginManager::getObject(); + ProjectExplorer::Abi::Architecture arch = targetAbi().architecture(); + m_secondaryToolChain = AndroidToolChainFactory::versionCompareLess(AndroidToolChainFactory::versionNumberFromString(m_ndkToolChainVersion), + factory->newestToolChainVersionForArch(arch)); return isValid(); } @@ -223,6 +234,16 @@ QString AndroidToolChain::ndkToolChainVersion() return m_ndkToolChainVersion; } +bool AndroidToolChain::secondaryToolChain() const +{ + return m_secondaryToolChain; +} + +void AndroidToolChain::setSecondaryToolChain(bool b) +{ + m_secondaryToolChain = b; +} + QList AndroidToolChain::detectSupportedAbis() const { return QList() << targetAbi(); @@ -297,6 +318,51 @@ QList AndroidToolChainFact return result; } +QList AndroidToolChainFactory::versionNumberFromString(const QString &version) +{ + QList result; + int start = 0; + int end = version.length(); + while (start <= end) { + int index = version.indexOf(QLatin1Char('.'), start); + if (index == -1) + index = end; + + bool ok; + int v = version.mid(start, index - start).toInt(&ok); + if (!ok) // unparseable, return what we have + return result; + + result << v; + start = index + 1; + } + return result; +} + +bool AndroidToolChainFactory::versionCompareLess(const QList &a, const QList &b) +{ + int aend = a.length(); + int bend = b.length(); + int end = qMax(aend, bend); + for (int i = 0; i < end; ++i) { + int an = i < aend ? a.at(i) : 0; + int bn = i < bend ? b.at(i) : 0; + if (an < bn) + return true; + if (bn < an) + return false; + } + return false; +} + +bool AndroidToolChainFactory::versionCompareLess(AndroidToolChain *atc, AndroidToolChain *btc) +{ + QList a = versionNumberFromString(atc->ndkToolChainVersion()); + QList b = versionNumberFromString(btc->ndkToolChainVersion()); + + return versionCompareLess(a, b); +} + QList AndroidToolChainFactory::createToolChainsForNdk(const Utils::FileName &ndkPath) { QList result; @@ -306,6 +372,8 @@ QList AndroidToolChainFactory::createToolChainsForNdk(const Utils:: FileName path = ndkPath; QDirIterator it(path.appendPath(QLatin1String("toolchains")).toString(), QStringList() << QLatin1String("*"), QDir::Dirs); + QMap newestToolChainForArch; + while (it.hasNext()) { const QString &fileName = QFileInfo(it.next()).fileName(); int idx = versionRegExp.indexIn(fileName); @@ -320,9 +388,53 @@ QList AndroidToolChainFactory::createToolChainsForNdk(const Utils:: FileName compilerPath = AndroidConfigurations::instance().gccPath(arch, version); tc->setCompilerCommand(compilerPath); result.append(tc); + + QMap::const_iterator it + = newestToolChainForArch.constFind(arch); + if (it == newestToolChainForArch.constEnd()) + newestToolChainForArch.insert(arch, tc); + else if (versionCompareLess(it.value(), tc)) + newestToolChainForArch[arch] = tc; } + + foreach (ToolChain *tc, result) { + AndroidToolChain *atc = static_cast(tc); + if (newestToolChainForArch.value(atc->targetAbi().architecture()) != atc) + atc->setSecondaryToolChain(true); + } + return result; } +QList AndroidToolChainFactory::newestToolChainVersionForArch(Abi::Architecture arch) +{ + if (m_newestVersionForArch.isEmpty() + || m_ndkLocation != AndroidConfigurations::instance().config().ndkLocation) { + QRegExp versionRegExp(NDKGccVersionRegExp); + m_ndkLocation = AndroidConfigurations::instance().config().ndkLocation; + FileName path = m_ndkLocation; + QDirIterator it(path.appendPath(QLatin1String("toolchains")).toString(), + QStringList() << QLatin1String("*"), QDir::Dirs); + while (it.hasNext()) { + const QString &fileName = QFileInfo(it.next()).fileName(); + int idx = versionRegExp.indexIn(fileName); + if (idx == -1) + continue; + QList version = versionNumberFromString(fileName.mid(idx + 1)); + QString platform = fileName.left(idx); + Abi::Architecture arch = AndroidConfigurations::architectureForToolChainPrefix(platform); + if (arch == Abi::UnknownArchitecture) // e.g. mipsel which is not yet supported + continue; + QMap >::const_iterator it + = m_newestVersionForArch.constFind(arch); + if (it == m_newestVersionForArch.constEnd()) + m_newestVersionForArch.insert(arch, version); + else if (versionCompareLess(it.value(), version)) + m_newestVersionForArch[arch] = version; + } + } + return m_newestVersionForArch.value(arch); +} + } // namespace Internal } // namespace Android diff --git a/src/plugins/android/androidtoolchain.h b/src/plugins/android/androidtoolchain.h index 111a1e90e3c..7999686460a 100644 --- a/src/plugins/android/androidtoolchain.h +++ b/src/plugins/android/androidtoolchain.h @@ -61,6 +61,9 @@ public: QString ndkToolChainVersion(); + bool secondaryToolChain() const; + void setSecondaryToolChain(bool b); + protected: QList detectSupportedAbis() const; @@ -70,6 +73,8 @@ private: AndroidToolChain(const AndroidToolChain &); QString m_ndkToolChainVersion; + bool m_secondaryToolChain; + friend class AndroidToolChainFactory; }; @@ -110,6 +115,14 @@ public: static QList createToolChainsForNdk(const Utils::FileName &ndkPath); static QList toolchainPathsForNdk(const Utils::FileName &ndkPath); + + static QList versionNumberFromString(const QString &version); + static bool versionCompareLess(const QList &a, const QList &b); + static bool versionCompareLess(AndroidToolChain *atc, AndroidToolChain *btc); + static QList newestToolChainVersionForArch(ProjectExplorer::Abi::Architecture arch); +private: + static QMap > m_newestVersionForArch; + static Utils::FileName m_ndkLocation; }; } // namespace Internal diff --git a/src/plugins/projectexplorer/kit.cpp b/src/plugins/projectexplorer/kit.cpp index 3116abeb48d..bada204cb2a 100644 --- a/src/plugins/projectexplorer/kit.cpp +++ b/src/plugins/projectexplorer/kit.cpp @@ -481,6 +481,11 @@ void Kit::makeSticky(Core::Id id) d->m_sticky.insert(id); } +void Kit::makeUnSticky() +{ + d->m_sticky.clear(); +} + void Kit::kitUpdated() { if (d->m_nestedBlockingLevel > 0 && !d->m_mustNotifyAboutDisplayName) { diff --git a/src/plugins/projectexplorer/kit.h b/src/plugins/projectexplorer/kit.h index 50b345f8b32..b781c792b1f 100644 --- a/src/plugins/projectexplorer/kit.h +++ b/src/plugins/projectexplorer/kit.h @@ -103,6 +103,7 @@ public: void setAutoDetected(bool detected); void makeSticky(); void makeSticky(Core::Id id); + void makeUnSticky(); private: void setSdkProvided(bool sdkProvided);