forked from qt-creator/qt-creator
Android: Auto detect clang toolchains
Remove GCC auto detection Make Clang toochain default for Android Remove auto detected toolchains from old NDK Task-number: QTCREATORBUG-11846 Change-Id: I618e6f8eda4f24f498260b8de778ef543311acd1 Reviewed-by: BogDan Vatra <bogdan@kdab.com> Reviewed-by: Leena Miettinen <riitta-leena.miettinen@qt.io>
This commit is contained in:
@@ -93,7 +93,6 @@ namespace {
|
|||||||
const QLatin1String OpenJDKLocationKey("OpenJDKLocation");
|
const QLatin1String OpenJDKLocationKey("OpenJDKLocation");
|
||||||
const QLatin1String KeystoreLocationKey("KeystoreLocation");
|
const QLatin1String KeystoreLocationKey("KeystoreLocation");
|
||||||
const QLatin1String AutomaticKitCreationKey("AutomatiKitCreation");
|
const QLatin1String AutomaticKitCreationKey("AutomatiKitCreation");
|
||||||
const QLatin1String MakeExtraSearchDirectory("MakeExtraSearchDirectory");
|
|
||||||
const QLatin1String PartitionSizeKey("PartitionSize");
|
const QLatin1String PartitionSizeKey("PartitionSize");
|
||||||
const QLatin1String ToolchainHostKey("ToolchainHost");
|
const QLatin1String ToolchainHostKey("ToolchainHost");
|
||||||
|
|
||||||
@@ -256,10 +255,6 @@ void AndroidConfig::load(const QSettings &settings)
|
|||||||
m_keystoreLocation = FileName::fromString(settings.value(KeystoreLocationKey).toString());
|
m_keystoreLocation = FileName::fromString(settings.value(KeystoreLocationKey).toString());
|
||||||
m_toolchainHost = settings.value(ToolchainHostKey).toString();
|
m_toolchainHost = settings.value(ToolchainHostKey).toString();
|
||||||
m_automaticKitCreation = settings.value(AutomaticKitCreationKey, true).toBool();
|
m_automaticKitCreation = settings.value(AutomaticKitCreationKey, true).toBool();
|
||||||
QString extraDirectory = settings.value(MakeExtraSearchDirectory).toString();
|
|
||||||
m_makeExtraSearchDirectories.clear();
|
|
||||||
if (!extraDirectory.isEmpty())
|
|
||||||
m_makeExtraSearchDirectories << extraDirectory;
|
|
||||||
|
|
||||||
PersistentSettingsReader reader;
|
PersistentSettingsReader reader;
|
||||||
if (reader.load(FileName::fromString(sdkSettingsFileName()))
|
if (reader.load(FileName::fromString(sdkSettingsFileName()))
|
||||||
@@ -272,10 +267,6 @@ void AndroidConfig::load(const QSettings &settings)
|
|||||||
m_keystoreLocation = FileName::fromString(reader.restoreValue(KeystoreLocationKey, m_keystoreLocation.toString()).toString());
|
m_keystoreLocation = FileName::fromString(reader.restoreValue(KeystoreLocationKey, m_keystoreLocation.toString()).toString());
|
||||||
m_toolchainHost = reader.restoreValue(ToolchainHostKey, m_toolchainHost).toString();
|
m_toolchainHost = reader.restoreValue(ToolchainHostKey, m_toolchainHost).toString();
|
||||||
m_automaticKitCreation = reader.restoreValue(AutomaticKitCreationKey, m_automaticKitCreation).toBool();
|
m_automaticKitCreation = reader.restoreValue(AutomaticKitCreationKey, m_automaticKitCreation).toBool();
|
||||||
QString extraDirectory = reader.restoreValue(MakeExtraSearchDirectory).toString();
|
|
||||||
m_makeExtraSearchDirectories.clear();
|
|
||||||
if (!extraDirectory.isEmpty())
|
|
||||||
m_makeExtraSearchDirectories << extraDirectory;
|
|
||||||
// persistent settings
|
// persistent settings
|
||||||
}
|
}
|
||||||
m_NdkInformationUpToDate = false;
|
m_NdkInformationUpToDate = false;
|
||||||
@@ -296,9 +287,6 @@ void AndroidConfig::save(QSettings &settings) const
|
|||||||
settings.setValue(PartitionSizeKey, m_partitionSize);
|
settings.setValue(PartitionSizeKey, m_partitionSize);
|
||||||
settings.setValue(AutomaticKitCreationKey, m_automaticKitCreation);
|
settings.setValue(AutomaticKitCreationKey, m_automaticKitCreation);
|
||||||
settings.setValue(ToolchainHostKey, m_toolchainHost);
|
settings.setValue(ToolchainHostKey, m_toolchainHost);
|
||||||
settings.setValue(MakeExtraSearchDirectory,
|
|
||||||
m_makeExtraSearchDirectories.isEmpty() ? QString()
|
|
||||||
: m_makeExtraSearchDirectories.at(0));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AndroidConfig::updateNdkInformation() const
|
void AndroidConfig::updateNdkInformation() const
|
||||||
@@ -382,16 +370,6 @@ FileName AndroidConfig::emulatorToolPath() const
|
|||||||
return path.appendPath(relativePath + QTC_HOST_EXE_SUFFIX);
|
return path.appendPath(relativePath + QTC_HOST_EXE_SUFFIX);
|
||||||
}
|
}
|
||||||
|
|
||||||
FileName AndroidConfig::toolPath(const Abi &abi, const QString &ndkToolChainVersion) const
|
|
||||||
{
|
|
||||||
FileName path = m_ndkLocation;
|
|
||||||
return path.appendPath(QString::fromLatin1("toolchains/%1-%2/prebuilt/%3/bin/%4")
|
|
||||||
.arg(toolchainPrefix(abi))
|
|
||||||
.arg(ndkToolChainVersion)
|
|
||||||
.arg(toolchainHost())
|
|
||||||
.arg(toolsPrefix(abi)));
|
|
||||||
}
|
|
||||||
|
|
||||||
FileName AndroidConfig::sdkManagerToolPath() const
|
FileName AndroidConfig::sdkManagerToolPath() const
|
||||||
{
|
{
|
||||||
FileName sdkPath = m_sdkLocation;
|
FileName sdkPath = m_sdkLocation;
|
||||||
@@ -423,28 +401,47 @@ FileName AndroidConfig::aaptToolPath() const
|
|||||||
return aaptToolPath;
|
return aaptToolPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
FileName AndroidConfig::gccPath(const Abi &abi, Core::Id lang,
|
FileName AndroidConfig::clangPath() const
|
||||||
const QString &ndkToolChainVersion) const
|
|
||||||
{
|
{
|
||||||
const QString tool
|
FileName clangPath = m_ndkLocation;
|
||||||
= HostOsInfo::withExecutableSuffix(QString::fromLatin1(lang == Core::Id(ProjectExplorer::Constants::C_LANGUAGE_ID) ? "-gcc" : "-g++"));
|
clangPath.appendPath("toolchains/llvm/prebuilt/");
|
||||||
return toolPath(abi, ndkToolChainVersion).appendString(tool);
|
|
||||||
|
// detect toolchain host
|
||||||
|
QStringList hostPatterns;
|
||||||
|
switch (HostOsInfo::hostOs()) {
|
||||||
|
case OsTypeLinux:
|
||||||
|
hostPatterns << QLatin1String("linux*");
|
||||||
|
break;
|
||||||
|
case OsTypeWindows:
|
||||||
|
hostPatterns << QLatin1String("windows*");
|
||||||
|
break;
|
||||||
|
case OsTypeMac:
|
||||||
|
hostPatterns << QLatin1String("darwin*");
|
||||||
|
break;
|
||||||
|
default: /* unknown host */ return FileName();
|
||||||
|
}
|
||||||
|
|
||||||
|
QDirIterator iter(clangPath.toString(), hostPatterns, QDir::Dirs);
|
||||||
|
if (iter.hasNext()) {
|
||||||
|
iter.next();
|
||||||
|
return clangPath.appendPath(iter.fileName()).appendPath("bin/clang");
|
||||||
|
}
|
||||||
|
|
||||||
|
return clangPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
FileName AndroidConfig::gdbPath(const Abi &abi, const QString &ndkToolChainVersion) const
|
FileName AndroidConfig::gdbPath() const
|
||||||
{
|
{
|
||||||
const auto gdbPath = QString::fromLatin1("%1/prebuilt/%2/bin/gdb" QTC_HOST_EXE_SUFFIX).arg(m_ndkLocation.toString()).arg(toolchainHost());
|
FileName path = m_ndkLocation;
|
||||||
if (QFile::exists(gdbPath))
|
path.appendPath(QString("prebuilt/%1/bin/gdb%2").arg(toolchainHost(), QTC_HOST_EXE_SUFFIX));
|
||||||
return FileName::fromString(gdbPath);
|
return path;
|
||||||
|
|
||||||
return toolPath(abi, ndkToolChainVersion).appendString(QLatin1String("-gdb" QTC_HOST_EXE_SUFFIX));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FileName AndroidConfig::makePath() const
|
FileName AndroidConfig::makePath() const
|
||||||
{
|
{
|
||||||
const QString makePath = QString::fromLatin1("%1/prebuilt/%2/bin/make" QTC_HOST_EXE_SUFFIX)
|
FileName path = m_ndkLocation;
|
||||||
.arg(m_ndkLocation.toString()).arg(toolchainHost());
|
path.appendPath(QString("prebuilt/%1/bin/make%2").arg(toolchainHost(), QTC_HOST_EXE_SUFFIX));
|
||||||
return FileName::fromString(makePath);
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
FileName AndroidConfig::openJDKBinPath() const
|
FileName AndroidConfig::openJDKBinPath() const
|
||||||
@@ -868,11 +865,6 @@ QString AndroidConfig::toolchainHost() const
|
|||||||
return m_toolchainHost;
|
return m_toolchainHost;
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList AndroidConfig::makeExtraSearchDirectories() const
|
|
||||||
{
|
|
||||||
return m_makeExtraSearchDirectories;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned AndroidConfig::partitionSize() const
|
unsigned AndroidConfig::partitionSize() const
|
||||||
{
|
{
|
||||||
return m_partitionSize;
|
return m_partitionSize;
|
||||||
@@ -965,8 +957,7 @@ static bool matchToolChain(const ToolChain *atc, const ToolChain *btc)
|
|||||||
|
|
||||||
auto aatc = static_cast<const AndroidToolChain *>(atc);
|
auto aatc = static_cast<const AndroidToolChain *>(atc);
|
||||||
auto abtc = static_cast<const AndroidToolChain *>(btc);
|
auto abtc = static_cast<const AndroidToolChain *>(btc);
|
||||||
return aatc->ndkToolChainVersion() == abtc->ndkToolChainVersion()
|
return aatc->targetAbi() == abtc->targetAbi();
|
||||||
&& aatc->targetAbi() == abtc->targetAbi();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool matchKits(const Kit *a, const Kit *b)
|
static bool matchKits(const Kit *a, const Kit *b)
|
||||||
@@ -986,8 +977,7 @@ void AndroidConfigurations::registerNewToolChains()
|
|||||||
= ToolChainManager::toolChains(Utils::equal(&ToolChain::typeId,
|
= ToolChainManager::toolChains(Utils::equal(&ToolChain::typeId,
|
||||||
Core::Id(Constants::ANDROID_TOOLCHAIN_ID)));
|
Core::Id(Constants::ANDROID_TOOLCHAIN_ID)));
|
||||||
const QList<ToolChain *> newToolchains
|
const QList<ToolChain *> newToolchains
|
||||||
= AndroidToolChainFactory::autodetectToolChainsForNdk(AndroidConfigurations::currentConfig().ndkLocation(),
|
= AndroidToolChainFactory::autodetectToolChainsForNdk(existingAndroidToolChains);
|
||||||
existingAndroidToolChains);
|
|
||||||
foreach (ToolChain *tc, newToolchains)
|
foreach (ToolChain *tc, newToolchains)
|
||||||
ToolChainManager::registerToolChain(tc);
|
ToolChainManager::registerToolChain(tc);
|
||||||
}
|
}
|
||||||
@@ -1014,22 +1004,6 @@ void AndroidConfigurations::updateAutomaticKitList()
|
|||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Update code for 3.0 beta, which shipped with a bug for the debugger settings
|
|
||||||
for (Kit *k : existingKits) {
|
|
||||||
ToolChain *tc = ToolChainKitInformation::toolChain(k, ProjectExplorer::Constants::CXX_LANGUAGE_ID);
|
|
||||||
if (tc && Debugger::DebuggerKitInformation::runnable(k).executable != tc->suggestedDebugger().toString()) {
|
|
||||||
Debugger::DebuggerItem debugger;
|
|
||||||
debugger.setCommand(tc->suggestedDebugger());
|
|
||||||
debugger.setEngineType(Debugger::GdbEngineType);
|
|
||||||
debugger.setUnexpandedDisplayName(tr("Android Debugger for %1").arg(tc->displayName()));
|
|
||||||
debugger.setAutoDetected(true);
|
|
||||||
debugger.setAbi(tc->targetAbi());
|
|
||||||
debugger.reinitializeFromFile();
|
|
||||||
QVariant id = Debugger::DebuggerItemManager::registerDebugger(debugger);
|
|
||||||
Debugger::DebuggerKitInformation::setDebugger(k, id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QHash<Abi, QList<const QtSupport::BaseQtVersion *> > qtVersionsForArch;
|
QHash<Abi, QList<const QtSupport::BaseQtVersion *> > qtVersionsForArch;
|
||||||
const QList<QtSupport::BaseQtVersion *> qtVersions
|
const QList<QtSupport::BaseQtVersion *> qtVersions
|
||||||
= QtSupport::QtVersionManager::versions([](const QtSupport::BaseQtVersion *v) {
|
= QtSupport::QtVersionManager::versions([](const QtSupport::BaseQtVersion *v) {
|
||||||
@@ -1052,18 +1026,16 @@ void AndroidConfigurations::updateAutomaticKitList()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// register new kits
|
// register new kits
|
||||||
const QList<ToolChain *> tmp = ToolChainManager::toolChains([](const ToolChain *tc) {
|
const QList<ToolChain *> toolchains = ToolChainManager::toolChains([](const ToolChain *tc) {
|
||||||
return tc->isAutoDetected()
|
return tc->isAutoDetected()
|
||||||
&& tc->isValid()
|
&& tc->isValid()
|
||||||
&& tc->typeId() == Constants::ANDROID_TOOLCHAIN_ID
|
&& tc->typeId() == Constants::ANDROID_TOOLCHAIN_ID;
|
||||||
&& !static_cast<const AndroidToolChain *>(tc)->isSecondaryToolChain();
|
|
||||||
});
|
});
|
||||||
const auto toolchains = Utils::static_container_cast<AndroidToolChain *>(tmp);
|
for (ToolChain *tc : toolchains) {
|
||||||
for (AndroidToolChain *tc : toolchains) {
|
if (tc->language() != Core::Id(ProjectExplorer::Constants::CXX_LANGUAGE_ID))
|
||||||
if (tc->isSecondaryToolChain() || tc->language() != Core::Id(ProjectExplorer::Constants::CXX_LANGUAGE_ID))
|
|
||||||
continue;
|
continue;
|
||||||
const QList<AndroidToolChain *> allLanguages = Utils::filtered(toolchains,
|
const QList<ToolChain *> allLanguages = Utils::filtered(toolchains,
|
||||||
[tc](AndroidToolChain *otherTc) {
|
[tc](ToolChain *otherTc) {
|
||||||
return tc->targetAbi() == otherTc->targetAbi();
|
return tc->targetAbi() == otherTc->targetAbi();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1071,7 +1043,7 @@ void AndroidConfigurations::updateAutomaticKitList()
|
|||||||
k->setAutoDetected(true);
|
k->setAutoDetected(true);
|
||||||
k->setAutoDetectionSource("AndroidConfiguration");
|
k->setAutoDetectionSource("AndroidConfiguration");
|
||||||
DeviceTypeKitInformation::setDeviceTypeId(k, Core::Id(Constants::ANDROID_DEVICE_TYPE));
|
DeviceTypeKitInformation::setDeviceTypeId(k, Core::Id(Constants::ANDROID_DEVICE_TYPE));
|
||||||
for (AndroidToolChain *tc : allLanguages)
|
for (ToolChain *tc : allLanguages)
|
||||||
ToolChainKitInformation::setToolChain(k, tc);
|
ToolChainKitInformation::setToolChain(k, tc);
|
||||||
QtSupport::QtKitInformation::setQtVersion(k, qt);
|
QtSupport::QtKitInformation::setQtVersion(k, qt);
|
||||||
DeviceKitInformation::setDevice(k, device);
|
DeviceKitInformation::setDevice(k, device);
|
||||||
@@ -1104,9 +1076,9 @@ void AndroidConfigurations::updateAutomaticKitList()
|
|||||||
|
|
||||||
AndroidGdbServerKitInformation::setGdbSever(toSetup, currentConfig().gdbServer(tc->targetAbi()));
|
AndroidGdbServerKitInformation::setGdbSever(toSetup, currentConfig().gdbServer(tc->targetAbi()));
|
||||||
toSetup->makeSticky();
|
toSetup->makeSticky();
|
||||||
toSetup->setUnexpandedDisplayName(tr("Android for %1 (GCC %2, %3)")
|
|
||||||
|
toSetup->setUnexpandedDisplayName(tr("Android for %1 (Clang %2)")
|
||||||
.arg(static_cast<const AndroidQtVersion *>(qt)->targetArch())
|
.arg(static_cast<const AndroidQtVersion *>(qt)->targetArch())
|
||||||
.arg(tc->ndkToolChainVersion())
|
|
||||||
.arg(qt->displayName()));
|
.arg(qt->displayName()));
|
||||||
if (!existingKit)
|
if (!existingKit)
|
||||||
KitManager::registerKit(std::move(newKit));
|
KitManager::registerKit(std::move(newKit));
|
||||||
|
@@ -117,7 +117,6 @@ public:
|
|||||||
void setKeystoreLocation(const Utils::FileName &keystoreLocation);
|
void setKeystoreLocation(const Utils::FileName &keystoreLocation);
|
||||||
|
|
||||||
QString toolchainHost() const;
|
QString toolchainHost() const;
|
||||||
QStringList makeExtraSearchDirectories() const;
|
|
||||||
|
|
||||||
unsigned partitionSize() const;
|
unsigned partitionSize() const;
|
||||||
void setPartitionSize(unsigned partitionSize);
|
void setPartitionSize(unsigned partitionSize);
|
||||||
@@ -134,10 +133,8 @@ public:
|
|||||||
Utils::FileName avdManagerToolPath() const;
|
Utils::FileName avdManagerToolPath() const;
|
||||||
Utils::FileName aaptToolPath() const;
|
Utils::FileName aaptToolPath() const;
|
||||||
|
|
||||||
Utils::FileName gccPath(const ProjectExplorer::Abi &abi, Core::Id lang,
|
Utils::FileName clangPath() const;
|
||||||
const QString &ndkToolChainVersion) const;
|
Utils::FileName gdbPath() const;
|
||||||
|
|
||||||
Utils::FileName gdbPath(const ProjectExplorer::Abi &abi, const QString &ndkToolChainVersion) const;
|
|
||||||
Utils::FileName makePath() const;
|
Utils::FileName makePath() const;
|
||||||
|
|
||||||
Utils::FileName keytoolPath() const;
|
Utils::FileName keytoolPath() const;
|
||||||
@@ -162,7 +159,6 @@ public:
|
|||||||
private:
|
private:
|
||||||
static QString getDeviceProperty(const QString &adbToolPath, const QString &device, const QString &property);
|
static QString getDeviceProperty(const QString &adbToolPath, const QString &device, const QString &property);
|
||||||
|
|
||||||
Utils::FileName toolPath(const ProjectExplorer::Abi &abi, const QString &ndkToolChainVersion) const;
|
|
||||||
Utils::FileName openJDKBinPath() const;
|
Utils::FileName openJDKBinPath() const;
|
||||||
int getSDKVersion(const QString &device) const;
|
int getSDKVersion(const QString &device) const;
|
||||||
static int getSDKVersion(const QString &adbToolPath, const QString &device);
|
static int getSDKVersion(const QString &adbToolPath, const QString &device);
|
||||||
@@ -179,7 +175,6 @@ private:
|
|||||||
Utils::FileName m_ndkLocation;
|
Utils::FileName m_ndkLocation;
|
||||||
Utils::FileName m_openJDKLocation;
|
Utils::FileName m_openJDKLocation;
|
||||||
Utils::FileName m_keystoreLocation;
|
Utils::FileName m_keystoreLocation;
|
||||||
QStringList m_makeExtraSearchDirectories;
|
|
||||||
unsigned m_partitionSize = 1024;
|
unsigned m_partitionSize = 1024;
|
||||||
bool m_automaticKitCreation = true;
|
bool m_automaticKitCreation = true;
|
||||||
|
|
||||||
|
@@ -26,31 +26,19 @@
|
|||||||
#include "androidtoolchain.h"
|
#include "androidtoolchain.h"
|
||||||
#include "androidconstants.h"
|
#include "androidconstants.h"
|
||||||
#include "androidconfigurations.h"
|
#include "androidconfigurations.h"
|
||||||
#include "androidqtversion.h"
|
|
||||||
|
|
||||||
#include <extensionsystem/pluginmanager.h>
|
|
||||||
|
|
||||||
#include <qtsupport/qtkitinformation.h>
|
|
||||||
#include <qtsupport/qtversionmanager.h>
|
|
||||||
|
|
||||||
#include <projectexplorer/target.h>
|
|
||||||
#include <projectexplorer/toolchainmanager.h>
|
#include <projectexplorer/toolchainmanager.h>
|
||||||
#include <projectexplorer/projectexplorer.h>
|
#include <projectexplorer/projectexplorer.h>
|
||||||
|
|
||||||
#include <utils/algorithm.h>
|
|
||||||
#include <utils/environment.h>
|
#include <utils/environment.h>
|
||||||
#include <utils/hostosinfo.h>
|
|
||||||
#include <utils/synchronousprocess.h>
|
|
||||||
|
|
||||||
#include <QDir>
|
#include <QFileInfo>
|
||||||
#include <QDirIterator>
|
#include <QLoggingCategory>
|
||||||
#include <QFormLayout>
|
|
||||||
#include <QLabel>
|
|
||||||
#include <QRegExp>
|
#include <QRegExp>
|
||||||
#include <QVBoxLayout>
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
const QLatin1String NDKGccVersionRegExp("-\\d[\\.\\d]+");
|
Q_LOGGING_CATEGORY(androidTCLog, "qtc.android.toolchainmanagement");
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Android {
|
namespace Android {
|
||||||
@@ -59,108 +47,51 @@ namespace Internal {
|
|||||||
using namespace ProjectExplorer;
|
using namespace ProjectExplorer;
|
||||||
using namespace Utils;
|
using namespace Utils;
|
||||||
|
|
||||||
static const char ANDROID_QT_VERSION_KEY[] = "Qt4ProjectManager.Android.QtVersion";
|
static const QHash<QString, Abi> ClangTargets = {
|
||||||
static const char ANDROID_NDK_TC_VERION[] = "Qt4ProjectManager.Android.NDK_TC_VERION";
|
{"arm-linux-androideabi",
|
||||||
|
Abi(Abi::ArmArchitecture, Abi::LinuxOS, Abi::AndroidLinuxFlavor, Abi::ElfFormat, 32)},
|
||||||
|
{"i686-linux-android",
|
||||||
|
Abi(Abi::X86Architecture, Abi::LinuxOS, Abi::AndroidLinuxFlavor, Abi::ElfFormat, 32)},
|
||||||
|
{"x86_64-linux-android",
|
||||||
|
Abi(Abi::X86Architecture, Abi::LinuxOS, Abi::AndroidLinuxFlavor, Abi::ElfFormat, 64)},
|
||||||
|
{"aarch64-linux-android",
|
||||||
|
Abi(Abi::ArmArchitecture, Abi::LinuxOS, Abi::AndroidLinuxFlavor, Abi::ElfFormat, 64)}};
|
||||||
|
|
||||||
QHash<Abi, QList<int> > AndroidToolChainFactory::m_newestVersionForAbi;
|
static const QList<Core::Id> LanguageIds = {ProjectExplorer::Constants::CXX_LANGUAGE_ID,
|
||||||
FileName AndroidToolChainFactory::m_ndkLocation;
|
ProjectExplorer::Constants::C_LANGUAGE_ID};
|
||||||
|
|
||||||
AndroidToolChain::AndroidToolChain(const Abi &abi, const QString &ndkToolChainVersion, Core::Id l, Detection d)
|
static ToolChain *findToolChain(Utils::FileName &compilerPath, Core::Id lang, const QString &target,
|
||||||
: GccToolChain(Constants::ANDROID_TOOLCHAIN_ID, d),
|
CToolChainList &alreadyKnown)
|
||||||
m_ndkToolChainVersion(ndkToolChainVersion), m_secondaryToolChain(false)
|
|
||||||
{
|
{
|
||||||
setLanguage(l);
|
ToolChain * tc = Utils::findOrDefault(alreadyKnown, [target, compilerPath, lang](ToolChain *tc) {
|
||||||
setTargetAbi(abi);
|
return tc->typeId() == Constants::ANDROID_TOOLCHAIN_ID
|
||||||
setDisplayName(QString::fromLatin1("Android GCC (%1, %2-%3)")
|
&& tc->language() == lang
|
||||||
.arg(ToolChainManager::displayNameOfLanguageId(l),
|
&& tc->targetAbi() == ClangTargets[target]
|
||||||
AndroidConfig::displayName(targetAbi()),
|
&& tc->compilerCommand() == compilerPath;
|
||||||
ndkToolChainVersion));
|
});
|
||||||
|
return tc;
|
||||||
}
|
}
|
||||||
|
|
||||||
// for fromMap
|
|
||||||
AndroidToolChain::AndroidToolChain()
|
|
||||||
: GccToolChain(Constants::ANDROID_TOOLCHAIN_ID, ToolChain::ManualDetection),
|
|
||||||
m_secondaryToolChain(false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
AndroidToolChain::AndroidToolChain(const AndroidToolChain &tc) = default;
|
|
||||||
|
|
||||||
AndroidToolChain::~AndroidToolChain() = default;
|
AndroidToolChain::~AndroidToolChain() = default;
|
||||||
|
|
||||||
static QString getArch(const QString &triple)
|
|
||||||
{
|
|
||||||
if (triple.indexOf("x86_64") == 0)
|
|
||||||
return QString::fromUtf8("x86_64");
|
|
||||||
if (triple.indexOf("i686") == 0)
|
|
||||||
return QString::fromUtf8("x86");
|
|
||||||
if (triple.indexOf("mips64") == 0)
|
|
||||||
return QString::fromUtf8("mips64");
|
|
||||||
if (triple.indexOf("mips") == 0)
|
|
||||||
return QString::fromUtf8("mips");
|
|
||||||
if (triple.indexOf("aarch64") == 0)
|
|
||||||
return QString::fromUtf8("arm64-v8a");
|
|
||||||
return QString::fromUtf8("armeabi-v7a");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Paths added here are those that were used by qmake. They were taken from
|
|
||||||
// *qtsource*/qtbase/mkspecs/common/android-base-head.conf
|
|
||||||
// Adding them here allows us to use them for all build systems.
|
|
||||||
static void addBuiltInHeaderPaths(ProjectExplorer::HeaderPaths &paths,
|
|
||||||
const QString &triple, const QString &version)
|
|
||||||
{
|
|
||||||
const Utils::FileName ndkPath = AndroidConfigurations::currentConfig().ndkLocation();
|
|
||||||
|
|
||||||
// Get short version (for example 4.9)
|
|
||||||
auto versionNumber = QVersionNumber::fromString(version);
|
|
||||||
const QString clangVersion = QString("%1.%2")
|
|
||||||
.arg(versionNumber.majorVersion()).arg(versionNumber.minorVersion());
|
|
||||||
Utils::FileName stdcppPath = ndkPath;
|
|
||||||
stdcppPath.appendPath("sources/cxx-stl/gnu-libstdc++/" + clangVersion);
|
|
||||||
Utils::FileName includePath = stdcppPath;
|
|
||||||
Utils::FileName cppLibsPath = stdcppPath;
|
|
||||||
cppLibsPath.appendPath("libs/" + getArch(triple) + "/include/");
|
|
||||||
paths.prepend({cppLibsPath.toString(), ProjectExplorer::HeaderPathType::BuiltIn});
|
|
||||||
includePath.appendPath("include/");
|
|
||||||
paths.prepend({includePath.toString(), ProjectExplorer::HeaderPathType::BuiltIn});
|
|
||||||
|
|
||||||
paths.prepend({ndkPath.toString() + "/sysroot/usr/include/" + triple,
|
|
||||||
ProjectExplorer::HeaderPathType::BuiltIn});
|
|
||||||
paths.prepend({ndkPath.toString() + "/sysroot/usr/include",
|
|
||||||
ProjectExplorer::HeaderPathType::BuiltIn});
|
|
||||||
}
|
|
||||||
|
|
||||||
AndroidToolChain::BuiltInHeaderPathsRunner AndroidToolChain::createBuiltInHeaderPathsRunner() const
|
|
||||||
{
|
|
||||||
const QString triple = originalTargetTriple();
|
|
||||||
const QString version = this->version();
|
|
||||||
initExtraHeaderPathsFunction([triple, version] (HeaderPaths &paths) {
|
|
||||||
addBuiltInHeaderPaths(paths, triple, version);
|
|
||||||
});
|
|
||||||
return GccToolChain::createBuiltInHeaderPathsRunner();
|
|
||||||
}
|
|
||||||
|
|
||||||
QString AndroidToolChain::typeDisplayName() const
|
QString AndroidToolChain::typeDisplayName() const
|
||||||
{
|
{
|
||||||
return AndroidToolChainFactory::tr("Android GCC");
|
return AndroidToolChainFactory::tr("Android Clang");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AndroidToolChain::isValid() const
|
bool AndroidToolChain::isValid() const
|
||||||
{
|
{
|
||||||
return GccToolChain::isValid() && targetAbi().isValid() && !m_ndkToolChainVersion.isEmpty()
|
return ClangToolChain::isValid()
|
||||||
|
&& typeId() == Constants::ANDROID_TOOLCHAIN_ID
|
||||||
|
&& targetAbi().isValid()
|
||||||
&& compilerCommand().isChildOf(AndroidConfigurations::currentConfig().ndkLocation())
|
&& compilerCommand().isChildOf(AndroidConfigurations::currentConfig().ndkLocation())
|
||||||
&& !originalTargetTriple().isEmpty();
|
&& !originalTargetTriple().isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AndroidToolChain::addToEnvironment(Environment &env) const
|
void AndroidToolChain::addToEnvironment(Environment &env) const
|
||||||
{
|
{
|
||||||
// TODO this vars should be configurable in projects -> build tab
|
env.set(QLatin1String("ANDROID_NDK_HOST"),
|
||||||
// TODO invalidate all .pro files !!!
|
AndroidConfigurations::currentConfig().toolchainHost());
|
||||||
|
|
||||||
env.set(QLatin1String("ANDROID_NDK_HOST"), AndroidConfigurations::currentConfig().toolchainHost());
|
|
||||||
env.set(QLatin1String("ANDROID_NDK_TOOLCHAIN_PREFIX"), AndroidConfig::toolchainPrefix(targetAbi()));
|
|
||||||
env.set(QLatin1String("ANDROID_NDK_TOOLS_PREFIX"), AndroidConfig::toolsPrefix(targetAbi()));
|
|
||||||
env.set(QLatin1String("ANDROID_NDK_TOOLCHAIN_VERSION"), m_ndkToolChainVersion);
|
|
||||||
const Utils::FileName javaHome = AndroidConfigurations::currentConfig().openJDKLocation();
|
const Utils::FileName javaHome = AndroidConfigurations::currentConfig().openJDKLocation();
|
||||||
if (!javaHome.isEmpty() && javaHome.toFileInfo().exists()) {
|
if (!javaHome.isEmpty() && javaHome.toFileInfo().exists()) {
|
||||||
env.set(QLatin1String("JAVA_HOME"), javaHome.toString());
|
env.set(QLatin1String("JAVA_HOME"), javaHome.toString());
|
||||||
@@ -169,26 +100,16 @@ void AndroidToolChain::addToEnvironment(Environment &env) const
|
|||||||
if (!Utils::contains(env.path(), [&javaBin](const Utils::FileName &p) { return p == javaBin; }))
|
if (!Utils::contains(env.path(), [&javaBin](const Utils::FileName &p) { return p == javaBin; }))
|
||||||
env.prependOrSetPath(javaBin.toUserOutput());
|
env.prependOrSetPath(javaBin.toUserOutput());
|
||||||
}
|
}
|
||||||
env.set(QLatin1String("ANDROID_HOME"), AndroidConfigurations::currentConfig().sdkLocation().toString());
|
env.set(QLatin1String("ANDROID_HOME"),
|
||||||
env.set(QLatin1String("ANDROID_SDK_ROOT"), AndroidConfigurations::currentConfig().sdkLocation().toString());
|
AndroidConfigurations::currentConfig().sdkLocation().toString());
|
||||||
}
|
env.set(QLatin1String("ANDROID_SDK_ROOT"),
|
||||||
|
AndroidConfigurations::currentConfig().sdkLocation().toString());
|
||||||
bool AndroidToolChain::operator ==(const ToolChain &tc) const
|
|
||||||
{
|
|
||||||
if (!GccToolChain::operator ==(tc))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return m_ndkToolChainVersion == static_cast<const AndroidToolChain &>(tc).m_ndkToolChainVersion;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<ToolChainConfigWidget> AndroidToolChain::createConfigurationWidget()
|
|
||||||
{
|
|
||||||
return std::make_unique<AndroidToolChainConfigWidget>(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FileName AndroidToolChain::suggestedDebugger() const
|
FileName AndroidToolChain::suggestedDebugger() const
|
||||||
{
|
{
|
||||||
return AndroidConfigurations::currentConfig().gdbPath(targetAbi(), m_ndkToolChainVersion);
|
// TODO: Make use of LLDB if available.
|
||||||
|
return AndroidConfigurations::currentConfig().gdbPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
FileName AndroidToolChain::suggestedGdbServer() const
|
FileName AndroidToolChain::suggestedGdbServer() const
|
||||||
@@ -196,45 +117,10 @@ FileName AndroidToolChain::suggestedGdbServer() const
|
|||||||
return AndroidConfigurations::currentConfig().gdbServer(targetAbi());
|
return AndroidConfigurations::currentConfig().gdbServer(targetAbi());
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariantMap AndroidToolChain::toMap() const
|
|
||||||
{
|
|
||||||
QVariantMap result = GccToolChain::toMap();
|
|
||||||
result.insert(QLatin1String(ANDROID_NDK_TC_VERION), m_ndkToolChainVersion);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AndroidToolChain::fromMap(const QVariantMap &data)
|
bool AndroidToolChain::fromMap(const QVariantMap &data)
|
||||||
{
|
{
|
||||||
if (!GccToolChain::fromMap(data))
|
if (!ClangToolChain::fromMap(data))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (data.contains(QLatin1String(ANDROID_QT_VERSION_KEY))) {
|
|
||||||
QString command = compilerCommand().toString();
|
|
||||||
QString ndkPath = AndroidConfigurations::currentConfig().ndkLocation().toString();
|
|
||||||
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);
|
|
||||||
setTargetAbi(AndroidConfig::abiForToolChainPrefix(platform));
|
|
||||||
} else {
|
|
||||||
m_ndkToolChainVersion = data.value(QLatin1String(ANDROID_NDK_TC_VERION)).toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
Abi abi = targetAbi();
|
|
||||||
m_secondaryToolChain = AndroidToolChainFactory::versionCompareLess(AndroidToolChainFactory::versionNumberFromString(m_ndkToolChainVersion),
|
|
||||||
AndroidToolChainFactory::newestToolChainVersionForArch(abi));
|
|
||||||
return isValid();
|
return isValid();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -246,59 +132,16 @@ FileNameList AndroidToolChain::suggestedMkspecList() const
|
|||||||
|
|
||||||
QString AndroidToolChain::makeCommand(const Environment &env) const
|
QString AndroidToolChain::makeCommand(const Environment &env) const
|
||||||
{
|
{
|
||||||
|
Q_UNUSED(env);
|
||||||
FileName makePath = AndroidConfigurations::currentConfig().makePath();
|
FileName makePath = AndroidConfigurations::currentConfig().makePath();
|
||||||
if (makePath.exists())
|
return makePath.exists() ? makePath.toString() : "make";
|
||||||
return makePath.toString();
|
|
||||||
const Utils::FileNameList extraDirectories
|
|
||||||
= Utils::transform(AndroidConfigurations::currentConfig().makeExtraSearchDirectories(),
|
|
||||||
[](const QString &s) { return Utils::FileName::fromString(s); });
|
|
||||||
if (HostOsInfo::isWindowsHost()) {
|
|
||||||
makePath = env.searchInPath("ma-make.exe", extraDirectories);
|
|
||||||
if (!makePath.isEmpty())
|
|
||||||
return makePath.toString();
|
|
||||||
makePath = env.searchInPath("mingw32-make", extraDirectories);
|
|
||||||
return makePath.isEmpty() ? QLatin1String("mingw32-make") : makePath.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
makePath = env.searchInPath("make", extraDirectories);
|
|
||||||
return makePath.isEmpty() ? "make" : makePath.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
QString AndroidToolChain::ndkToolChainVersion() const
|
|
||||||
{
|
|
||||||
return m_ndkToolChainVersion;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AndroidToolChain::isSecondaryToolChain() const
|
|
||||||
{
|
|
||||||
return m_secondaryToolChain;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AndroidToolChain::setSecondaryToolChain(bool b)
|
|
||||||
{
|
|
||||||
if (m_secondaryToolChain == b)
|
|
||||||
return;
|
|
||||||
m_secondaryToolChain = b;
|
|
||||||
toolChainUpdated();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GccToolChain::DetectedAbisResult AndroidToolChain::detectSupportedAbis() const
|
GccToolChain::DetectedAbisResult AndroidToolChain::detectSupportedAbis() const
|
||||||
{
|
{
|
||||||
GccToolChain::DetectedAbisResult supportedAbis = GccToolChain::detectSupportedAbis();
|
return GccToolChain::DetectedAbisResult({targetAbi()}, originalTargetTriple());
|
||||||
supportedAbis.supportedAbis = {targetAbi()};
|
|
||||||
return supportedAbis;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
|
||||||
// ToolChainConfigWidget
|
|
||||||
// --------------------------------------------------------------------------
|
|
||||||
|
|
||||||
AndroidToolChainConfigWidget::AndroidToolChainConfigWidget(AndroidToolChain *tc) :
|
|
||||||
ToolChainConfigWidget(tc)
|
|
||||||
{
|
|
||||||
QLabel *label = new QLabel(AndroidConfigurations::currentConfig().ndkLocation().toUserOutput());
|
|
||||||
m_mainLayout->addRow(tr("NDK Root:"), label);
|
|
||||||
}
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
// ToolChainFactory
|
// ToolChainFactory
|
||||||
@@ -306,7 +149,7 @@ AndroidToolChainConfigWidget::AndroidToolChainConfigWidget(AndroidToolChain *tc)
|
|||||||
|
|
||||||
AndroidToolChainFactory::AndroidToolChainFactory()
|
AndroidToolChainFactory::AndroidToolChainFactory()
|
||||||
{
|
{
|
||||||
setDisplayName(tr("Android GCC"));
|
setDisplayName(tr("Android Clang"));
|
||||||
}
|
}
|
||||||
|
|
||||||
QSet<Core::Id> Android::Internal::AndroidToolChainFactory::supportedLanguages() const
|
QSet<Core::Id> Android::Internal::AndroidToolChainFactory::supportedLanguages() const
|
||||||
@@ -314,9 +157,9 @@ QSet<Core::Id> Android::Internal::AndroidToolChainFactory::supportedLanguages()
|
|||||||
return {ProjectExplorer::Constants::CXX_LANGUAGE_ID};
|
return {ProjectExplorer::Constants::CXX_LANGUAGE_ID};
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<ToolChain *> AndroidToolChainFactory::autoDetect(const QList<ToolChain *> &alreadyKnown)
|
ToolChainList AndroidToolChainFactory::autoDetect(CToolChainList &alreadyKnown)
|
||||||
{
|
{
|
||||||
return autodetectToolChainsForNdk(AndroidConfigurations::currentConfig().ndkLocation(), alreadyKnown);
|
return autodetectToolChainsForNdk(alreadyKnown);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AndroidToolChainFactory::canRestore(const QVariantMap &data)
|
bool AndroidToolChainFactory::canRestore(const QVariantMap &data)
|
||||||
@@ -334,184 +177,67 @@ ToolChain *AndroidToolChainFactory::restore(const QVariantMap &data)
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<AndroidToolChainFactory::AndroidToolChainInformation> AndroidToolChainFactory::toolchainPathsForNdk(const FileName &ndkPath)
|
ToolChainList AndroidToolChainFactory::autodetectToolChainsForNdk(CToolChainList &alreadyKnown)
|
||||||
{
|
|
||||||
QList<AndroidToolChainInformation> result;
|
|
||||||
if (ndkPath.isEmpty())
|
|
||||||
return result;
|
|
||||||
QRegExp versionRegExp(NDKGccVersionRegExp);
|
|
||||||
FileName path = ndkPath;
|
|
||||||
QDirIterator it(path.appendPath(QLatin1String("toolchains")).toString(),
|
|
||||||
QStringList("*"), QDir::Dirs);
|
|
||||||
while (it.hasNext()) {
|
|
||||||
const QString &fileName = FileName::fromString(it.next()).fileName();
|
|
||||||
int idx = versionRegExp.indexIn(fileName);
|
|
||||||
if (idx == -1)
|
|
||||||
continue;
|
|
||||||
for (const Core::Id lang : {ProjectExplorer::Constants::CXX_LANGUAGE_ID,
|
|
||||||
ProjectExplorer::Constants::C_LANGUAGE_ID}) {
|
|
||||||
AndroidToolChainInformation ati;
|
|
||||||
ati.language = lang;
|
|
||||||
ati.version = fileName.mid(idx + 1);
|
|
||||||
QString platform = fileName.left(idx);
|
|
||||||
ati.abi = AndroidConfig::abiForToolChainPrefix(platform);
|
|
||||||
if (ati.abi.architecture() == Abi::UnknownArchitecture)
|
|
||||||
continue;
|
|
||||||
ati.compilerCommand = AndroidConfigurations::currentConfig().gccPath(ati.abi, lang, ati.version);
|
|
||||||
result.append(ati);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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.midRef(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(QList<AndroidToolChain *> atc,
|
|
||||||
QList<AndroidToolChain *> btc)
|
|
||||||
{
|
|
||||||
if (atc.isEmpty() || btc.isEmpty())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
const QList<int> a = versionNumberFromString(atc.at(0)->ndkToolChainVersion());
|
|
||||||
const QList<int> b = versionNumberFromString(btc.at(0)->ndkToolChainVersion());
|
|
||||||
|
|
||||||
return versionCompareLess(a, b);
|
|
||||||
}
|
|
||||||
|
|
||||||
static AndroidToolChain *findToolChain(Utils::FileName &compilerPath, Core::Id lang,
|
|
||||||
const QList<ToolChain *> &alreadyKnown)
|
|
||||||
{
|
|
||||||
return static_cast<AndroidToolChain *>(
|
|
||||||
Utils::findOrDefault(alreadyKnown, [compilerPath, lang](ToolChain *tc) {
|
|
||||||
return tc->typeId() == Constants::ANDROID_TOOLCHAIN_ID
|
|
||||||
&& tc->language() == lang
|
|
||||||
&& tc->compilerCommand() == compilerPath;
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<ToolChain *>
|
|
||||||
AndroidToolChainFactory::autodetectToolChainsForNdk(const FileName &ndkPath,
|
|
||||||
const QList<ToolChain *> &alreadyKnown)
|
|
||||||
{
|
{
|
||||||
QList<ToolChain *> result;
|
QList<ToolChain *> result;
|
||||||
if (ndkPath.isEmpty())
|
FileName clangPath = AndroidConfigurations::currentConfig().clangPath();
|
||||||
|
if (!clangPath.exists()) {
|
||||||
|
qCDebug(androidTCLog) << "Clang toolchains detection fails. Can not find Clang"<< clangPath;
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
QRegExp versionRegExp(NDKGccVersionRegExp);
|
|
||||||
FileName path = ndkPath;
|
|
||||||
QDirIterator it(path.appendPath(QLatin1String("toolchains")).toString(),
|
|
||||||
QStringList("*"), QDir::Dirs);
|
|
||||||
QHash<Abi, QList<AndroidToolChain *>> newestToolChainForArch;
|
|
||||||
|
|
||||||
while (it.hasNext()) {
|
|
||||||
const QString &fileName = FileName::fromString(it.next()).fileName();
|
|
||||||
int idx = versionRegExp.indexIn(fileName);
|
|
||||||
if (idx == -1)
|
|
||||||
continue;
|
|
||||||
QString version = fileName.mid(idx + 1);
|
|
||||||
QString platform = fileName.left(idx);
|
|
||||||
Abi abi = AndroidConfig::abiForToolChainPrefix(platform);
|
|
||||||
if (abi.architecture() == Abi::UnknownArchitecture)
|
|
||||||
continue;
|
|
||||||
QList<AndroidToolChain *> toolChainBundle;
|
|
||||||
for (Core::Id lang : {ProjectExplorer::Constants::CXX_LANGUAGE_ID, ProjectExplorer::Constants::C_LANGUAGE_ID}) {
|
|
||||||
FileName compilerPath = AndroidConfigurations::currentConfig().gccPath(abi, lang, version);
|
|
||||||
if (!compilerPath.exists())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
AndroidToolChain *tc = findToolChain(compilerPath, lang, alreadyKnown);
|
|
||||||
if (!tc || tc->originalTargetTriple().isEmpty()) {
|
|
||||||
tc = new AndroidToolChain(abi, version, lang,
|
|
||||||
ToolChain::AutoDetection);
|
|
||||||
tc->resetToolChain(compilerPath);
|
|
||||||
QTC_ASSERT(!tc->originalTargetTriple().isEmpty(),
|
|
||||||
delete tc; continue);
|
|
||||||
}
|
|
||||||
result.append(tc);
|
|
||||||
toolChainBundle.append(tc);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (toolChainBundle.isEmpty())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
auto it = newestToolChainForArch.constFind(abi);
|
|
||||||
if (it == newestToolChainForArch.constEnd())
|
|
||||||
newestToolChainForArch.insert(abi, toolChainBundle);
|
|
||||||
else if (versionCompareLess(it.value(), toolChainBundle))
|
|
||||||
newestToolChainForArch[abi] = toolChainBundle;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (ToolChain *tc, result) {
|
qCDebug(androidTCLog) << "Detecting toolchains from Android NDK:"
|
||||||
auto atc = static_cast<AndroidToolChain *>(tc);
|
<< AndroidConfigurations::currentConfig().ndkLocation();
|
||||||
atc->setSecondaryToolChain(!newestToolChainForArch.value(atc->targetAbi()).contains(atc));
|
|
||||||
|
for (const Core::Id &lang : LanguageIds) {
|
||||||
|
FileName compilerCommand = clangPath;
|
||||||
|
if (lang == ProjectExplorer::Constants::CXX_LANGUAGE_ID)
|
||||||
|
compilerCommand.appendString("++");
|
||||||
|
|
||||||
|
if (!compilerCommand.exists()) {
|
||||||
|
qCDebug(androidTCLog) << "Skipping Clang toolchain. Can not find compiler"
|
||||||
|
<< compilerCommand;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto targetItr = ClangTargets.constBegin();
|
||||||
|
while (targetItr != ClangTargets.constEnd()) {
|
||||||
|
const Abi &abi = targetItr.value();
|
||||||
|
ToolChain *tc = findToolChain(compilerCommand, lang, targetItr.key(), alreadyKnown);
|
||||||
|
if (tc) {
|
||||||
|
qCDebug(androidTCLog) << "Tool chain already known" << abi.toString() << lang;
|
||||||
|
} else {
|
||||||
|
qCDebug(androidTCLog) << "New Clang toolchain found" << abi.toString() << lang;
|
||||||
|
auto atc = new AndroidToolChain(targetItr.key(), lang);
|
||||||
|
atc->resetToolChain(compilerCommand);
|
||||||
|
tc = atc;
|
||||||
|
}
|
||||||
|
result << tc;
|
||||||
|
++targetItr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<int> AndroidToolChainFactory::newestToolChainVersionForArch(const Abi &abi)
|
// for fromMap
|
||||||
|
AndroidToolChain::AndroidToolChain()
|
||||||
|
: ClangToolChain(Constants::ANDROID_TOOLCHAIN_ID, ToolChain::ManualDetection)
|
||||||
{
|
{
|
||||||
if (m_newestVersionForAbi.isEmpty()
|
}
|
||||||
|| m_ndkLocation != AndroidConfigurations::currentConfig().ndkLocation()) {
|
|
||||||
QRegExp versionRegExp(NDKGccVersionRegExp);
|
|
||||||
m_ndkLocation = AndroidConfigurations::currentConfig().ndkLocation();
|
AndroidToolChain::AndroidToolChain(const QString& target, Core::Id languageId)
|
||||||
FileName path = m_ndkLocation;
|
: ClangToolChain(Constants::ANDROID_TOOLCHAIN_ID, ToolChain::AutoDetection)
|
||||||
QDirIterator it(path.appendPath(QLatin1String("toolchains")).toString(),
|
{
|
||||||
QStringList("*"), QDir::Dirs);
|
setOriginalTargetTriple(target);
|
||||||
while (it.hasNext()) {
|
setLanguage(languageId);
|
||||||
const QString &fileName = FileName::fromString(it.next()).fileName();
|
setTargetAbi(ClangTargets[target]);
|
||||||
int idx = versionRegExp.indexIn(fileName);
|
setPlatformCodeGenFlags({"-target", target});
|
||||||
if (idx == -1)
|
setPlatformLinkerFlags({"-target", target});
|
||||||
continue;
|
setDisplayName(QString::fromLatin1("Android Clang (%1, %2)")
|
||||||
QList<int> version = versionNumberFromString(fileName.mid(idx + 1));
|
.arg(ToolChainManager::displayNameOfLanguageId(languageId),
|
||||||
QString platform = fileName.left(idx);
|
AndroidConfig::displayName(targetAbi())));
|
||||||
Abi abi = AndroidConfig::abiForToolChainPrefix(platform);
|
|
||||||
if (abi.architecture() == Abi::UnknownArchitecture)
|
|
||||||
continue;
|
|
||||||
QHash<Abi, QList<int> >::const_iterator it
|
|
||||||
= m_newestVersionForAbi.constFind(abi);
|
|
||||||
if (it == m_newestVersionForAbi.constEnd())
|
|
||||||
m_newestVersionForAbi.insert(abi, version);
|
|
||||||
else if (versionCompareLess(it.value(), version))
|
|
||||||
m_newestVersionForAbi[abi] = version;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return m_newestVersionForAbi.value(abi);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
@@ -26,71 +26,38 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <projectexplorer/gcctoolchain.h>
|
#include <projectexplorer/gcctoolchain.h>
|
||||||
#include <projectexplorer/toolchainconfigwidget.h>
|
|
||||||
|
|
||||||
namespace Android {
|
namespace Android {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
class AndroidToolChain : public ProjectExplorer::GccToolChain
|
using ToolChainList = QList<ProjectExplorer::ToolChain *>;
|
||||||
|
using CToolChainList = const QList<ProjectExplorer::ToolChain *>;
|
||||||
|
|
||||||
|
class AndroidToolChain : public ProjectExplorer::ClangToolChain
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
~AndroidToolChain() override;
|
~AndroidToolChain() override;
|
||||||
|
|
||||||
QString typeDisplayName() const override;
|
QString typeDisplayName() const override;
|
||||||
|
|
||||||
bool isValid() const override;
|
bool isValid() const override;
|
||||||
|
|
||||||
void addToEnvironment(Utils::Environment &env) const override;
|
void addToEnvironment(Utils::Environment &env) const override;
|
||||||
|
|
||||||
bool operator ==(const ProjectExplorer::ToolChain &) const override;
|
|
||||||
|
|
||||||
std::unique_ptr<ProjectExplorer::ToolChainConfigWidget> createConfigurationWidget() override;
|
|
||||||
Utils::FileName suggestedDebugger() const override;
|
Utils::FileName suggestedDebugger() const override;
|
||||||
Utils::FileName suggestedGdbServer() const;
|
Utils::FileName suggestedGdbServer() const;
|
||||||
|
|
||||||
QVariantMap toMap() const override;
|
|
||||||
bool fromMap(const QVariantMap &data) override;
|
|
||||||
Utils::FileNameList suggestedMkspecList() const override;
|
Utils::FileNameList suggestedMkspecList() const override;
|
||||||
QString makeCommand(const Utils::Environment &environment) const override;
|
QString makeCommand(const Utils::Environment &environment) const override;
|
||||||
|
bool fromMap(const QVariantMap &data) override;
|
||||||
QString ndkToolChainVersion() const;
|
|
||||||
|
|
||||||
bool isSecondaryToolChain() const;
|
|
||||||
void setSecondaryToolChain(bool b);
|
|
||||||
|
|
||||||
BuiltInHeaderPathsRunner createBuiltInHeaderPathsRunner() const override;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
DetectedAbisResult detectSupportedAbis() const override;
|
DetectedAbisResult detectSupportedAbis() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit AndroidToolChain(const ProjectExplorer::Abi &abi, const QString &ndkToolChainVersion,
|
explicit AndroidToolChain();
|
||||||
Core::Id l, Detection d);
|
AndroidToolChain(const QString &target, Core::Id languageId);
|
||||||
AndroidToolChain();
|
|
||||||
AndroidToolChain(const AndroidToolChain &);
|
|
||||||
|
|
||||||
QString m_ndkToolChainVersion;
|
|
||||||
bool m_secondaryToolChain;
|
|
||||||
|
|
||||||
friend class AndroidToolChainFactory;
|
friend class AndroidToolChainFactory;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class AndroidToolChainConfigWidget : public ProjectExplorer::ToolChainConfigWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
AndroidToolChainConfigWidget(AndroidToolChain *);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void applyImpl() override {}
|
|
||||||
void discardImpl() override {}
|
|
||||||
bool isDirtyImpl() const override { return false; }
|
|
||||||
void makeReadOnlyImpl() override {}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class AndroidToolChainFactory : public ProjectExplorer::ToolChainFactory
|
class AndroidToolChainFactory : public ProjectExplorer::ToolChainFactory
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@@ -99,7 +66,7 @@ public:
|
|||||||
AndroidToolChainFactory();
|
AndroidToolChainFactory();
|
||||||
QSet<Core::Id> supportedLanguages() const override;
|
QSet<Core::Id> supportedLanguages() const override;
|
||||||
|
|
||||||
QList<ProjectExplorer::ToolChain *> autoDetect(const QList<ProjectExplorer::ToolChain *> &alreadyKnown) override;
|
ToolChainList autoDetect(CToolChainList &alreadyKnown) override;
|
||||||
bool canRestore(const QVariantMap &data) override;
|
bool canRestore(const QVariantMap &data) override;
|
||||||
ProjectExplorer::ToolChain *restore(const QVariantMap &data) override;
|
ProjectExplorer::ToolChain *restore(const QVariantMap &data) override;
|
||||||
|
|
||||||
@@ -112,19 +79,7 @@ public:
|
|||||||
QString version;
|
QString version;
|
||||||
};
|
};
|
||||||
|
|
||||||
static QList<ProjectExplorer::ToolChain *>
|
static ToolChainList autodetectToolChainsForNdk(CToolChainList &alreadyKnown);
|
||||||
autodetectToolChainsForNdk(const Utils::FileName &ndkPath,
|
|
||||||
const QList<ProjectExplorer::ToolChain *> &alreadyKnown);
|
|
||||||
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(QList<AndroidToolChain *> atc,
|
|
||||||
QList<AndroidToolChain *> btc);
|
|
||||||
static QList<int> newestToolChainVersionForArch(const ProjectExplorer::Abi &abi);
|
|
||||||
private:
|
|
||||||
static QHash<ProjectExplorer::Abi, QList<int> > m_newestVersionForAbi;
|
|
||||||
static Utils::FileName m_ndkLocation;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
@@ -1198,6 +1198,10 @@ ClangToolChain::ClangToolChain(Detection d) :
|
|||||||
GccToolChain(Constants::CLANG_TOOLCHAIN_TYPEID, d)
|
GccToolChain(Constants::CLANG_TOOLCHAIN_TYPEID, d)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
ClangToolChain::ClangToolChain(Core::Id typeId, ToolChain::Detection d) :
|
||||||
|
GccToolChain(typeId, d)
|
||||||
|
{ }
|
||||||
|
|
||||||
QString ClangToolChain::typeDisplayName() const
|
QString ClangToolChain::typeDisplayName() const
|
||||||
{
|
{
|
||||||
return ClangToolChainFactory::tr("Clang");
|
return ClangToolChainFactory::tr("Clang");
|
||||||
|
@@ -207,6 +207,7 @@ class PROJECTEXPLORER_EXPORT ClangToolChain : public GccToolChain
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit ClangToolChain(Detection d);
|
explicit ClangToolChain(Detection d);
|
||||||
|
ClangToolChain(Core::Id typeId, Detection d);
|
||||||
QString typeDisplayName() const override;
|
QString typeDisplayName() const override;
|
||||||
QString makeCommand(const Utils::Environment &environment) const override;
|
QString makeCommand(const Utils::Environment &environment) const override;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user