diff options
author | BogDan Vatra <bogdan@kde.org> | 2019-08-26 14:19:07 +0300 |
---|---|---|
committer | BogDan Vatra <bogdan@kdab.com> | 2019-09-16 07:34:54 +0000 |
commit | 6b31f9cf23cac79c10a9871961e3de79be657b38 (patch) | |
tree | 00098f39b2ac1698324bcfb79364ffac8574b397 /src/plugins/android | |
parent | 567a20843ff1024725eac26440e03b05b1f06b4d (diff) | |
download | qt-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')
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 "adb devices".</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(); |