Android: Automatically use the correct NDK for each Qt version

Based on change 286266, we can find a correct NDK version for Qt for
Andriod version. This change allows Android plugin to get relevant NDK
information and registers appropriate toolchains and kits settings.

[ChangeLog][Android] Automatically use correct NDK version
corresponding to used Qt version.

Task-number: QTCREATORBUG-23583
Change-Id: Ic6b0d7a1ae8962c075b77498de88e018a008ac3e
Reviewed-by: Alessandro Portale <alessandro.portale@qt.io>
This commit is contained in:
Assam Boudjelthia
2020-02-16 20:46:23 +02:00
parent 6b7effa02a
commit 67df868f5c
12 changed files with 254 additions and 186 deletions

View File

@@ -532,10 +532,14 @@ void AndroidBuildApkStep::setBuildTargetSdk(const QString &sdk)
QVariant AndroidBuildApkStep::data(Core::Id id) const
{
if (id == Constants::AndroidNdkPlatform)
return AndroidConfigurations::currentConfig().bestNdkPlatformMatch(AndroidManager::minimumSDK(target())).mid(8);
QtSupport::BaseQtVersion *qtVersion = QtSupport::QtKitAspect::qtVersion(target()->kit());
if (id == Constants::AndroidNdkPlatform) {
return AndroidConfigurations::currentConfig()
.bestNdkPlatformMatch(AndroidManager::minimumSDK(target()), qtVersion).mid(8);
}
if (id == Constants::NdkLocation)
return QVariant::fromValue(AndroidConfigurations::currentConfig().ndkLocation());
return QVariant::fromValue(AndroidConfigurations::currentConfig().ndkLocation(qtVersion));
if (id == Constants::SdkLocation)
return QVariant::fromValue(AndroidConfigurations::currentConfig().sdkLocation());
if (id == Constants::AndroidABIs)

View File

@@ -102,7 +102,6 @@ namespace {
const QLatin1String SDKLocationKey("SDKLocation");
const QLatin1String SdkFullyConfiguredKey("AllEssentialsInstalled");
const QLatin1String SDKManagerToolArgsKey("SDKManagerToolArgs");
const QLatin1String NDKLocationKey("NDKLocation");
const QLatin1String OpenJDKLocationKey("OpenJDKLocation");
const QLatin1String KeystoreLocationKey("KeystoreLocation");
const QLatin1String AutomaticKitCreationKey("AutomatiKitCreation");
@@ -237,10 +236,8 @@ void AndroidConfig::load(const QSettings &settings)
m_partitionSize = settings.value(PartitionSizeKey, 1024).toInt();
m_sdkLocation = FilePath::fromString(settings.value(SDKLocationKey).toString());
m_sdkManagerToolArgs = settings.value(SDKManagerToolArgsKey).toStringList();
m_ndkLocation = FilePath::fromString(settings.value(NDKLocationKey).toString());
m_openJDKLocation = FilePath::fromString(settings.value(OpenJDKLocationKey).toString());
m_keystoreLocation = FilePath::fromString(settings.value(KeystoreLocationKey).toString());
m_toolchainHost = settings.value(ToolchainHostKey).toString();
m_automaticKitCreation = settings.value(AutomaticKitCreationKey, true).toBool();
m_sdkFullyConfigured = settings.value(SdkFullyConfiguredKey, false).toBool();
@@ -250,16 +247,12 @@ void AndroidConfig::load(const QSettings &settings)
// persisten settings
m_sdkLocation = FilePath::fromString(reader.restoreValue(SDKLocationKey, m_sdkLocation.toString()).toString());
m_sdkManagerToolArgs = reader.restoreValue(SDKManagerToolArgsKey, m_sdkManagerToolArgs).toStringList();
m_ndkLocation = FilePath::fromString(reader.restoreValue(NDKLocationKey, m_ndkLocation.toString()).toString());
m_openJDKLocation = FilePath::fromString(reader.restoreValue(OpenJDKLocationKey, m_openJDKLocation.toString()).toString());
m_keystoreLocation = FilePath::fromString(reader.restoreValue(KeystoreLocationKey, m_keystoreLocation.toString()).toString());
m_toolchainHost = reader.restoreValue(ToolchainHostKey, m_toolchainHost).toString();
m_automaticKitCreation = reader.restoreValue(AutomaticKitCreationKey, m_automaticKitCreation).toBool();
m_sdkFullyConfigured = reader.restoreValue(SdkFullyConfiguredKey, m_sdkFullyConfigured).toBool();
// persistent settings
}
parseDependenciesJson();
m_NdkInformationUpToDate = false;
}
void AndroidConfig::save(QSettings &settings) const
@@ -271,51 +264,13 @@ void AndroidConfig::save(QSettings &settings) const
// user settings
settings.setValue(SDKLocationKey, m_sdkLocation.toString());
settings.setValue(SDKManagerToolArgsKey, m_sdkManagerToolArgs);
settings.setValue(NDKLocationKey, m_ndkLocation.toString());
settings.setValue(OpenJDKLocationKey, m_openJDKLocation.toString());
settings.setValue(KeystoreLocationKey, m_keystoreLocation.toString());
settings.setValue(PartitionSizeKey, m_partitionSize);
settings.setValue(AutomaticKitCreationKey, m_automaticKitCreation);
settings.setValue(ToolchainHostKey, m_toolchainHost);
settings.setValue(SdkFullyConfiguredKey, m_sdkFullyConfigured);
}
void AndroidConfig::updateNdkInformation() const
{
if (m_NdkInformationUpToDate)
return;
m_availableNdkPlatforms.clear();
QDirIterator it(m_ndkLocation.pathAppended("platforms").toString(), QStringList("android-*"), QDir::Dirs);
while (it.hasNext()) {
const QString &fileName = it.next();
m_availableNdkPlatforms.push_back(fileName.midRef(fileName.lastIndexOf(QLatin1Char('-')) + 1).toInt());
}
Utils::sort(m_availableNdkPlatforms, std::greater<>());
// 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;
}
QDirIterator jt(m_ndkLocation.pathAppended("prebuilt").toString(), hostPatterns, QDir::Dirs);
if (jt.hasNext()) {
jt.next();
m_toolchainHost = jt.fileName();
}
m_NdkInformationUpToDate = true;
}
void AndroidConfig::parseDependenciesJson()
{
QString sdkConfigFile(Core::ICore::resourcePath() + JsonFilePath);
@@ -382,6 +337,22 @@ void AndroidConfig::parseDependenciesJson()
}
}
QVector<int> AndroidConfig::availableNdkPlatforms(const BaseQtVersion *qtVersion) const
{
QVector<int> availableNdkPlatforms;
QDirIterator it(ndkLocation(qtVersion).pathAppended("platforms").toString(),
QStringList("android-*"),
QDir::Dirs);
while (it.hasNext()) {
const QString &fileName = it.next();
availableNdkPlatforms.push_back(
fileName.midRef(fileName.lastIndexOf(QLatin1Char('-')) + 1).toInt());
}
Utils::sort(availableNdkPlatforms, std::greater<>());
return availableNdkPlatforms;
}
QStringList AndroidConfig::apiLevelNamesFor(const SdkPlatformList &platforms)
{
return Utils::transform(platforms, AndroidConfig::apiLevelNameFor);
@@ -444,9 +415,9 @@ FilePath AndroidConfig::aaptToolPath() const
return aaptToolPath.pathAppended(toolPath);
}
FilePath AndroidConfig::toolchainPath() const
FilePath AndroidConfig::toolchainPath(const BaseQtVersion *qtVersion) const
{
const FilePath toolchainPath = m_ndkLocation.pathAppended("toolchains/llvm/prebuilt/");
const FilePath toolchainPath = ndkLocation(qtVersion).pathAppended("toolchains/llvm/prebuilt/");
// detect toolchain host
QStringList hostPatterns;
@@ -472,29 +443,34 @@ FilePath AndroidConfig::toolchainPath() const
return {};
}
FilePath AndroidConfig::clangPath() const
FilePath AndroidConfig::clangPath(const BaseQtVersion *qtVersion) const
{
const FilePath path = toolchainPath();
const FilePath path = toolchainPath(qtVersion);
if (path.isEmpty())
return {};
return path.pathAppended(HostOsInfo::withExecutableSuffix("bin/clang"));
}
FilePath AndroidConfig::gdbPath(const ProjectExplorer::Abi &abi) const
FilePath AndroidConfig::gdbPath(const ProjectExplorer::Abi &abi, const BaseQtVersion *qtVersion) const
{
const FilePath path = m_ndkLocation.pathAppended(
QString("prebuilt/%1/bin/gdb%2").arg(toolchainHost(), QTC_HOST_EXE_SUFFIX));
const FilePath path = ndkLocation(qtVersion).pathAppended(
QString("prebuilt/%1/bin/gdb%2").arg(toolchainHost(qtVersion), QTC_HOST_EXE_SUFFIX));
if (path.exists())
return path;
// fallback for old NDKs (e.g. 10e)
return m_ndkLocation.pathAppended(QString("toolchains/%1-4.9/prebuilt/%2/bin/%3-gdb%4")
.arg(toolchainPrefix(abi), toolchainHost(), toolsPrefix(abi), QTC_HOST_EXE_SUFFIX));
return ndkLocation(qtVersion).pathAppended(QString("toolchains/%1-4.9/prebuilt/%2/bin/%3-gdb%4")
.arg(toolchainPrefix(abi), toolchainHost(qtVersion), toolsPrefix(abi), QTC_HOST_EXE_SUFFIX));
}
FilePath AndroidConfig::makePath() const
FilePath AndroidConfig::makePath(const BaseQtVersion *qtVersion) const
{
return m_ndkLocation.pathAppended(
QString("prebuilt/%1/bin/make%2").arg(toolchainHost(), QTC_HOST_EXE_SUFFIX));
return makePathFromNdk(ndkLocation(qtVersion));
}
FilePath AndroidConfig::makePathFromNdk(const FilePath &ndkLocation) const
{
return ndkLocation.pathAppended(
QString("prebuilt/%1/bin/make%2").arg(toolchainHostFromNdk(ndkLocation), QTC_HOST_EXE_SUFFIX));
}
FilePath AndroidConfig::openJDKBinPath() const
@@ -757,11 +733,10 @@ bool AndroidConfig::useNativeUiTools() const
return !version.isNull() && version <= QVersionNumber(25, 3 ,0);
}
QString AndroidConfig::bestNdkPlatformMatch(int target) const
QString AndroidConfig::bestNdkPlatformMatch(int target, const BaseQtVersion *qtVersion) const
{
target = std::max(AndroidManager::apiLevelRange().first, target);
updateNdkInformation();
foreach (int apiLevel, m_availableNdkPlatforms) {
foreach (int apiLevel, availableNdkPlatforms(qtVersion)) {
if (apiLevel <= target)
return QString::fromLatin1("android-%1").arg(apiLevel);
}
@@ -812,9 +787,9 @@ void AndroidConfig::setSdkManagerToolArgs(const QStringList &args)
m_sdkManagerToolArgs = args;
}
FilePath AndroidConfig::ndkLocation() const
FilePath AndroidConfig::ndkLocation(const BaseQtVersion *qtVersion) const
{
return m_ndkLocation;
return sdkLocation().pathAppended(ndkPathFromQtVersion(*qtVersion));
}
FilePath AndroidConfig::defaultNdkLocation() const
@@ -837,9 +812,9 @@ static inline QString gdbServerArch(const QString &androidAbi)
}
}
FilePath AndroidConfig::gdbServer(const QString &androidAbi) const
FilePath AndroidConfig::gdbServer(const QString &androidAbi, const BaseQtVersion *qtVersion) const
{
const FilePath path = AndroidConfigurations::currentConfig().ndkLocation()
const FilePath path = AndroidConfigurations::currentConfig().ndkLocation(qtVersion)
.pathAppended(QString("prebuilt/android-%1/gdbserver/gdbserver")
.arg(gdbServerArch(androidAbi)));
if (path.exists())
@@ -847,16 +822,21 @@ FilePath AndroidConfig::gdbServer(const QString &androidAbi) const
return {};
}
QVersionNumber AndroidConfig::ndkVersion() const
QVersionNumber AndroidConfig::ndkVersion(const BaseQtVersion *qtVersion) const
{
return ndkVersion(ndkLocation(qtVersion));
}
QVersionNumber AndroidConfig::ndkVersion(const FilePath &ndkPath) const
{
QVersionNumber version;
if (!m_ndkLocation.exists()) {
if (!ndkPath.exists()) {
qCDebug(avdConfigLog) << "Cannot find ndk version. Check NDK path."
<< m_ndkLocation.toString();
<< ndkPath.toString();
return version;
}
const FilePath ndkPropertiesPath = m_ndkLocation.pathAppended("source.properties");
const FilePath ndkPropertiesPath = ndkPath.pathAppended("source.properties");
if (ndkPropertiesPath.exists()) {
// source.properties files exists in NDK version > 11
QSettings settings(ndkPropertiesPath.toString(), QSettings::IniFormat);
@@ -864,7 +844,7 @@ QVersionNumber AndroidConfig::ndkVersion() const
version = QVersionNumber::fromString(versionStr);
} else {
// No source.properties. There should be a file named RELEASE.TXT
const FilePath ndkReleaseTxtPath = m_ndkLocation.pathAppended("RELEASE.TXT");
const FilePath ndkReleaseTxtPath = ndkPath.pathAppended("RELEASE.TXT");
Utils::FileReader reader;
QString errorString;
if (reader.fetch(ndkReleaseTxtPath.toString(), &errorString)) {
@@ -892,12 +872,6 @@ QVersionNumber AndroidConfig::ndkVersion() const
return version;
}
void AndroidConfig::setNdkLocation(const FilePath &ndkLocation)
{
m_ndkLocation = ndkLocation;
m_NdkInformationUpToDate = false;
}
QStringList AndroidConfig::allEssentials() const
{
QList<BaseQtVersion *> installedVersions = QtVersionManager::versions(
@@ -925,7 +899,7 @@ QStringList AndroidConfig::essentialsFromQtVersion(const BaseQtVersion &version)
QString AndroidConfig::ndkPathFromQtVersion(const BaseQtVersion &version) const
{
QtVersionNumber qtVersion = version.qtVersion();
QtVersionNumber qtVersion(version.qtVersionString());
for (const SdkForQtVersions &item : m_specificQtVersions)
if (item.containsVersion(qtVersion))
return item.ndkPath;
@@ -969,10 +943,39 @@ void AndroidConfig::setKeystoreLocation(const FilePath &keystoreLocation)
m_keystoreLocation = keystoreLocation;
}
QString AndroidConfig::toolchainHost() const
QString AndroidConfig::toolchainHost(const BaseQtVersion *qtVersion) const
{
updateNdkInformation();
return m_toolchainHost;
return toolchainHostFromNdk(ndkLocation(qtVersion));
}
QString AndroidConfig::toolchainHostFromNdk(const FilePath &ndkPath) const
{
// detect toolchain host
QString toolchainHost;
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 toolchainHost;
}
QDirIterator jt(ndkPath.pathAppended("prebuilt").toString(),
hostPatterns,
QDir::Dirs);
if (jt.hasNext()) {
jt.next();
toolchainHost = jt.fileName();
}
return toolchainHost;
}
unsigned AndroidConfig::partitionSize() const
@@ -1087,9 +1090,9 @@ void AndroidConfigurations::removeOldToolChains()
}
}
static QVariant findOrRegisterDebugger(ToolChain *tc)
static QVariant findOrRegisterDebugger(ToolChain *tc, const BaseQtVersion *qtVersion)
{
const FilePath command = AndroidConfigurations::currentConfig().gdbPath(tc->targetAbi());
const FilePath command = AndroidConfigurations::currentConfig().gdbPath(tc->targetAbi(), qtVersion);
// check if the debugger is already registered, but ignoring the display name
const Debugger::DebuggerItem *existing = Debugger::DebuggerItemManager::findByCommand(command);
if (existing && existing->engineType() == Debugger::GdbEngineType && existing->isAutoDetected()
@@ -1116,7 +1119,7 @@ void AndroidConfigurations::updateAutomaticKitList()
for (auto k: androidKits) {
if (k->value(Constants::ANDROID_KIT_NDK).isNull() || k->value(Constants::ANDROID_KIT_SDK).isNull()) {
k->setValueSilently(Constants::ANDROID_KIT_NDK, currentConfig().ndkLocation().toString());
k->setValueSilently(Constants::ANDROID_KIT_NDK, currentConfig().ndkLocation(QtSupport::QtKitAspect::qtVersion(k)).toString());
k->setValue(Constants::ANDROID_KIT_SDK, currentConfig().sdkLocation().toString());
}
}
@@ -1163,16 +1166,22 @@ void AndroidConfigurations::updateAutomaticKitList()
for (ToolChain *tc : toolchains) {
if (tc->language() != Core::Id(ProjectExplorer::Constants::CXX_LANGUAGE_ID))
continue;
const QList<ToolChain *> allLanguages = Utils::filtered(toolchains,
[tc](ToolChain *otherTc) {
return tc->targetAbi() == otherTc->targetAbi();
for (const QtSupport::BaseQtVersion *qt : qtVersionsForArch.value(tc->targetAbi())) {
FilePath tcNdk = static_cast<const AndroidToolChain *>(tc)->ndkLocation();
if (tcNdk != currentConfig().ndkLocation(qt))
continue;
const QList<ToolChain *> allLanguages
= Utils::filtered(toolchains, [tc, tcNdk](ToolChain *otherTc) {
FilePath otherNdk = static_cast<const AndroidToolChain *>(otherTc)->ndkLocation();
return tc->targetAbi() == otherTc->targetAbi() && tcNdk == otherNdk;
});
QHash<Core::Id, ToolChain *> toolChainForLanguage;
for (ToolChain *tc : allLanguages)
toolChainForLanguage[tc->language()] = tc;
for (const QtSupport::BaseQtVersion *qt : qtVersionsForArch.value(tc->targetAbi())) {
Kit *existingKit = Utils::findOrDefault(existingKits, [&](const Kit *b) {
if (qt != QtSupport::QtKitAspect::qtVersion(b))
return false;
@@ -1190,12 +1199,12 @@ void AndroidConfigurations::updateAutomaticKitList()
ToolChainKitAspect::setToolChain(k, tc);
QtSupport::QtKitAspect::setQtVersion(k, qt);
DeviceKitAspect::setDevice(k, device);
Debugger::DebuggerKitAspect::setDebugger(k, findOrRegisterDebugger(tc));
Debugger::DebuggerKitAspect::setDebugger(k, findOrRegisterDebugger(tc, QtKitAspect::qtVersion(k)));
k->makeSticky();
k->setUnexpandedDisplayName(tr("Android for %1 (Clang %2)")
.arg(static_cast<const AndroidQtVersion *>(qt)->androidAbis().join(","))
.arg(qt->displayName()));
k->setValueSilently(Constants::ANDROID_KIT_NDK, currentConfig().ndkLocation().toString());
k->setValueSilently(Constants::ANDROID_KIT_NDK, currentConfig().ndkLocation(qt).toString());
k->setValueSilently(Constants::ANDROID_KIT_SDK, currentConfig().sdkLocation().toString());
};

View File

@@ -122,11 +122,11 @@ public:
QStringList sdkManagerToolArgs() const;
void setSdkManagerToolArgs(const QStringList &args);
Utils::FilePath ndkLocation() const;
Utils::FilePath ndkLocation(const QtSupport::BaseQtVersion *qtVersion) const;
Utils::FilePath defaultNdkLocation() const;
Utils::FilePath gdbServer(const QString &androidAbi) const;
QVersionNumber ndkVersion() const;
void setNdkLocation(const Utils::FilePath &ndkLocation);
Utils::FilePath gdbServer(const QString &androidAbi, const QtSupport::BaseQtVersion *qtVersion) const;
QVersionNumber ndkVersion(const QtSupport::BaseQtVersion *qtVersion) const;
QVersionNumber ndkVersion(const Utils::FilePath &ndkPath) const;
QUrl sdkToolsUrl() const { return m_sdkToolsUrl; };
QByteArray getSdkToolsSha256() const { return m_sdkToolsSha256; };
@@ -143,7 +143,8 @@ public:
Utils::FilePath keystoreLocation() const;
void setKeystoreLocation(const Utils::FilePath &keystoreLocation);
QString toolchainHost() const;
QString toolchainHost(const QtSupport::BaseQtVersion *qtVersion) const;
QString toolchainHostFromNdk(const Utils::FilePath &ndkPath) const;
unsigned partitionSize() const;
void setPartitionSize(unsigned partitionSize);
@@ -158,18 +159,19 @@ public:
Utils::FilePath avdManagerToolPath() const;
Utils::FilePath aaptToolPath() const;
Utils::FilePath toolchainPath() const;
Utils::FilePath clangPath() const;
Utils::FilePath toolchainPath(const QtSupport::BaseQtVersion *qtVersion) const;
Utils::FilePath clangPath(const QtSupport::BaseQtVersion *qtVersion) const;
Utils::FilePath gdbPath(const ProjectExplorer::Abi &abi) const;
Utils::FilePath makePath() const;
Utils::FilePath gdbPath(const ProjectExplorer::Abi &abi, const QtSupport::BaseQtVersion *qtVersion) const;
Utils::FilePath makePath(const QtSupport::BaseQtVersion *qtVersion) const;
Utils::FilePath makePathFromNdk(const Utils::FilePath &ndkLocation) const;
Utils::FilePath keytoolPath() const;
QVector<AndroidDeviceInfo> connectedDevices(QString *error = nullptr) const;
static QVector<AndroidDeviceInfo> connectedDevices(const Utils::FilePath &adbToolPath, QString *error = nullptr);
QString bestNdkPlatformMatch(int target) const;
QString bestNdkPlatformMatch(int target, const QtSupport::BaseQtVersion *qtVersion) const;
static ProjectExplorer::Abi abiForToolChainPrefix(const QString &toolchainPrefix);
static QLatin1String toolchainPrefix(const ProjectExplorer::Abi &abi);
@@ -199,12 +201,12 @@ private:
bool isBootToQt(const QString &device) const;
static QString getAvdName(const QString &serialnumber);
void updateNdkInformation() const;
void parseDependenciesJson();
QVector<int> availableNdkPlatforms(const QtSupport::BaseQtVersion *qtVersion) const;
Utils::FilePath m_sdkLocation;
QStringList m_sdkManagerToolArgs;
Utils::FilePath m_ndkLocation;
Utils::FilePath m_openJDKLocation;
Utils::FilePath m_keystoreLocation;
unsigned m_partitionSize = 1024;
@@ -217,10 +219,6 @@ private:
bool m_sdkFullyConfigured = false;
//caches
mutable bool m_NdkInformationUpToDate = false;
mutable QString m_toolchainHost;
mutable QVector<int> m_availableNdkPlatforms;
mutable QHash<QString, QString> m_serialNumberToDeviceName;
};

View File

@@ -122,14 +122,13 @@ void AndroidDebugSupport::start()
qCDebug(androidDebugSupportLog) << "Start. Package name: " << packageName
<< "PID: " << m_runner->pid().pid();
QtSupport::BaseQtVersion *qtVersion = QtSupport::QtKitAspect::qtVersion(kit);
if (!Utils::HostOsInfo::isWindowsHost() &&
AndroidConfigurations::currentConfig().ndkVersion() >= QVersionNumber(11, 0, 0)) {
AndroidConfigurations::currentConfig().ndkVersion(qtVersion) >= QVersionNumber(11, 0, 0)) {
qCDebug(androidDebugSupportLog) << "UseTargetAsync: " << true;
setUseTargetAsync(true);
}
QtSupport::BaseQtVersion *qtVersion = QtSupport::QtKitAspect::qtVersion(kit);
if (isCppDebugging()) {
qCDebug(androidDebugSupportLog) << "C++ debugging enabled";
const ProjectNode *node = target->project()->findNodeForBuildKey(runControl()->buildKey());
@@ -160,7 +159,7 @@ void AndroidDebugSupport::start()
// TODO find a way to use the new sysroot layout
// instead ~/android/ndk-bundle/platforms/android-29/arch-arm64
// use ~/android/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/sysroot
Utils::FilePath sysRoot = AndroidConfigurations::currentConfig().ndkLocation()
Utils::FilePath sysRoot = AndroidConfigurations::currentConfig().ndkLocation(qtVersion)
.pathAppended("platforms")
.pathAppended(QString("android-%1").arg(sdkVersion))
.pathAppended(devicePreferredAbi);

View File

@@ -293,22 +293,25 @@ QJsonObject AndroidManager::deploymentSettings(const Target *target)
QJsonObject settings;
settings["_description"] = qtcSignature;
settings["qt"] = qt->prefix().toString();
settings["ndk"] = AndroidConfigurations::currentConfig().ndkLocation().toString();
settings["ndk"] = AndroidConfigurations::currentConfig().ndkLocation(qt).toString();
settings["sdk"] = AndroidConfigurations::currentConfig().sdkLocation().toString();
if (qt->qtVersion() < QtSupport::QtVersionNumber(5, 14, 0)) {
const QStringList abis = applicationAbis(target);
QTC_ASSERT(abis.size() == 1, return {});
settings["stdcpp-path"] = AndroidConfigurations::currentConfig().toolchainPath()
settings["stdcpp-path"] = AndroidConfigurations::currentConfig().toolchainPath(qt)
.pathAppended("sysroot/usr/lib/")
.pathAppended(archTriplet(abis.first()))
.pathAppended("libc++_shared.so").toString();
} else {
settings["stdcpp-path"] = AndroidConfigurations::currentConfig().toolchainPath().pathAppended("sysroot/usr/lib/").toString();
settings["stdcpp-path"] = AndroidConfigurations::currentConfig()
.toolchainPath(qt)
.pathAppended("sysroot/usr/lib/")
.toString();
}
settings["toolchain-prefix"] = "llvm";
settings["tool-prefix"] = "llvm";
settings["useLLVM"] = true;
settings["ndk-host"] = AndroidConfigurations::currentConfig().toolchainHost();
settings["ndk-host"] = AndroidConfigurations::currentConfig().toolchainHost(qt);
return settings;
}

View File

@@ -34,6 +34,8 @@
#include <coreplugin/infobar.h>
#include <coreplugin/editormanager/ieditor.h>
#include <qtsupport/qtkitinformation.h>
#include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/project.h>
#include <projectexplorer/projectnodes.h>
@@ -612,8 +614,10 @@ void AndroidManifestEditorWidget::postSave()
const Utils::FilePath docPath = m_textEditorWidget->textDocument()->filePath();
if (Target *target = androidTarget(docPath)) {
if (BuildConfiguration *bc = target->activeBuildConfiguration()) {
QString androidNdkPlatform = AndroidConfigurations::currentConfig()
.bestNdkPlatformMatch(AndroidManager::minimumSDK(target));
QString androidNdkPlatform = AndroidConfigurations::currentConfig().bestNdkPlatformMatch(
AndroidManager::minimumSDK(target),
QtSupport::QtKitAspect::qtVersion(
androidTarget(m_textEditorWidget->textDocument()->filePath())->kit()));
if (m_androidNdkPlatform != androidNdkPlatform) {
m_androidNdkPlatform = androidNdkPlatform;
bc->updateCacheAndEmitEnvironmentChanged();

View File

@@ -178,6 +178,7 @@ void AndroidPlugin::kitsRestored()
}
AndroidConfigurations::updateAutomaticKitList();
AndroidConfigurations::registerNewToolChains();
connect(QtSupport::QtVersionManager::instance(), &QtSupport::QtVersionManager::qtVersionsChanged,
AndroidConfigurations::instance(), &AndroidConfigurations::updateAutomaticKitList);
disconnect(KitManager::instance(), &KitManager::kitsLoaded,

View File

@@ -70,7 +70,7 @@ QString AndroidQtVersion::invalidReason() const
{
QString tmp = BaseQtVersion::invalidReason();
if (tmp.isEmpty()) {
if (AndroidConfigurations::currentConfig().ndkLocation().isEmpty())
if (AndroidConfigurations::currentConfig().ndkLocation(this).isEmpty())
return tr("NDK is not configured in Devices > Android.");
if (AndroidConfigurations::currentConfig().sdkLocation().isEmpty())
return tr("SDK is not configured in Devices > Android.");
@@ -126,16 +126,17 @@ void AndroidQtVersion::addToEnvironment(const Kit *k, Utils::Environment &env) c
{
const AndroidConfig &config =AndroidConfigurations::currentConfig();
// this env vars are used by qmake mkspecs to generate makefiles (check QTDIR/mkspecs/android-g++/qmake.conf for more info)
env.set(QLatin1String("ANDROID_NDK_HOST"), config.toolchainHost());
env.set(QLatin1String("ANDROID_NDK_ROOT"), config.ndkLocation().toUserOutput());
env.set(QLatin1String("ANDROID_NDK_HOST"), config.toolchainHost(this));
env.set(QLatin1String("ANDROID_NDK_ROOT"), config.ndkLocation(this).toUserOutput());
env.set(QLatin1String("ANDROID_NDK_PLATFORM"),
config.bestNdkPlatformMatch(qMax(minimumNDK(), AndroidManager::minimumSDK(k))));
config.bestNdkPlatformMatch(qMax(minimumNDK(), AndroidManager::minimumSDK(k)), this));
}
Utils::Environment AndroidQtVersion::qmakeRunEnvironment() const
{
Utils::Environment env = Utils::Environment::systemEnvironment();
env.set(QLatin1String("ANDROID_NDK_ROOT"), AndroidConfigurations::currentConfig().ndkLocation().toUserOutput());
env.set(QLatin1String("ANDROID_NDK_ROOT"),
AndroidConfigurations::currentConfig().ndkLocation(this).toUserOutput());
return env;
}

View File

@@ -225,10 +225,11 @@ AndroidRunnerWorker::AndroidRunnerWorker(RunWorker *runner, const QString &packa
<< "Extra Start Args:" << m_amStartExtraArgs
<< "Before Start ADB cmds:" << m_beforeStartAdbCommands
<< "After finish ADB cmds:" << m_afterFinishAdbCommands;
QtSupport::BaseQtVersion *version = QtSupport::QtKitAspect::qtVersion(target->kit());
QString preferredAbi = AndroidManager::apkDevicePreferredAbi(target);
if (!preferredAbi.isEmpty())
m_gdbserverPath = AndroidConfigurations::instance()->currentConfig().gdbServer(preferredAbi).toString();
QtSupport::BaseQtVersion *version = QtSupport::QtKitAspect::qtVersion(target->kit());
m_gdbserverPath = AndroidConfigurations::instance()
->currentConfig().gdbServer(preferredAbi, version).toString();
m_useAppParamsForQmlDebugger = version->qtVersion() >= QtSupport::QtVersionNumber(5, 12);
}

View File

@@ -336,10 +336,8 @@ Utils::FilePath AndroidSettingsWidget::getDefaultSdkPath()
void AndroidSettingsWidget::updateNdkList()
{
m_ui->ndkListComboBox->clear();
QString currentNdk = m_androidConfig.ndkLocation().toString();
for (const Ndk *ndk : m_sdkManager->installedNdkPackages())
m_ui->ndkListComboBox->addItem(ndk->installedLocation().toString());
m_ui->ndkListComboBox->setCurrentText(currentNdk);
}
AndroidSettingsWidget::AndroidSettingsWidget()
@@ -584,7 +582,6 @@ Utils::FilePath AndroidSettingsWidget::findJdkInCommonPaths()
void AndroidSettingsWidget::validateNdk()
{
auto ndkPath = Utils::FilePath::fromUserInput(m_ui->ndkListComboBox->currentText());
m_androidConfig.setNdkLocation(ndkPath);
auto summaryWidget = static_cast<SummaryWidget *>(m_ui->androidDetailsWidget->widget());
summaryWidget->setPointValid(NdkPathExistsRow, ndkPath.exists());
@@ -745,9 +742,10 @@ void AndroidSettingsWidget::updateUI()
m_ui->sdkManagerTab->setEnabled(sdkToolsOk);
m_sdkManagerWidget->setSdkManagerControlsEnabled(!m_androidConfig.useNativeUiTools());
Utils::FilePath currentNdk = Utils::FilePath::fromString(m_ui->ndkListComboBox->currentText());
auto infoText = tr("(SDK Version: %1, NDK Bundle Version: %2)")
.arg(m_androidConfig.sdkToolsVersion().toString())
.arg(m_androidConfig.ndkVersion().toString());
.arg(currentNdk.isEmpty() ? "" : m_androidConfig.ndkVersion(currentNdk).toString());
androidSummaryWidget->setInfoText(androidSetupOk ? infoText : "");
m_ui->javaDetailsWidget->setState(javaSetupOk ? Utils::DetailsWidget::Collapsed :

View File

@@ -27,6 +27,7 @@
#include "androidconstants.h"
#include "androidconfigurations.h"
#include <projectexplorer/kitmanager.h>
#include <projectexplorer/toolchainmanager.h>
#include <projectexplorer/projectexplorer.h>
@@ -78,22 +79,36 @@ AndroidToolChain::AndroidToolChain()
setTypeDisplayName(AndroidToolChainFactory::tr("Android Clang"));
}
Utils::FilePath AndroidToolChain::ndkLocation() const
{
return m_ndkLocation;
}
void AndroidToolChain::setNdkLocation(const Utils::FilePath &ndkLocation)
{
m_ndkLocation = ndkLocation;
}
AndroidToolChain::~AndroidToolChain() = default;
bool AndroidToolChain::isValid() const
{
return ClangToolChain::isValid()
&& typeId() == Constants::ANDROID_TOOLCHAIN_TYPEID
const bool isChildofNdk = compilerCommand().isChildOf(m_ndkLocation);
// If we're restoring a toolchain we set NDK path ourselves so it's enough to check against SDK
const bool isChildofSdk = compilerCommand().isChildOf(
AndroidConfigurations::currentConfig().sdkLocation());
return ClangToolChain::isValid() && typeId() == Constants::ANDROID_TOOLCHAIN_TYPEID
&& targetAbi().isValid()
&& compilerCommand().isChildOf(AndroidConfigurations::currentConfig().ndkLocation())
&& (isChildofNdk || isChildofSdk)
&& !originalTargetTriple().isEmpty();
}
void AndroidToolChain::addToEnvironment(Environment &env) const
{
env.set(QLatin1String("ANDROID_NDK_HOST"),
AndroidConfigurations::currentConfig().toolchainHost());
const Utils::FilePath javaHome = AndroidConfigurations::currentConfig().openJDKLocation();
AndroidConfig config = AndroidConfigurations::currentConfig();
env.set(QLatin1String("ANDROID_NDK_HOST"), config.toolchainHostFromNdk(m_ndkLocation));
const Utils::FilePath javaHome = config.openJDKLocation();
if (javaHome.exists()) {
env.set(QLatin1String("JAVA_HOME"), javaHome.toString());
const FilePath javaBin = javaHome.pathAppended("bin");
@@ -101,10 +116,8 @@ void AndroidToolChain::addToEnvironment(Environment &env) const
if (!currentJavaFilePath.isChildOf(javaBin))
env.prependOrSetPath(javaBin.toUserOutput());
}
env.set(QLatin1String("ANDROID_HOME"),
AndroidConfigurations::currentConfig().sdkLocation().toString());
env.set(QLatin1String("ANDROID_SDK_ROOT"),
AndroidConfigurations::currentConfig().sdkLocation().toString());
env.set(QLatin1String("ANDROID_HOME"), config.sdkLocation().toString());
env.set(QLatin1String("ANDROID_SDK_ROOT"), config.sdkLocation().toString());
}
bool AndroidToolChain::fromMap(const QVariantMap &data)
@@ -122,7 +135,7 @@ QStringList AndroidToolChain::suggestedMkspecList() const
FilePath AndroidToolChain::makeCommand(const Environment &env) const
{
Q_UNUSED(env)
FilePath makePath = AndroidConfigurations::currentConfig().makePath();
FilePath makePath = AndroidConfigurations::currentConfig().makePathFromNdk(m_ndkLocation);
return makePath.exists() ? makePath : FilePath::fromString("make");
}
@@ -160,17 +173,44 @@ static FilePath clangPlusPlusPath(const FilePath &clangPath)
QFileInfo(clangPath.toString()).baseName() + "++"));
}
static QList<QtSupport::BaseQtVersion *> androidQtVersionsWithUniqueNdk()
{
AndroidConfig config = AndroidConfigurations::currentConfig();
auto androidQtVersions = QtSupport::QtVersionManager::versions(
[](const QtSupport::BaseQtVersion *v) {
return v->targetDeviceTypes().contains(Android::Constants::ANDROID_DEVICE_TYPE);
});
auto shouldRemove = [config](const QtSupport::BaseQtVersion *first,
const QtSupport::BaseQtVersion *second) {
return config.ndkLocation(first) == config.ndkLocation(second);
};
QList<QtSupport::BaseQtVersion *>::iterator it = std::unique(androidQtVersions.begin(),
androidQtVersions.end(),
shouldRemove);
androidQtVersions.erase(it, androidQtVersions.end());
return androidQtVersions;
}
ToolChainList AndroidToolChainFactory::autodetectToolChainsForNdk(const ToolChainList &alreadyKnown)
{
QList<ToolChain *> result;
FilePath clangPath = AndroidConfigurations::currentConfig().clangPath();
const QList<QtSupport::BaseQtVersion *> androidQtVersions = androidQtVersionsWithUniqueNdk();
const AndroidConfig config = AndroidConfigurations::currentConfig();
for (const QtSupport::BaseQtVersion *qtVersion : androidQtVersions) {
FilePath clangPath = config.clangPath(qtVersion);
if (!clangPath.exists()) {
qCDebug(androidTCLog) << "Clang toolchains detection fails. Can not find Clang"<< clangPath;
qCDebug(androidTCLog) << "Clang toolchains detection fails. Can not find Clang"
<< clangPath;
return result;
}
qCDebug(androidTCLog) << "Detecting toolchains from Android NDK:"
<< AndroidConfigurations::currentConfig().ndkLocation();
<< config.ndkLocation(qtVersion);
for (const Core::Id &lang : LanguageIds) {
FilePath compilerCommand = clangPath;
@@ -178,8 +218,8 @@ ToolChainList AndroidToolChainFactory::autodetectToolChainsForNdk(const ToolChai
compilerCommand = clangPlusPlusPath(clangPath);
if (!compilerCommand.exists()) {
qCDebug(androidTCLog) << "Skipping Clang toolchain. Can not find compiler"
<< compilerCommand;
qCDebug(androidTCLog)
<< "Skipping Clang toolchain. Can not find compiler" << compilerCommand;
continue;
}
@@ -192,16 +232,18 @@ ToolChainList AndroidToolChainFactory::autodetectToolChainsForNdk(const ToolChai
qCDebug(androidTCLog) << "Tool chain already known" << abi.toString() << lang;
} else {
qCDebug(androidTCLog) << "New Clang toolchain found" << abi.toString() << lang;
auto atc = new AndroidToolChain;
auto atc = new AndroidToolChain();
atc->setNdkLocation(config.ndkLocation(qtVersion));
atc->setOriginalTargetTriple(target);
atc->setLanguage(lang);
atc->setTargetAbi(ClangTargets[target]);
atc->setPlatformCodeGenFlags({"-target", target});
atc->setPlatformLinkerFlags({"-target", target});
atc->setDetection(ToolChain::AutoDetection);
atc->setDisplayName(QString("Android Clang (%1, %2)")
atc->setDisplayName(QString("Android Clang (%1, %2, NDK %3)")
.arg(ToolChainManager::displayNameOfLanguageId(lang),
AndroidConfig::displayName(abi)));
AndroidConfig::displayName(abi),
config.ndkVersion(qtVersion).toString()));
atc->resetToolChain(compilerCommand);
tc = atc;
}
@@ -209,6 +251,7 @@ ToolChainList AndroidToolChainFactory::autodetectToolChainsForNdk(const ToolChai
++targetItr;
}
}
}
return result;
}

View File

@@ -25,6 +25,8 @@
#pragma once
#include <qtsupport/baseqtversion.h>
#include <projectexplorer/gcctoolchain.h>
namespace Android {
@@ -44,6 +46,9 @@ public:
Utils::FilePath makeCommand(const Utils::Environment &environment) const override;
bool fromMap(const QVariantMap &data) override;
void setNdkLocation(const Utils::FilePath &ndkLocation);
Utils::FilePath ndkLocation() const;
protected:
DetectedAbisResult detectSupportedAbis() const override;
@@ -51,6 +56,8 @@ private:
explicit AndroidToolChain();
friend class AndroidToolChainFactory;
Utils::FilePath m_ndkLocation;
};
class AndroidToolChainFactory : public ProjectExplorer::ToolChainFactory