2016-01-15 14:57:40 +01:00
|
|
|
/****************************************************************************
|
2012-04-18 20:30:57 +03:00
|
|
|
**
|
2016-01-15 14:57:40 +01:00
|
|
|
** Copyright (C) 2016 BogDan Vatra <bog_dan_ro@yahoo.com>
|
|
|
|
|
** Contact: https://www.qt.io/licensing/
|
2012-04-18 20:30:57 +03:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
** This file is part of Qt Creator.
|
2012-04-18 20:30:57 +03:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
** Commercial License Usage
|
|
|
|
|
** Licensees holding valid commercial Qt licenses may use this file in
|
|
|
|
|
** accordance with the commercial license agreement provided with the
|
|
|
|
|
** Software or, alternatively, in accordance with the terms contained in
|
2016-01-15 14:57:40 +01:00
|
|
|
** a written agreement between you and The Qt Company. For licensing terms
|
|
|
|
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
|
|
|
|
** information use the contact form at https://www.qt.io/contact-us.
|
2012-04-18 20:30:57 +03:00
|
|
|
**
|
2016-01-15 14:57:40 +01:00
|
|
|
** GNU General Public License Usage
|
|
|
|
|
** Alternatively, this file may be used under the terms of the GNU
|
|
|
|
|
** General Public License version 3 as published by the Free Software
|
|
|
|
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
|
|
|
|
** included in the packaging of this file. Please review the following
|
|
|
|
|
** information to ensure the GNU General Public License requirements will
|
|
|
|
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
2012-04-18 20:30:57 +03:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
****************************************************************************/
|
2012-04-18 20:30:57 +03:00
|
|
|
|
|
|
|
|
#include "androidtoolchain.h"
|
|
|
|
|
#include "androidconstants.h"
|
|
|
|
|
#include "androidconfigurations.h"
|
|
|
|
|
#include "androidqtversion.h"
|
2012-12-07 19:52:56 +02:00
|
|
|
|
2013-08-28 13:34:24 +02:00
|
|
|
#include <extensionsystem/pluginmanager.h>
|
|
|
|
|
|
2012-12-07 19:52:56 +02:00
|
|
|
#include <qtsupport/qtkitinformation.h>
|
|
|
|
|
#include <qtsupport/qtversionmanager.h>
|
|
|
|
|
|
2012-07-03 16:57:44 +03:00
|
|
|
#include <projectexplorer/target.h>
|
2012-04-18 20:30:57 +03:00
|
|
|
#include <projectexplorer/toolchainmanager.h>
|
|
|
|
|
#include <projectexplorer/projectexplorer.h>
|
|
|
|
|
|
2015-10-15 16:01:40 +02:00
|
|
|
#include <utils/algorithm.h>
|
2012-04-18 20:30:57 +03:00
|
|
|
#include <utils/environment.h>
|
2012-08-23 15:53:58 +02:00
|
|
|
#include <utils/hostosinfo.h>
|
2012-04-18 20:30:57 +03:00
|
|
|
|
|
|
|
|
#include <QDir>
|
2013-01-25 16:49:22 +01:00
|
|
|
#include <QDirIterator>
|
2012-08-16 15:59:10 +02:00
|
|
|
#include <QFormLayout>
|
2012-04-18 20:30:57 +03:00
|
|
|
#include <QLabel>
|
|
|
|
|
#include <QVBoxLayout>
|
|
|
|
|
|
2013-01-25 16:49:22 +01:00
|
|
|
namespace {
|
|
|
|
|
const QLatin1String NDKGccVersionRegExp("-\\d[\\.\\d]+");
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-18 20:30:57 +03:00
|
|
|
namespace Android {
|
|
|
|
|
namespace Internal {
|
|
|
|
|
|
2012-08-09 01:56:51 +02:00
|
|
|
using namespace ProjectExplorer;
|
2012-08-23 15:53:58 +02:00
|
|
|
using namespace Utils;
|
2012-04-18 20:30:57 +03:00
|
|
|
|
|
|
|
|
static const char ANDROID_QT_VERSION_KEY[] = "Qt4ProjectManager.Android.QtVersion";
|
2013-01-25 16:49:22 +01:00
|
|
|
static const char ANDROID_NDK_TC_VERION[] = "Qt4ProjectManager.Android.NDK_TC_VERION";
|
2012-04-18 20:30:57 +03:00
|
|
|
|
2014-11-18 18:37:05 +01:00
|
|
|
QHash<Abi, QList<int> > AndroidToolChainFactory::m_newestVersionForAbi;
|
2015-02-03 23:50:37 +02:00
|
|
|
FileName AndroidToolChainFactory::m_ndkLocation;
|
2013-08-28 13:34:24 +02:00
|
|
|
|
2014-11-18 18:37:05 +01:00
|
|
|
AndroidToolChain::AndroidToolChain(const Abi &abi, const QString &ndkToolChainVersion, Detection d)
|
2015-07-07 12:01:22 +02:00
|
|
|
: GccToolChain(Constants::ANDROID_TOOLCHAIN_ID, d),
|
2013-08-28 13:34:24 +02:00
|
|
|
m_ndkToolChainVersion(ndkToolChainVersion), m_secondaryToolChain(false)
|
2013-01-25 16:49:22 +01:00
|
|
|
{
|
|
|
|
|
setTargetAbi(abi);
|
|
|
|
|
setDisplayName(QString::fromLatin1("Android GCC (%1-%2)")
|
2014-11-18 18:37:05 +01:00
|
|
|
.arg(AndroidConfig::displayName(targetAbi()))
|
2013-01-25 16:49:22 +01:00
|
|
|
.arg(ndkToolChainVersion));
|
|
|
|
|
}
|
2012-04-18 20:30:57 +03:00
|
|
|
|
2013-01-25 16:49:22 +01:00
|
|
|
// for fromMap
|
|
|
|
|
AndroidToolChain::AndroidToolChain()
|
2015-07-07 12:01:22 +02:00
|
|
|
: GccToolChain(Constants::ANDROID_TOOLCHAIN_ID, ToolChain::ManualDetection),
|
2013-08-28 13:34:24 +02:00
|
|
|
m_secondaryToolChain(false)
|
2013-01-25 16:49:22 +01:00
|
|
|
{
|
|
|
|
|
}
|
2012-04-18 20:30:57 +03:00
|
|
|
|
|
|
|
|
AndroidToolChain::AndroidToolChain(const AndroidToolChain &tc) :
|
2013-08-28 13:34:24 +02:00
|
|
|
GccToolChain(tc), m_ndkToolChainVersion(tc.m_ndkToolChainVersion),
|
|
|
|
|
m_secondaryToolChain(tc.m_secondaryToolChain)
|
2012-04-18 20:30:57 +03:00
|
|
|
{ }
|
|
|
|
|
|
|
|
|
|
AndroidToolChain::~AndroidToolChain()
|
|
|
|
|
{ }
|
|
|
|
|
|
|
|
|
|
QString AndroidToolChain::typeDisplayName() const
|
|
|
|
|
{
|
|
|
|
|
return AndroidToolChainFactory::tr("Android GCC");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool AndroidToolChain::isValid() const
|
|
|
|
|
{
|
2013-02-27 12:33:21 +01:00
|
|
|
return GccToolChain::isValid() && targetAbi().isValid() && !m_ndkToolChainVersion.isEmpty()
|
2013-12-16 20:19:07 +01:00
|
|
|
&& compilerCommand().isChildOf(AndroidConfigurations::currentConfig().ndkLocation());
|
2012-04-18 20:30:57 +03:00
|
|
|
}
|
|
|
|
|
|
2012-08-23 15:53:58 +02:00
|
|
|
void AndroidToolChain::addToEnvironment(Environment &env) const
|
2012-04-18 20:30:57 +03:00
|
|
|
{
|
|
|
|
|
// TODO this vars should be configurable in projects -> build tab
|
|
|
|
|
// TODO invalidate all .pro files !!!
|
|
|
|
|
|
2013-12-16 20:19:07 +01:00
|
|
|
env.set(QLatin1String("ANDROID_NDK_HOST"), AndroidConfigurations::currentConfig().toolchainHost());
|
2014-11-18 18:37:05 +01:00
|
|
|
env.set(QLatin1String("ANDROID_NDK_TOOLCHAIN_PREFIX"), AndroidConfig::toolchainPrefix(targetAbi()));
|
|
|
|
|
env.set(QLatin1String("ANDROID_NDK_TOOLS_PREFIX"), AndroidConfig::toolsPrefix(targetAbi()));
|
2013-01-25 16:49:22 +01:00
|
|
|
env.set(QLatin1String("ANDROID_NDK_TOOLCHAIN_VERSION"), m_ndkToolChainVersion);
|
2015-11-20 14:11:26 +01:00
|
|
|
const Utils::FileName javaHome = AndroidConfigurations::currentConfig().openJDKLocation();
|
|
|
|
|
if (!javaHome.isEmpty() && javaHome.toFileInfo().exists()) {
|
|
|
|
|
env.set(QLatin1String("JAVA_HOME"), javaHome.toString());
|
|
|
|
|
Utils::FileName javaBin = javaHome;
|
|
|
|
|
javaBin.appendPath(QLatin1String("bin"));
|
|
|
|
|
const QString jb = javaBin.toUserOutput();
|
|
|
|
|
if (!Utils::contains(env.path(), [&jb](const QString &p) { return p == jb; }))
|
|
|
|
|
env.prependOrSetPath(jb);
|
|
|
|
|
}
|
2013-12-16 20:19:07 +01:00
|
|
|
env.set(QLatin1String("ANDROID_HOME"), AndroidConfigurations::currentConfig().sdkLocation().toString());
|
|
|
|
|
env.set(QLatin1String("ANDROID_SDK_ROOT"), AndroidConfigurations::currentConfig().sdkLocation().toString());
|
2012-04-18 20:30:57 +03:00
|
|
|
}
|
|
|
|
|
|
2012-08-09 01:56:51 +02:00
|
|
|
bool AndroidToolChain::operator ==(const ToolChain &tc) const
|
2012-04-18 20:30:57 +03:00
|
|
|
{
|
2013-01-25 16:49:22 +01:00
|
|
|
if (!GccToolChain::operator ==(tc))
|
2012-04-18 20:30:57 +03:00
|
|
|
return false;
|
|
|
|
|
|
2013-01-25 16:49:22 +01:00
|
|
|
return m_ndkToolChainVersion == static_cast<const AndroidToolChain &>(tc).m_ndkToolChainVersion;
|
2012-04-18 20:30:57 +03:00
|
|
|
}
|
|
|
|
|
|
2012-08-09 01:56:51 +02:00
|
|
|
ToolChainConfigWidget *AndroidToolChain::configurationWidget()
|
2012-04-18 20:30:57 +03:00
|
|
|
{
|
|
|
|
|
return new AndroidToolChainConfigWidget(this);
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-25 16:49:22 +01:00
|
|
|
FileName AndroidToolChain::suggestedDebugger() const
|
|
|
|
|
{
|
2014-11-18 18:37:05 +01:00
|
|
|
return AndroidConfigurations::currentConfig().gdbPath(targetAbi(), m_ndkToolChainVersion);
|
2013-01-25 16:49:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FileName AndroidToolChain::suggestedGdbServer() const
|
|
|
|
|
{
|
2015-02-03 23:50:37 +02:00
|
|
|
FileName path = AndroidConfigurations::currentConfig().ndkLocation();
|
2013-01-25 16:49:22 +01:00
|
|
|
path.appendPath(QString::fromLatin1("prebuilt/android-%1/gdbserver/gdbserver")
|
|
|
|
|
.arg(Abi::toString(targetAbi().architecture())));
|
2014-10-24 13:15:54 +02:00
|
|
|
if (path.exists())
|
2013-01-25 16:49:22 +01:00
|
|
|
return path;
|
2013-12-16 20:19:07 +01:00
|
|
|
path = AndroidConfigurations::currentConfig().ndkLocation();
|
2013-01-25 16:49:22 +01:00
|
|
|
path.appendPath(QString::fromLatin1("toolchains/%1-%2/prebuilt/gdbserver")
|
2014-11-18 18:37:05 +01:00
|
|
|
.arg(AndroidConfig::toolchainPrefix(targetAbi()))
|
2013-01-25 16:49:22 +01:00
|
|
|
.arg(m_ndkToolChainVersion));
|
2014-10-24 13:15:54 +02:00
|
|
|
if (path.exists())
|
2013-01-25 16:49:22 +01:00
|
|
|
return path;
|
|
|
|
|
|
2015-02-03 23:50:37 +02:00
|
|
|
return FileName();
|
2013-01-25 16:49:22 +01:00
|
|
|
}
|
|
|
|
|
|
2012-04-18 20:30:57 +03:00
|
|
|
QVariantMap AndroidToolChain::toMap() const
|
|
|
|
|
{
|
|
|
|
|
QVariantMap result = GccToolChain::toMap();
|
2013-01-25 16:49:22 +01:00
|
|
|
result.insert(QLatin1String(ANDROID_NDK_TC_VERION), m_ndkToolChainVersion);
|
2012-04-18 20:30:57 +03:00
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool AndroidToolChain::fromMap(const QVariantMap &data)
|
|
|
|
|
{
|
|
|
|
|
if (!GccToolChain::fromMap(data))
|
|
|
|
|
return false;
|
|
|
|
|
|
2013-01-25 16:49:22 +01:00
|
|
|
if (data.contains(QLatin1String(ANDROID_QT_VERSION_KEY))) {
|
|
|
|
|
QString command = compilerCommand().toString();
|
2013-12-16 20:19:07 +01:00
|
|
|
QString ndkPath = AndroidConfigurations::currentConfig().ndkLocation().toString();
|
2013-01-25 16:49:22 +01:00
|
|
|
if (!command.startsWith(ndkPath))
|
|
|
|
|
return false;
|
|
|
|
|
command = command.mid(ndkPath.length());
|
|
|
|
|
if (!command.startsWith(QLatin1String("/toolchains/")))
|
|
|
|
|
return false;
|
|
|
|
|
command = command.mid(12);
|
|
|
|
|
int index = command.indexOf(QLatin1Char('/'));
|
|
|
|
|
if (index == -1)
|
|
|
|
|
return false;
|
|
|
|
|
command = command.left(index);
|
|
|
|
|
QRegExp versionRegExp(NDKGccVersionRegExp);
|
|
|
|
|
index = versionRegExp.indexIn(command);
|
|
|
|
|
if (index == -1)
|
|
|
|
|
return false;
|
|
|
|
|
m_ndkToolChainVersion = command.mid(index + 1);
|
|
|
|
|
QString platform = command.left(index);
|
2014-11-18 18:37:05 +01:00
|
|
|
setTargetAbi(AndroidConfig::abiForToolChainPrefix(platform));
|
2013-01-25 16:49:22 +01:00
|
|
|
} else {
|
|
|
|
|
m_ndkToolChainVersion = data.value(QLatin1String(ANDROID_NDK_TC_VERION)).toString();
|
|
|
|
|
}
|
2012-04-18 20:30:57 +03:00
|
|
|
|
2014-11-18 18:37:05 +01:00
|
|
|
Abi abi = targetAbi();
|
2013-08-28 13:34:24 +02:00
|
|
|
m_secondaryToolChain = AndroidToolChainFactory::versionCompareLess(AndroidToolChainFactory::versionNumberFromString(m_ndkToolChainVersion),
|
2014-11-18 18:37:05 +01:00
|
|
|
AndroidToolChainFactory::newestToolChainVersionForArch(abi));
|
2012-04-18 20:30:57 +03:00
|
|
|
return isValid();
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-03 14:01:25 +01:00
|
|
|
FileNameList AndroidToolChain::suggestedMkspecList() const
|
2012-04-18 20:30:57 +03:00
|
|
|
{
|
2015-11-03 14:01:25 +01:00
|
|
|
return FileNameList()<< FileName::fromLatin1("android-g++");
|
2012-04-18 20:30:57 +03:00
|
|
|
}
|
|
|
|
|
|
2015-02-03 23:50:37 +02:00
|
|
|
QString AndroidToolChain::makeCommand(const Environment &env) const
|
2012-04-18 20:30:57 +03:00
|
|
|
{
|
2013-12-16 20:19:07 +01:00
|
|
|
QStringList extraDirectories = AndroidConfigurations::currentConfig().makeExtraSearchDirectories();
|
2013-05-13 13:37:31 +02:00
|
|
|
if (HostOsInfo::isWindowsHost()) {
|
2014-07-15 23:32:11 +03:00
|
|
|
FileName tmp = env.searchInPath(QLatin1String("ma-make.exe"), extraDirectories);
|
2013-05-13 13:37:31 +02:00
|
|
|
if (!tmp.isEmpty())
|
2014-07-15 23:32:11 +03:00
|
|
|
return QString();
|
2013-05-13 13:37:31 +02:00
|
|
|
tmp = env.searchInPath(QLatin1String("mingw32-make"), extraDirectories);
|
2014-07-15 23:32:11 +03:00
|
|
|
return tmp.isEmpty() ? QLatin1String("mingw32-make") : tmp.toString();
|
2013-05-13 13:37:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString make = QLatin1String("make");
|
2014-07-15 23:32:11 +03:00
|
|
|
FileName tmp = env.searchInPath(make, extraDirectories);
|
|
|
|
|
return tmp.isEmpty() ? make : tmp.toString();
|
2012-04-18 20:30:57 +03:00
|
|
|
}
|
|
|
|
|
|
2013-10-11 11:29:06 +02:00
|
|
|
QString AndroidToolChain::ndkToolChainVersion() const
|
2012-04-18 20:30:57 +03:00
|
|
|
{
|
2013-01-25 16:49:22 +01:00
|
|
|
return m_ndkToolChainVersion;
|
2012-04-18 20:30:57 +03:00
|
|
|
}
|
|
|
|
|
|
2013-10-11 11:29:06 +02:00
|
|
|
bool AndroidToolChain::isSecondaryToolChain() const
|
2013-08-28 13:34:24 +02:00
|
|
|
{
|
|
|
|
|
return m_secondaryToolChain;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AndroidToolChain::setSecondaryToolChain(bool b)
|
|
|
|
|
{
|
|
|
|
|
m_secondaryToolChain = b;
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-09 01:56:51 +02:00
|
|
|
QList<Abi> AndroidToolChain::detectSupportedAbis() const
|
2012-04-18 20:30:57 +03:00
|
|
|
{
|
2013-01-25 16:49:22 +01:00
|
|
|
return QList<Abi>() << targetAbi();
|
2012-04-18 20:30:57 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
|
// ToolChainConfigWidget
|
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
AndroidToolChainConfigWidget::AndroidToolChainConfigWidget(AndroidToolChain *tc) :
|
2012-08-09 01:56:51 +02:00
|
|
|
ToolChainConfigWidget(tc)
|
2012-04-18 20:30:57 +03:00
|
|
|
{
|
2013-12-16 20:19:07 +01:00
|
|
|
QLabel *label = new QLabel(AndroidConfigurations::currentConfig().ndkLocation().toUserOutput());
|
2012-08-16 15:59:10 +02:00
|
|
|
m_mainLayout->addRow(tr("NDK Root:"), label);
|
2012-04-18 20:30:57 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
|
// ToolChainFactory
|
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
|
|
2013-08-09 17:49:30 +02:00
|
|
|
AndroidToolChainFactory::AndroidToolChainFactory()
|
2012-04-18 20:30:57 +03:00
|
|
|
{
|
2013-08-09 17:49:30 +02:00
|
|
|
setDisplayName(tr("Android GCC"));
|
2012-04-18 20:30:57 +03:00
|
|
|
}
|
|
|
|
|
|
2015-07-19 10:59:06 +03:00
|
|
|
QList<ToolChain *> AndroidToolChainFactory::autoDetect(const QList<ToolChain *> &alreadyKnown)
|
2012-04-18 20:30:57 +03:00
|
|
|
{
|
2015-10-15 16:01:40 +02:00
|
|
|
return autodetectToolChainsForNdk(AndroidConfigurations::currentConfig().ndkLocation(), alreadyKnown);
|
2012-04-18 20:30:57 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool AndroidToolChainFactory::canRestore(const QVariantMap &data)
|
|
|
|
|
{
|
2015-07-07 14:20:12 +02:00
|
|
|
return typeIdFromMap(data) == Constants::ANDROID_TOOLCHAIN_ID;
|
2012-04-18 20:30:57 +03:00
|
|
|
}
|
|
|
|
|
|
2012-08-09 01:56:51 +02:00
|
|
|
ToolChain *AndroidToolChainFactory::restore(const QVariantMap &data)
|
2012-04-18 20:30:57 +03:00
|
|
|
{
|
2013-01-25 16:49:22 +01:00
|
|
|
AndroidToolChain *tc = new AndroidToolChain();
|
2012-04-18 20:30:57 +03:00
|
|
|
if (tc->fromMap(data))
|
|
|
|
|
return tc;
|
|
|
|
|
|
|
|
|
|
delete tc;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-03 23:50:37 +02:00
|
|
|
QList<AndroidToolChainFactory::AndroidToolChainInformation> AndroidToolChainFactory::toolchainPathsForNdk(const FileName &ndkPath)
|
2013-02-14 15:51:59 +01:00
|
|
|
{
|
|
|
|
|
QList<AndroidToolChainInformation> result;
|
|
|
|
|
if (ndkPath.isEmpty())
|
|
|
|
|
return result;
|
|
|
|
|
QRegExp versionRegExp(NDKGccVersionRegExp);
|
|
|
|
|
FileName path = ndkPath;
|
|
|
|
|
QDirIterator it(path.appendPath(QLatin1String("toolchains")).toString(),
|
|
|
|
|
QStringList() << QLatin1String("*"), QDir::Dirs);
|
|
|
|
|
while (it.hasNext()) {
|
2015-01-10 23:40:32 +02:00
|
|
|
const QString &fileName = FileName::fromString(it.next()).fileName();
|
2013-02-14 15:51:59 +01:00
|
|
|
int idx = versionRegExp.indexIn(fileName);
|
|
|
|
|
if (idx == -1)
|
|
|
|
|
continue;
|
|
|
|
|
AndroidToolChainInformation ati;
|
|
|
|
|
ati.version = fileName.mid(idx + 1);
|
|
|
|
|
QString platform = fileName.left(idx);
|
2014-11-18 18:37:05 +01:00
|
|
|
ati.abi = AndroidConfig::abiForToolChainPrefix(platform);
|
|
|
|
|
if (ati.abi.architecture() == Abi::UnknownArchitecture) // e.g. mipsel which is not yet supported
|
2013-02-14 15:51:59 +01:00
|
|
|
continue;
|
|
|
|
|
// AndroidToolChain *tc = new AndroidToolChain(arch, version, true);
|
2014-11-18 18:37:05 +01:00
|
|
|
ati.compilerCommand = AndroidConfigurations::currentConfig().gccPath(ati.abi, ati.version);
|
2013-02-14 15:51:59 +01:00
|
|
|
// tc->setCompilerCommand(compilerPath);
|
|
|
|
|
result.append(ati);
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2013-08-28 13:34:24 +02:00
|
|
|
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;
|
2016-02-03 13:49:53 +01:00
|
|
|
int v = version.midRef(start, index - start).toInt(&ok);
|
2013-08-28 13:34:24 +02:00
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-15 16:01:40 +02:00
|
|
|
static AndroidToolChain *findToolChain(Utils::FileName &compilerPath, const QList<ToolChain *> &alreadyKnown)
|
|
|
|
|
{
|
|
|
|
|
return static_cast<AndroidToolChain *>(
|
|
|
|
|
Utils::findOrDefault(alreadyKnown, [compilerPath](ToolChain *tc) {
|
2015-10-30 13:30:08 +01:00
|
|
|
return tc->typeId() == Constants::ANDROID_TOOLCHAIN_ID
|
|
|
|
|
&& tc->compilerCommand() == compilerPath;
|
2015-10-15 16:01:40 +02:00
|
|
|
}));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QList<ToolChain *>
|
|
|
|
|
AndroidToolChainFactory::autodetectToolChainsForNdk(const FileName &ndkPath,
|
|
|
|
|
const QList<ToolChain *> &alreadyKnown)
|
2012-04-18 20:30:57 +03:00
|
|
|
{
|
2012-08-09 01:56:51 +02:00
|
|
|
QList<ToolChain *> result;
|
2013-01-25 16:49:22 +01:00
|
|
|
if (ndkPath.isEmpty())
|
|
|
|
|
return result;
|
2015-10-15 16:01:40 +02:00
|
|
|
|
2013-01-25 16:49:22 +01:00
|
|
|
QRegExp versionRegExp(NDKGccVersionRegExp);
|
|
|
|
|
FileName path = ndkPath;
|
|
|
|
|
QDirIterator it(path.appendPath(QLatin1String("toolchains")).toString(),
|
|
|
|
|
QStringList() << QLatin1String("*"), QDir::Dirs);
|
2014-11-18 18:37:05 +01:00
|
|
|
QHash<Abi, AndroidToolChain *> newestToolChainForArch;
|
2013-08-28 13:34:24 +02:00
|
|
|
|
2013-01-25 16:49:22 +01:00
|
|
|
while (it.hasNext()) {
|
2015-01-10 23:40:32 +02:00
|
|
|
const QString &fileName = FileName::fromString(it.next()).fileName();
|
2013-01-25 16:49:22 +01:00
|
|
|
int idx = versionRegExp.indexIn(fileName);
|
|
|
|
|
if (idx == -1)
|
2012-04-18 20:30:57 +03:00
|
|
|
continue;
|
2013-01-25 16:49:22 +01:00
|
|
|
QString version = fileName.mid(idx + 1);
|
|
|
|
|
QString platform = fileName.left(idx);
|
2014-11-18 18:37:05 +01:00
|
|
|
Abi abi = AndroidConfig::abiForToolChainPrefix(platform);
|
|
|
|
|
if (abi.architecture() == Abi::UnknownArchitecture) // e.g. mipsel which is not yet supported
|
2013-01-25 16:49:22 +01:00
|
|
|
continue;
|
2014-11-18 18:37:05 +01:00
|
|
|
FileName compilerPath = AndroidConfigurations::currentConfig().gccPath(abi, version);
|
2015-10-15 16:01:40 +02:00
|
|
|
|
|
|
|
|
AndroidToolChain *tc = findToolChain(compilerPath, alreadyKnown);
|
|
|
|
|
if (!tc) {
|
|
|
|
|
tc = new AndroidToolChain(abi, version, ToolChain::AutoDetection);
|
|
|
|
|
tc->resetToolChain(compilerPath);
|
|
|
|
|
}
|
2013-01-25 16:49:22 +01:00
|
|
|
result.append(tc);
|
2013-08-28 13:34:24 +02:00
|
|
|
|
2015-10-15 16:01:40 +02:00
|
|
|
auto it = newestToolChainForArch.constFind(abi);
|
2013-08-28 13:34:24 +02:00
|
|
|
if (it == newestToolChainForArch.constEnd())
|
2014-11-18 18:37:05 +01:00
|
|
|
newestToolChainForArch.insert(abi, tc);
|
2013-08-28 13:34:24 +02:00
|
|
|
else if (versionCompareLess(it.value(), tc))
|
2014-11-18 18:37:05 +01:00
|
|
|
newestToolChainForArch[abi] = tc;
|
2012-04-18 20:30:57 +03:00
|
|
|
}
|
2013-08-28 13:34:24 +02:00
|
|
|
|
|
|
|
|
foreach (ToolChain *tc, result) {
|
|
|
|
|
AndroidToolChain *atc = static_cast<AndroidToolChain *>(tc);
|
2015-10-15 16:01:40 +02:00
|
|
|
atc->setSecondaryToolChain(newestToolChainForArch.value(atc->targetAbi()) != atc);
|
2013-08-28 13:34:24 +02:00
|
|
|
}
|
|
|
|
|
|
2012-04-18 20:30:57 +03:00
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2014-11-18 18:37:05 +01:00
|
|
|
QList<int> AndroidToolChainFactory::newestToolChainVersionForArch(const Abi &abi)
|
2013-08-28 13:34:24 +02:00
|
|
|
{
|
2014-11-18 18:37:05 +01:00
|
|
|
if (m_newestVersionForAbi.isEmpty()
|
2013-12-16 20:19:07 +01:00
|
|
|
|| m_ndkLocation != AndroidConfigurations::currentConfig().ndkLocation()) {
|
2013-08-28 13:34:24 +02:00
|
|
|
QRegExp versionRegExp(NDKGccVersionRegExp);
|
2013-12-16 20:19:07 +01:00
|
|
|
m_ndkLocation = AndroidConfigurations::currentConfig().ndkLocation();
|
2013-08-28 13:34:24 +02:00
|
|
|
FileName path = m_ndkLocation;
|
|
|
|
|
QDirIterator it(path.appendPath(QLatin1String("toolchains")).toString(),
|
|
|
|
|
QStringList() << QLatin1String("*"), QDir::Dirs);
|
|
|
|
|
while (it.hasNext()) {
|
2015-01-10 23:40:32 +02:00
|
|
|
const QString &fileName = FileName::fromString(it.next()).fileName();
|
2013-08-28 13:34:24 +02:00
|
|
|
int idx = versionRegExp.indexIn(fileName);
|
|
|
|
|
if (idx == -1)
|
|
|
|
|
continue;
|
|
|
|
|
QList<int> version = versionNumberFromString(fileName.mid(idx + 1));
|
|
|
|
|
QString platform = fileName.left(idx);
|
2014-11-18 18:37:05 +01:00
|
|
|
Abi abi = AndroidConfig::abiForToolChainPrefix(platform);
|
|
|
|
|
if (abi.architecture() == Abi::UnknownArchitecture) // e.g. mipsel which is not yet supported
|
2013-08-28 13:34:24 +02:00
|
|
|
continue;
|
2014-11-18 18:37:05 +01:00
|
|
|
QHash<Abi, QList<int> >::const_iterator it
|
|
|
|
|
= m_newestVersionForAbi.constFind(abi);
|
|
|
|
|
if (it == m_newestVersionForAbi.constEnd())
|
|
|
|
|
m_newestVersionForAbi.insert(abi, version);
|
2013-08-28 13:34:24 +02:00
|
|
|
else if (versionCompareLess(it.value(), version))
|
2014-11-18 18:37:05 +01:00
|
|
|
m_newestVersionForAbi[abi] = version;
|
2013-08-28 13:34:24 +02:00
|
|
|
}
|
|
|
|
|
}
|
2014-11-18 18:37:05 +01:00
|
|
|
return m_newestVersionForAbi.value(abi);
|
2013-08-28 13:34:24 +02:00
|
|
|
}
|
|
|
|
|
|
2012-04-18 20:30:57 +03:00
|
|
|
} // namespace Internal
|
|
|
|
|
} // namespace Android
|