Commit 0aae98fb authored by Daniel Teske's avatar Daniel Teske

Android: Only create Kits for the newest toolchains

It's rare that users will want older toolchains.
In updateAutomaticKits distinguish between a Kit being removed since
the toolchain doesn't exist anymore. Which happens on e.g. changing
the ndk path. If the toolchain still exists, then it isn't the
newest anymore, so demote the Kit to a manual kit thus enabling the
user to remove it if he no longer needs it.

Change-Id: I59203abc9bed5f2c46a002cea68fd72a84283840
Reviewed-by: default avatarEskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@digia.com>
Reviewed-by: default avatarTobias Hunger <tobias.hunger@digia.com>
parent 7dd56b5b
......@@ -779,6 +779,8 @@ void AndroidConfigurations::updateAutomaticKitList()
foreach (AndroidToolChain *tc, toolchains) {
QList<QtSupport::BaseQtVersion *> 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<AndroidToolChain *>(ToolChainKitInformation::toolChain(kit));
......
......@@ -32,6 +32,8 @@
#include "androidconfigurations.h"
#include "androidqtversion.h"
#include <extensionsystem/pluginmanager.h>
#include <qtsupport/qtkitinformation.h>
#include <qtsupport/qtversionmanager.h>
......@@ -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<ProjectExplorer::Abi::Architecture, QList<int> > 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<AndroidToolChainFactory>();
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<Abi> AndroidToolChain::detectSupportedAbis() const
{
return QList<Abi>() << targetAbi();
......@@ -297,6 +318,51 @@ QList<AndroidToolChainFactory::AndroidToolChainInformation> AndroidToolChainFact
return result;
}
QList<int> AndroidToolChainFactory::versionNumberFromString(const QString &version)
{
QList<int> 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<int> &a, const QList<int> &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<int> a = versionNumberFromString(atc->ndkToolChainVersion());
QList<int> b = versionNumberFromString(btc->ndkToolChainVersion());
return versionCompareLess(a, b);
}
QList<ToolChain *> AndroidToolChainFactory::createToolChainsForNdk(const Utils::FileName &ndkPath)
{
QList<ToolChain *> result;
......@@ -306,6 +372,8 @@ QList<ToolChain *> AndroidToolChainFactory::createToolChainsForNdk(const Utils::
FileName path = ndkPath;
QDirIterator it(path.appendPath(QLatin1String("toolchains")).toString(),
QStringList() << QLatin1String("*"), QDir::Dirs);
QMap<Abi::Architecture, AndroidToolChain *> newestToolChainForArch;
while (it.hasNext()) {
const QString &fileName = QFileInfo(it.next()).fileName();
int idx = versionRegExp.indexIn(fileName);
......@@ -320,9 +388,53 @@ QList<ToolChain *> AndroidToolChainFactory::createToolChainsForNdk(const Utils::
FileName compilerPath = AndroidConfigurations::instance().gccPath(arch, version);
tc->setCompilerCommand(compilerPath);
result.append(tc);
QMap<Abi::Architecture, AndroidToolChain *>::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<AndroidToolChain *>(tc);
if (newestToolChainForArch.value(atc->targetAbi().architecture()) != atc)
atc->setSecondaryToolChain(true);
}
return result;
}
QList<int> 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<int> 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<Abi::Architecture, QList<int> >::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
......@@ -61,6 +61,9 @@ public:
QString ndkToolChainVersion();
bool secondaryToolChain() const;
void setSecondaryToolChain(bool b);
protected:
QList<ProjectExplorer::Abi> 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<ProjectExplorer::ToolChain *> createToolChainsForNdk(const Utils::FileName &ndkPath);
static QList<AndroidToolChainInformation> toolchainPathsForNdk(const Utils::FileName &ndkPath);
static QList<int> versionNumberFromString(const QString &version);
static bool versionCompareLess(const QList<int> &a, const QList<int> &b);
static bool versionCompareLess(AndroidToolChain *atc, AndroidToolChain *btc);
static QList<int> newestToolChainVersionForArch(ProjectExplorer::Abi::Architecture arch);
private:
static QMap<ProjectExplorer::Abi::Architecture, QList<int> > m_newestVersionForArch;
static Utils::FileName m_ndkLocation;
};
} // namespace Internal
......
......@@ -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) {
......
......@@ -103,6 +103,7 @@ public:
void setAutoDetected(bool detected);
void makeSticky();
void makeSticky(Core::Id id);
void makeUnSticky();
private:
void setSdkProvided(bool sdkProvided);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment