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 QVariant AndroidBuildApkStep::data(Core::Id id) const
{ {
if (id == Constants::AndroidNdkPlatform) QtSupport::BaseQtVersion *qtVersion = QtSupport::QtKitAspect::qtVersion(target()->kit());
return AndroidConfigurations::currentConfig().bestNdkPlatformMatch(AndroidManager::minimumSDK(target())).mid(8);
if (id == Constants::AndroidNdkPlatform) {
return AndroidConfigurations::currentConfig()
.bestNdkPlatformMatch(AndroidManager::minimumSDK(target()), qtVersion).mid(8);
}
if (id == Constants::NdkLocation) if (id == Constants::NdkLocation)
return QVariant::fromValue(AndroidConfigurations::currentConfig().ndkLocation()); return QVariant::fromValue(AndroidConfigurations::currentConfig().ndkLocation(qtVersion));
if (id == Constants::SdkLocation) if (id == Constants::SdkLocation)
return QVariant::fromValue(AndroidConfigurations::currentConfig().sdkLocation()); return QVariant::fromValue(AndroidConfigurations::currentConfig().sdkLocation());
if (id == Constants::AndroidABIs) if (id == Constants::AndroidABIs)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -70,7 +70,7 @@ QString AndroidQtVersion::invalidReason() const
{ {
QString tmp = BaseQtVersion::invalidReason(); QString tmp = BaseQtVersion::invalidReason();
if (tmp.isEmpty()) { if (tmp.isEmpty()) {
if (AndroidConfigurations::currentConfig().ndkLocation().isEmpty()) if (AndroidConfigurations::currentConfig().ndkLocation(this).isEmpty())
return tr("NDK is not configured in Devices > Android."); return tr("NDK is not configured in Devices > Android.");
if (AndroidConfigurations::currentConfig().sdkLocation().isEmpty()) if (AndroidConfigurations::currentConfig().sdkLocation().isEmpty())
return tr("SDK is not configured in Devices > Android."); 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(); 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) // 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_HOST"), config.toolchainHost(this));
env.set(QLatin1String("ANDROID_NDK_ROOT"), config.ndkLocation().toUserOutput()); env.set(QLatin1String("ANDROID_NDK_ROOT"), config.ndkLocation(this).toUserOutput());
env.set(QLatin1String("ANDROID_NDK_PLATFORM"), 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 AndroidQtVersion::qmakeRunEnvironment() const
{ {
Utils::Environment env = Utils::Environment::systemEnvironment(); 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; return env;
} }

View File

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

View File

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

View File

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

View File

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