summaryrefslogtreecommitdiff
path: root/src/plugins/android
diff options
context:
space:
mode:
authorBogDan Vatra <bogdan@kde.org>2019-08-26 14:19:07 +0300
committerBogDan Vatra <bogdan@kdab.com>2019-09-16 07:34:54 +0000
commit6b31f9cf23cac79c10a9871961e3de79be657b38 (patch)
tree00098f39b2ac1698324bcfb79364ffac8574b397 /src/plugins/android
parent567a20843ff1024725eac26440e03b05b1f06b4d (diff)
downloadqt-creator-6b31f9cf23cac79c10a9871961e3de79be657b38.tar.gz
Android multi arch support
[ChangeLog][Android] Android multi arch support for qmake Change-Id: Ib8b1874604a3392130c96fbc00b26713b3d788ae Reviewed-by: hjk <hjk@qt.io>
Diffstat (limited to 'src/plugins/android')
-rw-r--r--src/plugins/android/CMakeLists.txt1
-rw-r--r--src/plugins/android/android.pro2
-rw-r--r--src/plugins/android/android.qbs2
-rw-r--r--src/plugins/android/androidbuildapkstep.cpp74
-rw-r--r--src/plugins/android/androidbuildapkstep.h6
-rw-r--r--src/plugins/android/androidbuildapkwidget.cpp7
-rw-r--r--src/plugins/android/androidconfigurations.cpp66
-rw-r--r--src/plugins/android/androidconfigurations.h6
-rw-r--r--src/plugins/android/androidconstants.h2
-rw-r--r--src/plugins/android/androiddebugsupport.cpp16
-rw-r--r--src/plugins/android/androiddeployqtstep.cpp33
-rw-r--r--src/plugins/android/androiddeployqtstep.h2
-rw-r--r--src/plugins/android/androiddevicedialog.cpp20
-rw-r--r--src/plugins/android/androiddevicedialog.h4
-rw-r--r--src/plugins/android/androidgdbserverkitinformation.cpp217
-rw-r--r--src/plugins/android/androidgdbserverkitinformation.h53
-rw-r--r--src/plugins/android/androidmanager.cpp132
-rw-r--r--src/plugins/android/androidmanager.h12
-rw-r--r--src/plugins/android/androidplugin.cpp2
-rw-r--r--src/plugins/android/androidqtversion.cpp55
-rw-r--r--src/plugins/android/androidqtversion.h4
-rw-r--r--src/plugins/android/androidrunner.cpp4
-rw-r--r--src/plugins/android/androidrunnerworker.cpp3
-rw-r--r--src/plugins/android/avddialog.cpp10
-rw-r--r--src/plugins/android/avddialog.h4
25 files changed, 301 insertions, 436 deletions
diff --git a/src/plugins/android/CMakeLists.txt b/src/plugins/android/CMakeLists.txt
index 36bde749a9..aeb808423b 100644
--- a/src/plugins/android/CMakeLists.txt
+++ b/src/plugins/android/CMakeLists.txt
@@ -18,7 +18,6 @@ add_qtc_plugin(Android
androiddevicedialog.cpp androiddevicedialog.h androiddevicedialog.ui
androiderrormessage.cpp androiderrormessage.h
androidextralibrarylistmodel.cpp androidextralibrarylistmodel.h
- androidgdbserverkitinformation.cpp androidgdbserverkitinformation.h
androidglobal.h
androidmanager.cpp androidmanager.h
androidmanifestdocument.cpp androidmanifestdocument.h
diff --git a/src/plugins/android/android.pro b/src/plugins/android/android.pro
index f0a952c622..c00021f48b 100644
--- a/src/plugins/android/android.pro
+++ b/src/plugins/android/android.pro
@@ -24,7 +24,6 @@ HEADERS += \
javaparser.h \
androidplugin.h \
androiddevice.h \
- androidgdbserverkitinformation.h \
androidqmltoolingsupport.h \
androidmanifesteditorfactory.h \
androidmanifesteditor.h \
@@ -69,7 +68,6 @@ SOURCES += \
javaparser.cpp \
androidplugin.cpp \
androiddevice.cpp \
- androidgdbserverkitinformation.cpp \
androidqmltoolingsupport.cpp \
androidmanifesteditorfactory.cpp \
androidmanifesteditor.cpp \
diff --git a/src/plugins/android/android.qbs b/src/plugins/android/android.qbs
index 1c6ed28a41..8b6a6aba91 100644
--- a/src/plugins/android/android.qbs
+++ b/src/plugins/android/android.qbs
@@ -49,8 +49,6 @@ Project {
"androiderrormessage.cpp",
"androidextralibrarylistmodel.cpp",
"androidextralibrarylistmodel.h",
- "androidgdbserverkitinformation.cpp",
- "androidgdbserverkitinformation.h",
"androidglobal.h",
"androidmanager.cpp",
"androidmanager.h",
diff --git a/src/plugins/android/androidbuildapkstep.cpp b/src/plugins/android/androidbuildapkstep.cpp
index 0875743900..df2708c374 100644
--- a/src/plugins/android/androidbuildapkstep.cpp
+++ b/src/plugins/android/androidbuildapkstep.cpp
@@ -205,8 +205,9 @@ bool AndroidBuildApkStep::init()
setOutputParser(parser);
m_openPackageLocationForRun = m_openPackageLocation;
- m_apkPath = AndroidManager::apkPath(target()).toString();
- qCDebug(buildapkstepLog) << "APK path:" << m_apkPath;
+ m_packagePath = m_buildAAB ? AndroidManager::aabPath(target()).toString()
+ : AndroidManager::apkPath(target()).toString();
+ qCDebug(buildapkstepLog) << "Package path:" << m_packagePath;
if (!AbstractProcessStep::init())
return false;
@@ -246,6 +247,9 @@ bool AndroidBuildApkStep::init()
arguments << "--gradle";
+ if (m_buildAAB)
+ arguments << "--aab" << "--jarsigner";
+
if (m_useMinistro)
arguments << "--deployment" << "ministro";
@@ -286,7 +290,7 @@ bool AndroidBuildApkStep::init()
void AndroidBuildApkStep::showInGraphicalShell()
{
- Core::FileUtils::showInGraphicalShell(Core::ICore::mainWindow(), m_apkPath);
+ Core::FileUtils::showInGraphicalShell(Core::ICore::mainWindow(), m_packagePath);
}
ProjectExplorer::BuildStepConfigWidget *AndroidBuildApkStep::createConfigWidget()
@@ -373,14 +377,15 @@ void AndroidBuildApkStep::doRun()
auto setup = [this] {
auto bc = target()->activeBuildConfiguration();
- Utils::FilePath androidLibsDir = bc->buildDirectory()
- .pathAppended("android-build/libs")
- .pathAppended(AndroidManager::targetArch(target()));
- if (!androidLibsDir.exists() && !QDir{bc->buildDirectory().toString()}.mkpath(androidLibsDir.toString()))
- return false;
-
+ const auto androidAbis = AndroidManager::applicationAbis(target());
+ for (const auto &abi : androidAbis) {
+ Utils::FilePath androidLibsDir = bc->buildDirectory()
+ .pathAppended("android-build/libs")
+ .pathAppended(abi);
+ if (!androidLibsDir.exists() && !QDir{bc->buildDirectory().toString()}.mkpath(androidLibsDir.toString()))
+ return false;
+ }
- QJsonObject deploySettings = Android::AndroidManager::deploymentSettings(target());
RunConfiguration *rc = target()->activeRunConfiguration();
const QString buildKey = rc ? rc->buildKey() : QString();
const ProjectNode *node = rc ? target()->project()->findNodeForBuildKey(buildKey) : nullptr;
@@ -392,12 +397,41 @@ void AndroidBuildApkStep::doRun()
if (targets.isEmpty())
return true; // qmake does this job for us
+ QJsonObject deploySettings = Android::AndroidManager::deploymentSettings(target());
+ QJsonObject architectures;
+
// Copy targets to android build folder
- for (const auto &target : targets) {
- if (!copyFileIfNewer(target, androidLibsDir.pathAppended(QFileInfo{target}.fileName()).toString()))
- return false;
+ QString applicationBinary = target()->activeRunConfiguration()->buildTargetInfo().targetFilePath.toFileInfo().fileName();
+ for (const auto &abi : androidAbis) {
+ QString targetSuffix = QString{"_%1.so"}.arg(abi);
+ if (applicationBinary.endsWith(targetSuffix)) {
+ // Keep only TargetName from "lib[TargetName]_abi.so"
+ applicationBinary.remove(0, 3).chop(targetSuffix.size());
+ }
+
+ Utils::FilePath androidLibsDir = bc->buildDirectory()
+ .pathAppended("android-build/libs")
+ .pathAppended(abi);
+ for (const auto &target : targets) {
+ if (target.endsWith(targetSuffix)) {
+ if (!copyFileIfNewer(target, androidLibsDir.pathAppended(QFileInfo{target}.fileName()).toString()))
+ return false;
+ if (abi == "x86") {
+ architectures[abi] = "i686-linux-android";
+ } else if (abi == "x86_64") {
+ architectures[abi] = "x86_64-linux-android";
+ } else if (abi == "arm64-v8a") {
+ architectures[abi] = "aarch64-linux-android";
+ } else {
+ architectures[abi] = "arm-linux-androideabi";
+ }
+ }
+ }
}
+ deploySettings["application-binary"] = applicationBinary;
+ deploySettings["architectures"] = architectures;
+
QString extraLibs = node->data(Android::Constants::AndroidExtraLibs).toString();
if (!extraLibs.isEmpty())
deploySettings["android-extra-libs"] = extraLibs;
@@ -485,8 +519,8 @@ QVariant AndroidBuildApkStep::data(Core::Id id) const
return AndroidConfigurations::currentConfig().bestNdkPlatformMatch(AndroidManager::minimumSDK(target())).mid(8);
if (id == Constants::NdkLocation)
return QVariant::fromValue(AndroidConfigurations::currentConfig().ndkLocation());
- if (id == Constants::AndroidABI)
- return AndroidManager::targetArch(target());
+ if (id == Constants::AndroidABIs)
+ return AndroidManager::applicationAbis(target());
return AbstractProcessStep::data(id);
}
@@ -523,6 +557,16 @@ void AndroidBuildApkStep::setSignPackage(bool b)
m_signPackage = b;
}
+bool AndroidBuildApkStep::buildAAB() const
+{
+ return m_buildAAB;
+}
+
+void AndroidBuildApkStep::setBuildAAB(bool aab)
+{
+ m_buildAAB = aab;
+}
+
bool AndroidBuildApkStep::openPackageLocation() const
{
return m_openPackageLocation;
diff --git a/src/plugins/android/androidbuildapkstep.h b/src/plugins/android/androidbuildapkstep.h
index 9e7ec4a07a..2ed137ccc3 100644
--- a/src/plugins/android/androidbuildapkstep.h
+++ b/src/plugins/android/androidbuildapkstep.h
@@ -61,6 +61,9 @@ public:
bool signPackage() const;
void setSignPackage(bool b);
+ bool buildAAB() const;
+ void setBuildAAB(bool aab);
+
bool openPackageLocation() const;
void setOpenPackageLocation(bool open);
@@ -89,6 +92,7 @@ private:
void doRun() override;
+ bool m_buildAAB = false;
bool m_signPackage = false;
bool m_verbose = false;
bool m_useMinistro = false;
@@ -101,7 +105,7 @@ private:
QString m_keystorePasswd;
QString m_certificateAlias;
QString m_certificatePasswd;
- QString m_apkPath;
+ QString m_packagePath;
QString m_command;
QString m_argumentsPasswordConcealed;
diff --git a/src/plugins/android/androidbuildapkwidget.cpp b/src/plugins/android/androidbuildapkwidget.cpp
index ff8441f889..ccb9454225 100644
--- a/src/plugins/android/androidbuildapkwidget.cpp
+++ b/src/plugins/android/androidbuildapkwidget.cpp
@@ -236,6 +236,13 @@ QWidget *AndroidBuildApkWidget::createAdvancedGroup()
m_step, &AndroidBuildApkStep::setUseMinistro);
auto vbox = new QVBoxLayout(group);
+ QtSupport::BaseQtVersion *version = QtSupport::QtKitAspect::qtVersion(step()->target()->kit());
+ if (version && version->qtVersion() >= QtSupport::QtVersionNumber{5,14}) {
+ auto buildAAB = new QCheckBox(tr("Build .aab (Android App Bundle)"), group);
+ buildAAB->setChecked(m_step->buildAAB());
+ connect(buildAAB, &QAbstractButton::toggled, m_step, &AndroidBuildApkStep::setBuildAAB);
+ vbox->addWidget(buildAAB);
+ }
vbox->addWidget(openPackageLocationCheckBox);
vbox->addWidget(verboseOutputCheckBox);
vbox->addWidget(m_addDebuggerCheckBox);
diff --git a/src/plugins/android/androidconfigurations.cpp b/src/plugins/android/androidconfigurations.cpp
index aa74b1578c..6986d56a8f 100644
--- a/src/plugins/android/androidconfigurations.cpp
+++ b/src/plugins/android/androidconfigurations.cpp
@@ -27,7 +27,6 @@
#include "androidconstants.h"
#include "androidtoolchain.h"
#include "androiddevice.h"
-#include "androidgdbserverkitinformation.h"
#include "androidmanager.h"
#include "androidqtversion.h"
#include "androiddevicedialog.h"
@@ -364,11 +363,9 @@ FilePath AndroidConfig::aaptToolPath() const
return aaptToolPath.pathAppended(toolPath);
}
-FilePath AndroidConfig::clangPath() const
+FilePath AndroidConfig::toolchainPath() const
{
- const FilePath clangPath = m_ndkLocation.pathAppended("toolchains/llvm/prebuilt/");
- const FilePath oldNdkClangPath = m_ndkLocation.pathAppended("toolchains/llvm-3.6/prebuilt/");
- const QVector<FilePath> clangSearchPaths{clangPath, oldNdkClangPath};
+ const FilePath toolchainPath = m_ndkLocation.pathAppended("toolchains/llvm/prebuilt/");
// detect toolchain host
QStringList hostPatterns;
@@ -385,18 +382,23 @@ FilePath AndroidConfig::clangPath() const
default: /* unknown host */ return FilePath();
}
- for (const FilePath &path : clangSearchPaths) {
- QDirIterator iter(path.toString(), hostPatterns, QDir::Dirs);
- if (iter.hasNext()) {
- iter.next();
- return path.pathAppended(iter.fileName())
- .pathAppended(HostOsInfo::withExecutableSuffix("bin/clang"));
- }
+ QDirIterator iter(toolchainPath.toString(), hostPatterns, QDir::Dirs);
+ if (iter.hasNext()) {
+ iter.next();
+ return toolchainPath.pathAppended(iter.fileName());
}
return {};
}
+FilePath AndroidConfig::clangPath() const
+{
+ const FilePath path = toolchainPath();
+ if (path.isEmpty())
+ return {};
+ return path.pathAppended(HostOsInfo::withExecutableSuffix("bin/clang"));
+}
+
FilePath AndroidConfig::gdbPath(const ProjectExplorer::Abi &abi) const
{
const FilePath path = m_ndkLocation.pathAppended(
@@ -733,22 +735,26 @@ FilePath AndroidConfig::ndkLocation() const
return m_ndkLocation;
}
-static inline QString gdbServerArch(const Abi &abi)
+static inline QString gdbServerArch(const QString &androidAbi)
{
- switch (abi.architecture()) {
- case Abi::X86Architecture:
- return abi.wordWidth() == 64 ? QString{"x86_64"} : QString{"x86"};
- case Abi::ArmArchitecture:
- return abi.wordWidth() == 64 ? QString{"arm64"} : QString{"arm"};
- default: return {};
- };
+ if (androidAbi == "arm64-v8a") {
+ return "arm64";
+ } else if (androidAbi == "armeabi-v7a") {
+ return "arm";
+ } else if (androidAbi == "x86_64") {
+ return "x86_64";
+ } else if (androidAbi == "x86") {
+ return "x86";
+ } else {
+ return {};
+ }
}
-FilePath AndroidConfig::gdbServer(const ProjectExplorer::Abi &abi) const
+FilePath AndroidConfig::gdbServer(const QString &androidAbi) const
{
const FilePath path = AndroidConfigurations::currentConfig().ndkLocation()
.pathAppended(QString("prebuilt/android-%1/gdbserver/gdbserver")
- .arg(gdbServerArch(abi)));
+ .arg(gdbServerArch(androidAbi)));
if (path.exists())
return path;
return {};
@@ -875,16 +881,21 @@ void AndroidConfigurations::setConfig(const AndroidConfig &devConfigs)
}
AndroidDeviceInfo AndroidConfigurations::showDeviceDialog(Project *project,
- int apiLevel, const QString &abi)
+ int apiLevel, const QStringList &abis)
{
- QString serialNumber = defaultDevice(project, abi);
- AndroidDeviceDialog dialog(apiLevel, abi, serialNumber, Core::ICore::mainWindow());
+ QString serialNumber;
+ for (const QString &abi : abis) {
+ serialNumber = defaultDevice(project, abi);
+ if (!serialNumber.isEmpty())
+ break;
+ }
+ AndroidDeviceDialog dialog(apiLevel, abis, serialNumber, Core::ICore::mainWindow());
AndroidDeviceInfo info = dialog.device();
if (dialog.saveDeviceSelection() && info.isValid()) {
const QString serialNumber = info.type == AndroidDeviceInfo::Hardware ?
info.serialNumber : info.avdname;
if (!serialNumber.isEmpty())
- AndroidConfigurations::setDefaultDevice(project, abi, serialNumber);
+ AndroidConfigurations::setDefaultDevice(project, AndroidManager::devicePreferredAbi(info.cpuAbi, abis), serialNumber);
}
return info;
}
@@ -1049,10 +1060,9 @@ void AndroidConfigurations::updateAutomaticKitList()
QtSupport::QtKitAspect::setQtVersion(k, qt);
DeviceKitAspect::setDevice(k, device);
Debugger::DebuggerKitAspect::setDebugger(k, findOrRegisterDebugger(tc));
- AndroidGdbServerKitAspect::setGdbSever(k, currentConfig().gdbServer(tc->targetAbi()));
k->makeSticky();
k->setUnexpandedDisplayName(tr("Android for %1 (Clang %2)")
- .arg(static_cast<const AndroidQtVersion *>(qt)->targetArch())
+ .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_SDK, currentConfig().sdkLocation().toString());
diff --git a/src/plugins/android/androidconfigurations.h b/src/plugins/android/androidconfigurations.h
index 749c4d3bbc..aba533fc27 100644
--- a/src/plugins/android/androidconfigurations.h
+++ b/src/plugins/android/androidconfigurations.h
@@ -105,7 +105,7 @@ public:
void setSdkManagerToolArgs(const QStringList &args);
Utils::FilePath ndkLocation() const;
- Utils::FilePath gdbServer(const ProjectExplorer::Abi &abi) const;
+ Utils::FilePath gdbServer(const QString &androidAbi) const;
QVersionNumber ndkVersion() const;
void setNdkLocation(const Utils::FilePath &ndkLocation);
@@ -132,7 +132,9 @@ public:
Utils::FilePath avdManagerToolPath() const;
Utils::FilePath aaptToolPath() const;
+ Utils::FilePath toolchainPath() const;
Utils::FilePath clangPath() const;
+
Utils::FilePath gdbPath(const ProjectExplorer::Abi &abi) const;
Utils::FilePath makePath() const;
@@ -196,7 +198,7 @@ public:
static void setConfig(const AndroidConfig &config);
static AndroidConfigurations *instance();
- static AndroidDeviceInfo showDeviceDialog(ProjectExplorer::Project *project, int apiLevel, const QString &abi);
+ static AndroidDeviceInfo showDeviceDialog(ProjectExplorer::Project *project, int apiLevel, const QStringList &abis);
static void setDefaultDevice(ProjectExplorer::Project *project, const QString &abi, const QString &serialNumber); // serial number or avd name
static QString defaultDevice(ProjectExplorer::Project *project, const QString &abi); // serial number or avd name
static void clearDefaultDevices(ProjectExplorer::Project *project);
diff --git a/src/plugins/android/androidconstants.h b/src/plugins/android/androidconstants.h
index d2794842cb..b617087787 100644
--- a/src/plugins/android/androidconstants.h
+++ b/src/plugins/android/androidconstants.h
@@ -82,7 +82,7 @@ const char AndroidManifest[] = "Android.Manifest"; // QStringList
const char AndroidNdkPlatform[] = "AndroidNdkPlatform"; //QString
const char NdkLocation[] = "NdkLocation"; // FileName
-const char AndroidABI[] = "AndroidABI"; // QString
+const char AndroidABIs[] = "AndroidABIs"; // QString
} // namespace Constants;
} // namespace Android
diff --git a/src/plugins/android/androiddebugsupport.cpp b/src/plugins/android/androiddebugsupport.cpp
index 181d55e4cb..0481df89b2 100644
--- a/src/plugins/android/androiddebugsupport.cpp
+++ b/src/plugins/android/androiddebugsupport.cpp
@@ -102,15 +102,6 @@ static QStringList getExtraLibs(const ProjectNode *node)
return node->data(Android::Constants::AndroidExtraLibs).toStringList();
}
-static QString toNdkArch(const QString &arch)
-{
- if (arch == QLatin1String("armeabi-v7a") || arch == QLatin1String("armeabi"))
- return QLatin1String("arch-arm");
- if (arch == QLatin1String("arm64-v8a"))
- return QLatin1String("arch-arm64");
- return QLatin1String("arch-") + arch;
-}
-
AndroidDebugSupport::AndroidDebugSupport(RunControl *runControl, const QString &intentName)
: Debugger::DebuggerRunTool(runControl)
{
@@ -155,6 +146,8 @@ void AndroidDebugSupport::start()
setSymbolFile(target->activeBuildConfiguration()->buildDirectory().pathAppended("app_process"));
setSkipExecutableValidation(true);
setUseExtendedRemote(true);
+ QString devicePreferredAbi = AndroidManager::devicePreferredAbi(target);
+ setAbi(AndroidManager::androidAbi2Abi(devicePreferredAbi));
QUrl gdbServer;
gdbServer.setHost(QHostAddress(QHostAddress::LocalHost).toString());
gdbServer.setPort(m_runner->gdbServerPort().number());
@@ -165,10 +158,13 @@ void AndroidDebugSupport::start()
const int minimumNdk = qt ? qt->minimumNDK() : 0;
int sdkVersion = qMax(AndroidManager::minimumSDK(kit), minimumNdk);
+ // 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()
.pathAppended("platforms")
.pathAppended(QString("android-%1").arg(sdkVersion))
- .pathAppended(toNdkArch(AndroidManager::targetArch(target)));
+ .pathAppended(devicePreferredAbi);
setSysRoot(sysRoot);
qCDebug(androidDebugSupportLog) << "Sysroot: " << sysRoot;
}
diff --git a/src/plugins/android/androiddeployqtstep.cpp b/src/plugins/android/androiddeployqtstep.cpp
index 02f0ecda83..ab9a0745a6 100644
--- a/src/plugins/android/androiddeployqtstep.cpp
+++ b/src/plugins/android/androiddeployqtstep.cpp
@@ -110,9 +110,6 @@ public:
auto resetDefaultDevices = new QPushButton(this);
resetDefaultDevices->setText(AndroidDeployQtStep::tr("Reset Default Devices"));
- auto cleanLibsPushButton = new QPushButton(this);
- cleanLibsPushButton->setText(AndroidDeployQtStep::tr("Clean Temporary Libraries Directory on Device"));
-
auto installMinistroButton = new QPushButton(this);
installMinistroButton->setText(AndroidDeployQtStep::tr("Install Ministro from APK"));
@@ -126,10 +123,6 @@ public:
AndroidManager::installQASIPackage(step->target(), packagePath);
});
- connect(cleanLibsPushButton, &QAbstractButton::clicked, this, [step] {
- AndroidManager::cleanLibsOnDevice(step->target());
- });
-
connect(resetDefaultDevices, &QAbstractButton::clicked, this, [step] {
AndroidConfigurations::clearDefaultDevices(step->project());
});
@@ -140,7 +133,6 @@ public:
auto layout = new QVBoxLayout(this);
layout->addWidget(uninstallPreviousPackage);
layout->addWidget(resetDefaultDevices);
- layout->addWidget(cleanLibsPushButton);
layout->addWidget(installMinistroButton);
}
};
@@ -173,8 +165,8 @@ bool AndroidDeployQtStep::init()
{
m_androiddeployqtArgs = CommandLine();
- m_targetArch = AndroidManager::targetArch(target());
- if (m_targetArch.isEmpty()) {
+ m_androidABIs = AndroidManager::applicationAbis(target());
+ if (m_androidABIs.isEmpty()) {
emit addOutput(tr("No Android arch set by the .pro file."), OutputFormat::Stderr);
return false;
}
@@ -189,7 +181,7 @@ bool AndroidDeployQtStep::init()
auto androidBuildApkStep = AndroidBuildApkStep::findInBuild(bc);
int minTargetApi = AndroidManager::minimumSDK(target());
- qCDebug(deployStepLog) << "Target architecture:" << m_targetArch
+ qCDebug(deployStepLog) << "Target architecture:" << m_androidABIs
<< "Min target API" << minTargetApi;
// Try to re-use user-provided information from an earlier step of the same type.
@@ -202,7 +194,7 @@ bool AndroidDeployQtStep::init()
info = androidDeployQtStep->m_deviceInfo;
if (!info.isValid()) {
- info = AndroidConfigurations::showDeviceDialog(project(), minTargetApi, m_targetArch);
+ info = AndroidConfigurations::showDeviceDialog(project(), minTargetApi, m_androidABIs);
m_deviceInfo = info; // Keep around for later steps
}
@@ -218,6 +210,7 @@ bool AndroidDeployQtStep::init()
AndroidManager::setDeviceSerialNumber(target(), m_serialNumber);
AndroidManager::setDeviceApiLevel(target(), info.sdk);
+ AndroidManager::setDeviceAbis(target(), info.cpuAbi);
emit addOutput(tr("Deploying to %1").arg(m_serialNumber), OutputFormat::Stdout);
@@ -516,17 +509,11 @@ void AndroidDeployQtStep::gatherFilesToPull()
QString linkerName("linker");
QString libDirName("lib");
- if (m_deviceInfo.cpuAbi.contains(QLatin1String("arm64-v8a")) ||
- m_deviceInfo.cpuAbi.contains(QLatin1String("x86_64"))) {
- const Core::Id cxxLanguageId = ProjectExplorer::Constants::CXX_LANGUAGE_ID;
- ToolChain *tc = ToolChainKitAspect::toolChain(target()->kit(), cxxLanguageId);
- if (tc && tc->targetAbi().wordWidth() == 64) {
- m_filesToPull["/system/bin/app_process64"] = buildDir + "app_process";
- libDirName = "lib64";
- linkerName = "linker64";
- } else {
- m_filesToPull["/system/bin/app_process32"] = buildDir + "app_process";
- }
+ auto preferreABI = AndroidManager::devicePreferredAbi(target());
+ if (preferreABI == "arm64-v8a" || preferreABI == "x86_64") {
+ m_filesToPull["/system/bin/app_process64"] = buildDir + "app_process";
+ libDirName = "lib64";
+ linkerName = "linker64";
} else {
m_filesToPull["/system/bin/app_process32"] = buildDir + "app_process";
m_filesToPull["/system/bin/app_process"] = buildDir + "app_process";
diff --git a/src/plugins/android/androiddeployqtstep.h b/src/plugins/android/androiddeployqtstep.h
index ad3deda99f..6b0091d2ad 100644
--- a/src/plugins/android/androiddeployqtstep.h
+++ b/src/plugins/android/androiddeployqtstep.h
@@ -111,7 +111,7 @@ private:
Utils::FilePath m_apkPath;
QMap<QString, QString> m_filesToPull;
- QString m_targetArch;
+ QStringList m_androidABIs;
bool m_uninstallPreviousPackage = false;
bool m_uninstallPreviousPackageRun = false;
bool m_useAndroiddeployqt = false;
diff --git a/src/plugins/android/androiddevicedialog.cpp b/src/plugins/android/androiddevicedialog.cpp
index ce4505521a..cd8ae2f611 100644
--- a/src/plugins/android/androiddevicedialog.cpp
+++ b/src/plugins/android/androiddevicedialog.cpp
@@ -236,7 +236,7 @@ class AndroidDeviceModel : public QAbstractItemModel
{
Q_OBJECT
public:
- AndroidDeviceModel(int apiLevel, const QString &abi);
+ AndroidDeviceModel(int apiLevel, const QStringList &abis);
QModelIndex index(int row, int column,
const QModelIndex &parent = QModelIndex()) const override;
QModelIndex parent(const QModelIndex &child) const override;
@@ -251,7 +251,7 @@ public:
QModelIndex indexFor(AndroidDeviceInfo::AndroidDeviceType type, const QString &serial);
private:
int m_apiLevel;
- QString m_abi;
+ QStringList m_abis;
AndroidDeviceModelNode *m_root;
};
@@ -260,8 +260,8 @@ private:
/////////////////
// AndroidDeviceModel
/////////////////
-AndroidDeviceModel::AndroidDeviceModel(int apiLevel, const QString &abi)
- : m_apiLevel(apiLevel), m_abi(abi), m_root(nullptr)
+AndroidDeviceModel::AndroidDeviceModel(int apiLevel, const QStringList &abis)
+ : m_apiLevel(apiLevel), m_abis(abis), m_root(nullptr)
{
}
@@ -364,7 +364,7 @@ void AndroidDeviceModel::setDevices(const QVector<AndroidDeviceInfo> &devices)
}else if (device.state == AndroidDeviceInfo::OfflineState) {
error = AndroidDeviceDialog::tr("Offline. Please check the state of your device %1.")
.arg(device.serialNumber);
- } else if (!device.cpuAbi.contains(m_abi)) {
+ } else if (!AndroidManager::matchedAbis(device.cpuAbi, m_abis)) {
error = AndroidDeviceDialog::tr("ABI is incompatible, device supports ABIs: %1.")
.arg(device.cpuAbi.join(QLatin1Char(' ')));
} else if (device.sdk < m_apiLevel) {
@@ -413,13 +413,13 @@ static inline QString msgAdbListDevices()
return AndroidDeviceDialog::tr("<p>The adb tool in the Android SDK lists all connected devices if run via &quot;adb devices&quot;.</p>");
}
-AndroidDeviceDialog::AndroidDeviceDialog(int apiLevel, const QString &abi,
+AndroidDeviceDialog::AndroidDeviceDialog(int apiLevel, const QStringList &abis,
const QString &serialNumber, QWidget *parent) :
QDialog(parent),
- m_model(new AndroidDeviceModel(apiLevel, abi)),
+ m_model(new AndroidDeviceModel(apiLevel, abis)),
m_ui(new Ui::AndroidDeviceDialog),
m_apiLevel(apiLevel),
- m_abi(abi),
+ m_abis(abis),
m_defaultDevice(serialNumber),
m_avdManager(new AndroidAvdManager)
{
@@ -431,7 +431,7 @@ AndroidDeviceDialog::AndroidDeviceDialog(int apiLevel, const QString &abi,
m_ui->deviceView->setUniformRowHeights(true);
m_ui->deviceView->setExpandsOnDoubleClick(false);
- m_ui->defaultDeviceCheckBox->setText(tr("Always use this device for architecture %1 for this project").arg(abi));
+ m_ui->defaultDeviceCheckBox->setText(tr("Always use this device for this project"));
m_ui->noDeviceFoundLabel->setText(QLatin1String("<p align=\"center\"><span style=\" font-size:16pt;\">")
+ tr("No Device Found") + QLatin1String("</span></p><br/>")
@@ -578,7 +578,7 @@ void AndroidDeviceDialog::createAvd()
{
m_ui->createAVDButton->setEnabled(false);
CreateAvdInfo info = AvdDialog::gatherCreateAVDInfo(this, AndroidConfigurations::sdkManager(),
- m_apiLevel, m_abi);
+ m_apiLevel, m_abis);
if (!info.isValid()) {
m_ui->createAVDButton->setEnabled(true);
diff --git a/src/plugins/android/androiddevicedialog.h b/src/plugins/android/androiddevicedialog.h
index e366b18075..26011303c3 100644
--- a/src/plugins/android/androiddevicedialog.h
+++ b/src/plugins/android/androiddevicedialog.h
@@ -52,7 +52,7 @@ class AndroidDeviceDialog : public QDialog
Q_OBJECT
public:
- explicit AndroidDeviceDialog(int apiLevel, const QString &abi,
+ explicit AndroidDeviceDialog(int apiLevel, const QStringList &abis,
const QString &serialNumber, QWidget *parent = nullptr);
~AndroidDeviceDialog() override;
@@ -74,7 +74,7 @@ private:
Ui::AndroidDeviceDialog *m_ui;
Utils::ProgressIndicator *m_progressIndicator;
int m_apiLevel;
- QString m_abi;
+ QStringList m_abis;
QString m_avdNameFromAdd;
QString m_defaultDevice;
std::unique_ptr<AndroidAvdManager> m_avdManager;
diff --git a/src/plugins/android/androidgdbserverkitinformation.cpp b/src/plugins/android/androidgdbserverkitinformation.cpp
deleted file mode 100644
index e3ab975a8f..0000000000
--- a/src/plugins/android/androidgdbserverkitinformation.cpp
+++ /dev/null
@@ -1,217 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "androidgdbserverkitinformation.h"
-#include "androidconstants.h"
-#include "androidtoolchain.h"
-#include "androidconfigurations.h"
-
-#include <utils/pathchooser.h>
-#include <utils/elidinglabel.h>
-#include <utils/qtcassert.h>
-
-#include <QDialogButtonBox>
-#include <QLabel>
-#include <QPushButton>
-#include <QMenu>
-#include <QDialog>
-#include <QVBoxLayout>
-#include <QFormLayout>
-
-#include <projectexplorer/projectexplorerconstants.h>
-
-#include <qtsupport/baseqtversion.h>
-#include <qtsupport/qtkitinformation.h>
-
-using namespace ProjectExplorer;
-using namespace Utils;
-
-namespace Android {
-namespace Internal {
-
-class AndroidGdbServerKitAspectWidget : public KitAspectWidget
-{
- Q_DECLARE_TR_FUNCTIONS(Android::Internal::AndroidGdbServerKitAspect)
-public:
- AndroidGdbServerKitAspectWidget(Kit *kit, const KitAspect *ki);
- ~AndroidGdbServerKitAspectWidget() override;
-
- void makeReadOnly() override;
- void refresh() override;
-
- QWidget *mainWidget() const override;
- QWidget *buttonWidget() const override;
-
-private:
- void autoDetectDebugger();
- void showDialog();
-
- QLabel *m_label;
- QPushButton *m_button;
-};
-
-
-AndroidGdbServerKitAspect::AndroidGdbServerKitAspect()
-{
- setId(AndroidGdbServerKitAspect::id());
- setDisplayName(tr("Android GDB server"));
- setDescription(tr("The GDB server to use for this kit."));
- setPriority(27999); // Just one less than Debugger!
-}
-
-void AndroidGdbServerKitAspect::setup(Kit *kit)
-{
- if (kit && !kit->hasValue(id()))
- kit->setValue(id(), autoDetect(kit).toString());
-}
-
-Tasks AndroidGdbServerKitAspect::validate(const Kit *) const
-{
- return {};
-}
-
-bool AndroidGdbServerKitAspect::isApplicableToKit(const Kit *k) const
-{
- return DeviceKitAspect::deviceId(k) == Constants::ANDROID_DEVICE_ID;
-}
-
-KitAspect::ItemList AndroidGdbServerKitAspect::toUserOutput(const Kit *kit) const
-{
- return {{tr("GDB server"), AndroidGdbServerKitAspect::gdbServer(kit).toUserOutput()}};
-}
-
-KitAspectWidget *AndroidGdbServerKitAspect::createConfigWidget(Kit *kit) const
-{
- QTC_ASSERT(kit, return nullptr);
- return new AndroidGdbServerKitAspectWidget(kit, this);
-}
-
-Core::Id AndroidGdbServerKitAspect::id()
-{
- return "Android.GdbServer.Information";
-}
-
-FilePath AndroidGdbServerKitAspect::gdbServer(const Kit *kit)
-{
- QTC_ASSERT(kit, return FilePath());
- return FilePath::fromString(kit->value(AndroidGdbServerKitAspect::id()).toString());
-}
-
-void AndroidGdbServerKitAspect::setGdbSever(Kit *kit, const FilePath &gdbServerCommand)
-{
- QTC_ASSERT(kit, return);
- kit->setValue(AndroidGdbServerKitAspect::id(), gdbServerCommand.toString());
-}
-
-FilePath AndroidGdbServerKitAspect::autoDetect(const Kit *kit)
-{
- ToolChain *tc = ToolChainKitAspect::toolChain(kit, ProjectExplorer::Constants::CXX_LANGUAGE_ID);
- if (!tc || tc->typeId() != Constants::ANDROID_TOOLCHAIN_TYPEID)
- return FilePath();
- return AndroidConfigurations::currentConfig().gdbServer(tc->targetAbi());
-}
-
-///////////////
-// AndroidGdbServerKitAspectWidget
-///////////////
-
-
-AndroidGdbServerKitAspectWidget::AndroidGdbServerKitAspectWidget(Kit *kit, const KitAspect *ki) :
- KitAspectWidget(kit, ki),
- m_label(new ElidingLabel),
- m_button(new QPushButton(tr("Manage...")))
-{
- // ToolButton with Menu, defaulting to 'Autodetect'.
- auto buttonMenu = new QMenu(m_button);
- QAction *autoDetectAction = buttonMenu->addAction(tr("Auto-detect"));
- connect(autoDetectAction, &QAction::triggered,
- this, &AndroidGdbServerKitAspectWidget::autoDetectDebugger);
- QAction *changeAction = buttonMenu->addAction(tr("Edit..."));
- connect(changeAction, &QAction::triggered,
- this, &AndroidGdbServerKitAspectWidget::showDialog);
- m_button->setMenu(buttonMenu);
-
- refresh();
-}
-
-AndroidGdbServerKitAspectWidget::~AndroidGdbServerKitAspectWidget()
-{
- delete m_button;
- delete m_label;
-}
-
-void AndroidGdbServerKitAspectWidget::makeReadOnly()
-{
- m_button->setEnabled(false);
-}
-
-void AndroidGdbServerKitAspectWidget::refresh()
-{
- m_label->setText(AndroidGdbServerKitAspect::gdbServer(m_kit).toString());
-}
-
-QWidget *AndroidGdbServerKitAspectWidget::mainWidget() const
-{
- return m_label;
-}
-
-QWidget *AndroidGdbServerKitAspectWidget::buttonWidget() const
-{
- return m_button;
-}
-
-void AndroidGdbServerKitAspectWidget::autoDetectDebugger()
-{
- AndroidGdbServerKitAspect::setGdbSever(m_kit, AndroidGdbServerKitAspect::autoDetect(m_kit));
-}
-
-void AndroidGdbServerKitAspectWidget::showDialog()
-{
- QDialog dialog;
- auto layout = new QVBoxLayout(&dialog);
- auto formLayout = new QFormLayout;
- formLayout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
-
- auto binaryLabel = new QLabel(tr("&Binary:"));
- auto chooser = new PathChooser;
- chooser->setExpectedKind(PathChooser::ExistingCommand);
- chooser->setPath(AndroidGdbServerKitAspect::gdbServer(m_kit).toString());
- binaryLabel->setBuddy(chooser);
- formLayout->addRow(binaryLabel, chooser);
- layout->addLayout(formLayout);
-
- auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, &dialog);
- connect(buttonBox, &QDialogButtonBox::accepted, &dialog, &QDialog::accept);
- connect(buttonBox, &QDialogButtonBox::rejected, &dialog, &QDialog::reject);
- layout->addWidget(buttonBox);
-
- dialog.setWindowTitle(tr("GDB Server for \"%1\"").arg(m_kit->displayName()));
-
- if (dialog.exec() == QDialog::Accepted)
- AndroidGdbServerKitAspect::setGdbSever(m_kit, chooser->fileName());
-}
-
-} // namespace Internal
-} // namespace Android
diff --git a/src/plugins/android/androidgdbserverkitinformation.h b/src/plugins/android/androidgdbserverkitinformation.h
deleted file mode 100644
index db4f349344..0000000000
--- a/src/plugins/android/androidgdbserverkitinformation.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <projectexplorer/kitinformation.h>
-
-namespace Android {
-namespace Internal {
-
-class AndroidGdbServerKitAspect : public ProjectExplorer::KitAspect
-{
- Q_OBJECT
-public:
- AndroidGdbServerKitAspect();
-
- void setup(ProjectExplorer::Kit *) override;
- ProjectExplorer::Tasks validate(const ProjectExplorer::Kit *) const override;
- bool isApplicableToKit(const ProjectExplorer::Kit *k) const override;
- ItemList toUserOutput(const ProjectExplorer::Kit *) const override;
-
- ProjectExplorer::KitAspectWidget *createConfigWidget(ProjectExplorer::Kit *) const override;
-
- static Core::Id id();
- static Utils::FilePath gdbServer(const ProjectExplorer::Kit *kit);
- static void setGdbSever(ProjectExplorer::Kit *kit, const Utils::FilePath &gdbServerCommand);
- static Utils::FilePath autoDetect(const ProjectExplorer::Kit *kit);
-};
-
-} // namespace Internal
-} // namespace Android
diff --git a/src/plugins/android/androidmanager.cpp b/src/plugins/android/androidmanager.cpp
index 4b2a4ea3d6..2ce27e5d26 100644
--- a/src/plugins/android/androidmanager.cpp
+++ b/src/plugins/android/androidmanager.cpp
@@ -70,6 +70,7 @@ namespace {
const QLatin1String AndroidManifestName("AndroidManifest.xml");
const QLatin1String AndroidDefaultPropertiesName("project.properties");
const QLatin1String AndroidDeviceSn("AndroidDeviceSerialNumber");
+ const QLatin1String AndroidDeviceAbis("AndroidDeviceAbis");
const QLatin1String ApiLevelKey("AndroidVersion.ApiLevel");
const QString packageNameRegEx("(?<token>package: )(.*?)(name=)'(?<target>.*?)'");
const QString activityRegEx("(?<token>launchable-activity: )(.*?)(name=)'(?<target>.*?)'");
@@ -258,10 +259,10 @@ QString AndroidManager::buildTargetSDK(ProjectExplorer::Target *target)
return fallback;
}
-QString AndroidManager::targetArch(const Target *target)
+QStringList AndroidManager::applicationAbis(const Target *target)
{
auto qt = static_cast<AndroidQtVersion *>(QtSupport::QtKitAspect::qtVersion(target->kit()));
- return qt->targetArch();
+ return qt->androidAbis();
}
QJsonObject AndroidManager::deploymentSettings(const Target *target)
@@ -274,21 +275,15 @@ QJsonObject AndroidManager::deploymentSettings(const Target *target)
if (!tc || tc->typeId() != Constants::ANDROID_TOOLCHAIN_TYPEID)
return {};
QJsonObject settings;
- settings["description"] = "This file is generated by QtCreator to be read by androiddeployqt and should not be modified by hand.";
+ settings["_description"] = "This file is generated by QtCreator to be read by androiddeployqt and should not be modified by hand.";
settings["qt"] = qt->qmakeProperty("QT_INSTALL_PREFIX");
settings["ndk"] = AndroidConfigurations::currentConfig().ndkLocation().toString();
settings["sdk"] = AndroidConfigurations::currentConfig().sdkLocation().toString();
- settings["sdkBuildToolsRevision"] = AndroidConfigurations::currentConfig().buildToolsVersion().toString();
- settings["application-binary"] = target->activeRunConfiguration()->buildTargetInfo().targetFilePath.toString();
- settings["target-architecture"] = targetArch(target);
+ settings["stdcpp-path"] = AndroidConfigurations::currentConfig().toolchainPath().pathAppended("sysroot/usr/lib/").toString();
settings["toolchain-prefix"] = "llvm";
settings["tool-prefix"] = "llvm";
settings["useLLVM"] = true;
settings["ndk-host"] = AndroidConfigurations::currentConfig().toolchainHost();
- settings["stdcpp-path"] = AndroidConfigurations::currentConfig().ndkLocation()
- .pathAppended("/sources/cxx-stl/llvm-libc++/libs/"
- + targetArch(target)
- + "/libc++_shared.so").toString();
return settings;
}
@@ -316,6 +311,75 @@ Utils::FilePath AndroidManager::apkPath(const ProjectExplorer::Target *target)
return dirPath(target).pathAppended(apkPath);
}
+FilePath AndroidManager::aabPath(const Target *target)
+{
+ QTC_ASSERT(target, return Utils::FilePath());
+
+ auto buildApkStep = AndroidBuildApkStep::findInBuild(target->activeBuildConfiguration());
+ if (!buildApkStep)
+ return Utils::FilePath();
+
+ QString buildType;
+ if (buildApkStep->buildConfiguration()->buildType() == BuildConfiguration::Release)
+ buildType = "release";
+ else
+ buildType = "debug";
+ return dirPath(target).pathAppended(QString("build/outputs/bundle/%1/android-build-%1.aab").arg(buildType));
+}
+
+bool AndroidManager::matchedAbis(const QStringList &deviceAbis, const QStringList &appAbis)
+{
+ for (const auto &abi : appAbis) {
+ if (deviceAbis.contains(abi))
+ return true;
+ }
+ return false;
+}
+
+QString AndroidManager::devicePreferredAbi(const QStringList &deviceAbis, const QStringList &appAbis)
+{
+ for (const auto &abi : appAbis) {
+ if (deviceAbis.contains(abi))
+ return abi;
+ }
+ return {};
+}
+
+Abi AndroidManager::androidAbi2Abi(const QString &androidAbi)
+{
+ if (androidAbi == "arm64-v8a") {
+ return Abi{Abi::Architecture::ArmArchitecture,
+ Abi::OS::LinuxOS,
+ Abi::OSFlavor::AndroidLinuxFlavor,
+ Abi::BinaryFormat::ElfFormat,
+ 64, androidAbi};
+ } else if (androidAbi == "armeabi-v7a") {
+ return Abi{Abi::Architecture::ArmArchitecture,
+ Abi::OS::LinuxOS,
+ Abi::OSFlavor::AndroidLinuxFlavor,
+ Abi::BinaryFormat::ElfFormat,
+ 32, androidAbi};
+ } else if (androidAbi == "x86_64") {
+ return Abi{Abi::Architecture::X86Architecture,
+ Abi::OS::LinuxOS,
+ Abi::OSFlavor::AndroidLinuxFlavor,
+ Abi::BinaryFormat::ElfFormat,
+ 64, androidAbi};
+ } else if (androidAbi == "x86") {
+ return Abi{Abi::Architecture::X86Architecture,
+ Abi::OS::LinuxOS,
+ Abi::OSFlavor::AndroidLinuxFlavor,
+ Abi::BinaryFormat::ElfFormat,
+ 32, androidAbi};
+ } else {
+ return Abi{Abi::Architecture::UnknownArchitecture,
+ Abi::OS::LinuxOS,
+ Abi::OSFlavor::AndroidLinuxFlavor,
+ Abi::BinaryFormat::ElfFormat,
+ 0, androidAbi};
+ }
+}
+
Utils::FilePath AndroidManager::manifestSourcePath(ProjectExplorer::Target *target)
{
if (const ProjectNode *node = currentProjectNode(target)) {
@@ -360,6 +424,22 @@ void AndroidManager::setDeviceSerialNumber(ProjectExplorer::Target *target, cons
target->setNamedSettings(AndroidDeviceSn, deviceSerialNumber);
}
+QString AndroidManager::devicePreferredAbi(Target *target)
+{
+ auto appAbis = applicationAbis(target);
+ const auto deviceAbis = target->namedSettings(AndroidDeviceAbis).toStringList();
+ for (const auto &abi : deviceAbis) {
+ if (appAbis.contains(abi))
+ return abi;
+ }
+ return {};
+}
+
+void AndroidManager::setDeviceAbis(ProjectExplorer::Target *target, const QStringList &deviceAbis)
+{
+ target->setNamedSettings(AndroidDeviceAbis, deviceAbis);
+}
+
int AndroidManager::deviceApiLevel(ProjectExplorer::Target *target)
{
return target->namedSettings(ApiLevelKey).toInt();
@@ -474,39 +554,13 @@ static int parseMinSdk(const QDomElement &manifestElem)
return 0;
}
-void AndroidManager::cleanLibsOnDevice(ProjectExplorer::Target *target)
-{
- const QString targetArch = AndroidManager::targetArch(target);
- if (targetArch.isEmpty())
- return;
- const int deviceAPILevel = AndroidManager::minimumSDK(target);
- AndroidDeviceInfo info = AndroidConfigurations::showDeviceDialog(target->project(), deviceAPILevel, targetArch);
- if (!info.isValid()) // aborted
- return;
-
- QString deviceSerialNumber = info.serialNumber;
-
- if (info.type == AndroidDeviceInfo::Emulator) {
- deviceSerialNumber = AndroidAvdManager().startAvd(info.avdname);
- if (deviceSerialNumber.isEmpty())
- Core::MessageManager::write(tr("Starting Android virtual device failed."));
- }
-
- QStringList arguments = AndroidDeviceInfo::adbSelector(deviceSerialNumber);
- arguments << "shell" << "rm" << "-r" << "/data/local/tmp/qt";
-
- QString error;
- if (!runAdbCommandDetached(arguments, &error))
- Core::MessageManager::write(tr("Cleaning Qt libraries on device failed.\n%1").arg(error));
-}
-
void AndroidManager::installQASIPackage(ProjectExplorer::Target *target, const QString &packagePath)
{
- const QString targetArch = AndroidManager::targetArch(target);
- if (targetArch.isEmpty())
+ const QStringList appAbis = AndroidManager::applicationAbis(target);
+ if (appAbis.isEmpty())
return;
const int deviceAPILevel = AndroidManager::minimumSDK(target);
- AndroidDeviceInfo info = AndroidConfigurations::showDeviceDialog(target->project(), deviceAPILevel, targetArch);
+ AndroidDeviceInfo info = AndroidConfigurations::showDeviceDialog(target->project(), deviceAPILevel, appAbis);
if (!info.isValid()) // aborted
return;
diff --git a/src/plugins/android/androidmanager.h b/src/plugins/android/androidmanager.h
index c42550d4cf..73e0fa79cb 100644
--- a/src/plugins/android/androidmanager.h
+++ b/src/plugins/android/androidmanager.h
@@ -31,6 +31,8 @@
#include <QObject>
#include <QVersionNumber>
+#include <projectexplorer/abi.h>
+
QT_BEGIN_NAMESPACE
class QProcess;
QT_END_NAMESPACE
@@ -82,6 +84,9 @@ public:
static QString deviceSerialNumber(ProjectExplorer::Target *target);
static void setDeviceSerialNumber(ProjectExplorer::Target *target, const QString &deviceSerialNumber);
+ static QString devicePreferredAbi(ProjectExplorer::Target *target);
+ static void setDeviceAbis(ProjectExplorer::Target *target, const QStringList &deviceAbis);
+
static int deviceApiLevel(ProjectExplorer::Target *target);
static void setDeviceApiLevel(ProjectExplorer::Target *target, int level);
@@ -90,7 +95,7 @@ public:
static int minimumSDK(ProjectExplorer::Target *target);
static int minimumSDK(const ProjectExplorer::Kit *kit);
- static QString targetArch(const ProjectExplorer::Target *target);
+ static QStringList applicationAbis(const ProjectExplorer::Target *target);
static Utils::FilePath dirPath(const ProjectExplorer::Target *target);
static Utils::FilePath manifestPath(ProjectExplorer::Target *target);
@@ -98,11 +103,14 @@ public:
static Utils::FilePath manifestSourcePath(ProjectExplorer::Target *target);
static Utils::FilePath defaultPropertiesPath(ProjectExplorer::Target *target);
static Utils::FilePath apkPath(const ProjectExplorer::Target *target);
+ static Utils::FilePath aabPath(const ProjectExplorer::Target *target);
+ static bool matchedAbis(const QStringList &deviceAbis, const QStringList &appAbis);
+ static QString devicePreferredAbi(const QStringList &deviceAbis, const QStringList &appAbis);
+ static ProjectExplorer::Abi androidAbi2Abi(const QString &androidAbi);
static QPair<int, int> apiLevelRange();
static QString androidNameForApiLevel(int x);
- static void cleanLibsOnDevice(ProjectExplorer::Target *target);
static void installQASIPackage(ProjectExplorer::Target *target, const QString &packagePath);
static bool checkKeystorePassword(const QString &keystorePath, const QString &keystorePasswd);
diff --git a/src/plugins/android/androidplugin.cpp b/src/plugins/android/androidplugin.cpp
index 0b136da7c7..d8225eebae 100644
--- a/src/plugins/android/androidplugin.cpp
+++ b/src/plugins/android/androidplugin.cpp
@@ -30,7 +30,6 @@
#include "androiddebugsupport.h"
#include "androiddeployqtstep.h"
#include "androiddevice.h"
-#include "androidgdbserverkitinformation.h"
#include "androidmanager.h"
#include "androidmanifesteditorfactory.h"
#include "androidpackageinstallationstep.h"
@@ -168,7 +167,6 @@ public:
};
AndroidBuildApkStepFactory buildApkStepFactory;
- AndroidGdbServerKitAspect gdbServerKitAspect;
};
AndroidPlugin::~AndroidPlugin()
diff --git a/src/plugins/android/androidqtversion.cpp b/src/plugins/android/androidqtversion.cpp
index eff95c3f04..4b1696ee78 100644
--- a/src/plugins/android/androidqtversion.cpp
+++ b/src/plugins/android/androidqtversion.cpp
@@ -71,14 +71,42 @@ QString AndroidQtVersion::invalidReason() const
Abis AndroidQtVersion::detectQtAbis() const
{
- Abis abis = BaseQtVersion::detectQtAbis();
- for (int i = 0; i < abis.count(); ++i) {
- abis[i] = Abi(abis.at(i).architecture(),
- abis.at(i).os(),
- Abi::AndroidLinuxFlavor,
- abis.at(i).binaryFormat(),
- abis.at(i).wordWidth());
- }
+ auto androidAbi2Abi = [](const QString &androidAbi) {
+ if (androidAbi == "arm64-v8a") {
+ return Abi{Abi::Architecture::ArmArchitecture,
+ Abi::OS::LinuxOS,
+ Abi::OSFlavor::AndroidLinuxFlavor,
+ Abi::BinaryFormat::ElfFormat,
+ 64, androidAbi};
+ } else if (androidAbi == "armeabi-v7a") {
+ return Abi{Abi::Architecture::ArmArchitecture,
+ Abi::OS::LinuxOS,
+ Abi::OSFlavor::AndroidLinuxFlavor,
+ Abi::BinaryFormat::ElfFormat,
+ 32, androidAbi};
+ } else if (androidAbi == "x86_64") {
+ return Abi{Abi::Architecture::X86Architecture,
+ Abi::OS::LinuxOS,
+ Abi::OSFlavor::AndroidLinuxFlavor,
+ Abi::BinaryFormat::ElfFormat,
+ 64, androidAbi};
+ } else if (androidAbi == "x86") {
+ return Abi{Abi::Architecture::X86Architecture,
+ Abi::OS::LinuxOS,
+ Abi::OSFlavor::AndroidLinuxFlavor,
+ Abi::BinaryFormat::ElfFormat,
+ 32, androidAbi};
+ } else {
+ return Abi{Abi::Architecture::UnknownArchitecture,
+ Abi::OS::LinuxOS,
+ Abi::OSFlavor::AndroidLinuxFlavor,
+ Abi::BinaryFormat::ElfFormat,
+ 0, androidAbi};
+ }
+ };
+ Abis abis;
+ for (const auto &abi : androidAbis())
+ abis << androidAbi2Abi(abi);
return abis;
}
@@ -105,10 +133,10 @@ QString AndroidQtVersion::description() const
return tr("Android");
}
-QString AndroidQtVersion::targetArch() const
+const QStringList &AndroidQtVersion::androidAbis() const
{
ensureMkSpecParsed();
- return m_targetArch;
+ return m_androidAbis;
}
int AndroidQtVersion::minimumNDK() const
@@ -119,8 +147,11 @@ int AndroidQtVersion::minimumNDK() const
void AndroidQtVersion::parseMkSpec(ProFileEvaluator *evaluator) const
{
- m_targetArch = evaluator->value(QLatin1String("ANDROID_TARGET_ARCH"));
- const QString androidPlatform = evaluator->value(QLatin1String("ANDROID_PLATFORM"));
+ if (qtVersion() >= QtSupport::QtVersionNumber{5, 14})
+ m_androidAbis = evaluator->values("ALL_ANDROID_ABIS");
+ else
+ m_androidAbis = QStringList{evaluator->value("ANDROID_TARGET_ARCH")};
+ const QString androidPlatform = evaluator->value("ANDROID_PLATFORM");
if (!androidPlatform.isEmpty()) {
const QRegExp regex("android-(\\d+)");
if (regex.exactMatch(androidPlatform)) {
diff --git a/src/plugins/android/androidqtversion.h b/src/plugins/android/androidqtversion.h
index 519d702ead..c986960819 100644
--- a/src/plugins/android/androidqtversion.h
+++ b/src/plugins/android/androidqtversion.h
@@ -52,13 +52,13 @@ public:
QSet<Core::Id> targetDeviceTypes() const override;
QString description() const override;
- QString targetArch() const;
+ const QStringList &androidAbis() const;
int minimumNDK() const;
protected:
void parseMkSpec(ProFileEvaluator *) const override;
private:
- mutable QString m_targetArch;
+ mutable QStringList m_androidAbis;
mutable int m_minNdk = -1;
};
diff --git a/src/plugins/android/androidrunner.cpp b/src/plugins/android/androidrunner.cpp
index ed8fe5ace7..257b40cadd 100644
--- a/src/plugins/android/androidrunner.cpp
+++ b/src/plugins/android/androidrunner.cpp
@@ -246,11 +246,11 @@ void AndroidRunner::launchAVD()
return;
int deviceAPILevel = AndroidManager::minimumSDK(m_target);
- QString targetArch = AndroidManager::targetArch(m_target);
+ QStringList androidAbis = AndroidManager::applicationAbis(m_target);
// Get AVD info.
AndroidDeviceInfo info = AndroidConfigurations::showDeviceDialog(
- m_target->project(), deviceAPILevel, targetArch);
+ m_target->project(), deviceAPILevel, androidAbis);
AndroidManager::setDeviceSerialNumber(m_target, info.serialNumber);
emit androidDeviceInfoChanged(info);
if (info.isValid()) {
diff --git a/src/plugins/android/androidrunnerworker.cpp b/src/plugins/android/androidrunnerworker.cpp
index f3c9a3ac9f..96508910e6 100644
--- a/src/plugins/android/androidrunnerworker.cpp
+++ b/src/plugins/android/androidrunnerworker.cpp
@@ -29,7 +29,6 @@
#include "androidconstants.h"
#include "androidmanager.h"
#include "androidrunconfiguration.h"
-#include "androidgdbserverkitinformation.h"
#include <debugger/debuggerrunconfigurationaspect.h>
@@ -226,7 +225,7 @@ AndroidRunnerWorker::AndroidRunnerWorker(RunWorker *runner, const QString &packa
<< "Extra Start Args:" << m_amStartExtraArgs
<< "Before Start ADB cmds:" << m_beforeStartAdbCommands
<< "After finish ADB cmds:" << m_afterFinishAdbCommands;
- m_gdbserverPath = AndroidGdbServerKitAspect::gdbServer(target->kit()).toString();
+ m_gdbserverPath = AndroidConfigurations::instance()->currentConfig().gdbServer(AndroidManager::devicePreferredAbi(target)).toString();
QtSupport::BaseQtVersion *version = QtSupport::QtKitAspect::qtVersion(target->kit());
m_useAppParamsForQmlDebugger = version->qtVersion() >= QtSupport::QtVersionNumber(5, 12);
}
diff --git a/src/plugins/android/avddialog.cpp b/src/plugins/android/avddialog.cpp
index c0f692734c..29f60b506f 100644
--- a/src/plugins/android/avddialog.cpp
+++ b/src/plugins/android/avddialog.cpp
@@ -38,7 +38,7 @@
using namespace Android;
using namespace Android::Internal;
-AvdDialog::AvdDialog(int minApiLevel, AndroidSdkManager *sdkManager, const QString &targetArch,
+AvdDialog::AvdDialog(int minApiLevel, AndroidSdkManager *sdkManager, const QStringList &abis,
QWidget *parent) :
QDialog(parent),
m_sdkManager(sdkManager),
@@ -50,11 +50,11 @@ AvdDialog::AvdDialog(int minApiLevel, AndroidSdkManager *sdkManager, const QStri
m_hideTipTimer.setInterval(2000);
m_hideTipTimer.setSingleShot(true);
- if (targetArch.isEmpty()) {
+ if (abis.isEmpty()) {
m_avdDialog.abiComboBox->addItems(QStringList({"armeabi-v7a", "armeabi", "x86",
"arm64-v8a", "x86_64"}));
} else {
- m_avdDialog.abiComboBox->addItems(QStringList(targetArch));
+ m_avdDialog.abiComboBox->addItems(abis);
}
auto v = new QRegExpValidator(m_allowedNameChars, this);
@@ -79,10 +79,10 @@ bool AvdDialog::isValid() const
}
CreateAvdInfo AvdDialog::gatherCreateAVDInfo(QWidget *parent, AndroidSdkManager *sdkManager,
- int minApiLevel, QString targetArch)
+ int minApiLevel, const QStringList &abis)
{
CreateAvdInfo result;
- AvdDialog d(minApiLevel, sdkManager, targetArch, parent);
+ AvdDialog d(minApiLevel, sdkManager, abis, parent);
if (d.exec() != QDialog::Accepted || !d.isValid())
return result;
diff --git a/src/plugins/android/avddialog.h b/src/plugins/android/avddialog.h
index d0e3fe0324..6f32cd43a6 100644
--- a/src/plugins/android/avddialog.h
+++ b/src/plugins/android/avddialog.h
@@ -40,7 +40,7 @@ class AvdDialog : public QDialog
{
Q_OBJECT
public:
- explicit AvdDialog(int minApiLevel, AndroidSdkManager *sdkManager, const QString &targetArch,
+ explicit AvdDialog(int minApiLevel, AndroidSdkManager *sdkManager, const QStringList &abis,
QWidget *parent = nullptr);
const SdkPlatform *sdkPlatform() const;
@@ -49,7 +49,7 @@ public:
int sdcardSize() const;
bool isValid() const;
static CreateAvdInfo gatherCreateAVDInfo(QWidget *parent, AndroidSdkManager *sdkManager,
- int minApiLevel = 0, QString targetArch = QString());
+ int minApiLevel = 0, const QStringList &abis = {});
private:
void updateApiLevelComboBox();