forked from qt-creator/qt-creator
Android multi arch support
[ChangeLog][Android] Android multi arch support for qmake Change-Id: Ib8b1874604a3392130c96fbc00b26713b3d788ae Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
committed by
BogDan Vatra
parent
567a20843f
commit
6b31f9cf23
@@ -20,7 +20,8 @@ find_package(Qt5 COMPONENTS Core Quick REQUIRED)
|
||||
@endif
|
||||
|
||||
if(ANDROID)
|
||||
add_library(%{ProjectName} SHARED
|
||||
set(TARGET %{ProjectName}_${ANDROID_ABI})
|
||||
add_library(${TARGET} SHARED
|
||||
%{MainCppFileName}
|
||||
qml.qrc
|
||||
@if %{HasTranslation}
|
||||
@@ -28,7 +29,8 @@ if(ANDROID)
|
||||
@endif
|
||||
)
|
||||
else()
|
||||
add_executable(%{ProjectName}
|
||||
set(TARGET %{ProjectName})
|
||||
add_executable(${TARGET}
|
||||
%{MainCppFileName}
|
||||
qml.qrc
|
||||
@if %{HasTranslation}
|
||||
@@ -37,9 +39,9 @@ else()
|
||||
)
|
||||
endif()
|
||||
|
||||
target_compile_definitions(%{ProjectName}
|
||||
target_compile_definitions(${TARGET}
|
||||
PRIVATE $<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:QT_QML_DEBUG>)
|
||||
target_link_libraries(%{ProjectName}
|
||||
target_link_libraries(${TARGET}
|
||||
PRIVATE Qt5::Core Qt5::Quick)
|
||||
@if %{HasTranslation}
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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 \
|
||||
|
@@ -49,8 +49,6 @@ Project {
|
||||
"androiderrormessage.cpp",
|
||||
"androidextralibrarylistmodel.cpp",
|
||||
"androidextralibrarylistmodel.h",
|
||||
"androidgdbserverkitinformation.cpp",
|
||||
"androidgdbserverkitinformation.h",
|
||||
"androidglobal.h",
|
||||
"androidmanager.cpp",
|
||||
"androidmanager.h",
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
|
@@ -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());
|
||||
|
@@ -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);
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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";
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
|
@@ -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
|
@@ -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
|
@@ -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;
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -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()
|
||||
|
@@ -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)) {
|
||||
|
@@ -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;
|
||||
};
|
||||
|
||||
|
@@ -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()) {
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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();
|
||||
|
@@ -196,10 +196,21 @@ void CMakeBuildConfiguration::initialize()
|
||||
CMakeProjectManager::CMakeConfigItem::Type::PATH,
|
||||
"Android CMake toolchain file",
|
||||
ndkLocation.pathAppended("build/cmake/android.toolchain.cmake").toUserOutput().toUtf8()});
|
||||
auto androidAbis = bs->data(Android::Constants::AndroidABIs).toStringList();
|
||||
QString preferredAbi;
|
||||
if (androidAbis.contains("arm64-v8a")) {
|
||||
preferredAbi = "arm64-v8a";
|
||||
} else if (androidAbis.isEmpty() || androidAbis.contains("armeabi-v7a")) {
|
||||
preferredAbi = "armeabi-v7a";
|
||||
} else {
|
||||
preferredAbi = androidAbis.first();
|
||||
}
|
||||
// FIXME: configmodel doesn't care about our androidAbis list...
|
||||
m_initialConfiguration.prepend(CMakeProjectManager::CMakeConfigItem{"ANDROID_ABI",
|
||||
CMakeProjectManager::CMakeConfigItem::Type::STRING,
|
||||
"Android ABI",
|
||||
bs->data(Android::Constants::AndroidABI).toString().toUtf8()});
|
||||
preferredAbi.toLatin1(),
|
||||
androidAbis});
|
||||
m_initialConfiguration.prepend(CMakeProjectManager::CMakeConfigItem{"ANDROID_STL",
|
||||
CMakeProjectManager::CMakeConfigItem::Type::STRING,
|
||||
"Android STL",
|
||||
|
@@ -43,8 +43,9 @@ namespace CMakeProjectManager {
|
||||
CMakeConfigItem::CMakeConfigItem() = default;
|
||||
|
||||
CMakeConfigItem::CMakeConfigItem(const QByteArray &k, Type t,
|
||||
const QByteArray &d, const QByteArray &v) :
|
||||
key(k), type(t), value(v), documentation(d)
|
||||
const QByteArray &d, const QByteArray &v,
|
||||
const QStringList &s) :
|
||||
key(k), type(t), value(v), documentation(d), values(s)
|
||||
{ }
|
||||
|
||||
CMakeConfigItem::CMakeConfigItem(const QByteArray &k, const QByteArray &v) :
|
||||
|
@@ -44,7 +44,7 @@ class CMakeConfigItem {
|
||||
public:
|
||||
enum Type { FILEPATH, PATH, BOOL, STRING, INTERNAL, STATIC };
|
||||
CMakeConfigItem();
|
||||
CMakeConfigItem(const QByteArray &k, Type t, const QByteArray &d, const QByteArray &v);
|
||||
CMakeConfigItem(const QByteArray &k, Type t, const QByteArray &d, const QByteArray &v, const QStringList &s = {});
|
||||
CMakeConfigItem(const QByteArray &k, const QByteArray &v);
|
||||
|
||||
static QByteArray valueOf(const QByteArray &key, const QList<CMakeConfigItem> &input);
|
||||
|
@@ -445,6 +445,11 @@ void DebuggerRunTool::setOverrideStartScript(const QString &script)
|
||||
m_runParameters.overrideStartScript = script;
|
||||
}
|
||||
|
||||
void DebuggerRunTool::setAbi(const Abi &abi)
|
||||
{
|
||||
m_runParameters.toolChainAbi = abi;
|
||||
}
|
||||
|
||||
void DebuggerRunTool::setInferior(const Runnable &runnable)
|
||||
{
|
||||
m_runParameters.inferior = runnable;
|
||||
|
@@ -122,6 +122,8 @@ public:
|
||||
void setTestCase(int testCase);
|
||||
void setOverrideStartScript(const QString &script);
|
||||
|
||||
void setAbi(const ProjectExplorer::Abi &abi);
|
||||
|
||||
Internal::TerminalRunner *terminalRunner() const;
|
||||
|
||||
private:
|
||||
|
@@ -443,8 +443,8 @@ static Abis abiOf(const QByteArray &data)
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
Abi::Abi(const Architecture &a, const OS &o,
|
||||
const OSFlavor &of, const BinaryFormat &f, unsigned char w) :
|
||||
m_architecture(a), m_os(o), m_osFlavor(of), m_binaryFormat(f), m_wordWidth(w)
|
||||
const OSFlavor &of, const BinaryFormat &f, unsigned char w, const QString &p) :
|
||||
m_architecture(a), m_os(o), m_osFlavor(of), m_binaryFormat(f), m_wordWidth(w), m_param(p)
|
||||
{
|
||||
QTC_ASSERT(osSupportsFlavor(o, of), m_osFlavor = UnknownFlavor);
|
||||
}
|
||||
@@ -601,6 +601,13 @@ QString Abi::toString() const
|
||||
return dn.join('-');
|
||||
}
|
||||
|
||||
QString Abi::param() const
|
||||
{
|
||||
if (m_param.isEmpty())
|
||||
return toString();
|
||||
return m_param;
|
||||
}
|
||||
|
||||
bool Abi::operator != (const Abi &other) const
|
||||
{
|
||||
return !operator ==(other);
|
||||
|
@@ -123,7 +123,7 @@ public:
|
||||
|
||||
Abi(const Architecture &a = UnknownArchitecture, const OS &o = UnknownOS,
|
||||
const OSFlavor &so = UnknownFlavor, const BinaryFormat &f = UnknownFormat,
|
||||
unsigned char w = 0);
|
||||
unsigned char w = 0, const QString &p = {});
|
||||
|
||||
static Abi abiFromTargetTriplet(const QString &machineTriple);
|
||||
|
||||
@@ -143,6 +143,7 @@ public:
|
||||
unsigned char wordWidth() const { return m_wordWidth; }
|
||||
|
||||
QString toString() const;
|
||||
QString param() const;
|
||||
|
||||
static QString toString(const Architecture &a);
|
||||
static QString toString(const OS &o);
|
||||
@@ -173,6 +174,7 @@ private:
|
||||
OSFlavor m_osFlavor;
|
||||
BinaryFormat m_binaryFormat;
|
||||
unsigned char m_wordWidth;
|
||||
QString m_param;
|
||||
};
|
||||
|
||||
inline int qHash(const ProjectExplorer::Abi &abi)
|
||||
|
@@ -45,6 +45,8 @@
|
||||
|
||||
#include <android/androidconstants.h>
|
||||
#include <ios/iosconstants.h>
|
||||
#include <qtsupport/baseqtversion.h>
|
||||
#include <qtsupport/qtkitinformation.h>
|
||||
#include <winrt/winrtconstants.h>
|
||||
|
||||
#include <QDir>
|
||||
@@ -293,6 +295,18 @@ QVariantMap DefaultPropertyProvider::autoGeneratedProperties(const ProjectExplor
|
||||
data.insert("Android.ndk.ndkDir", ndkDir);
|
||||
}
|
||||
}
|
||||
data.remove(QBS_ARCHITECTURES);
|
||||
data.remove(QBS_ARCHITECTURE);
|
||||
QtSupport::BaseQtVersion *qtVersion = QtSupport::QtKitAspect::qtVersion(k);
|
||||
if (qtVersion) {
|
||||
QStringList abis;
|
||||
for (const auto &abi : qtVersion->qtAbis())
|
||||
abis << abi.param();
|
||||
if (abis.size() == 1)
|
||||
data.insert(QLatin1String(QBS_ARCHITECTURE), abis.first());
|
||||
else
|
||||
data.insert(QLatin1String(QBS_ARCHITECTURES), abis);
|
||||
}
|
||||
} else {
|
||||
Utils::FilePath cCompilerPath;
|
||||
if (tcC)
|
||||
|
@@ -596,6 +596,7 @@ QMakeStepConfigWidget::QMakeStepConfigWidget(QMakeStep *step)
|
||||
connect(step->qmakeBuildConfiguration(), &QmakeBuildConfiguration::qmakeBuildConfigurationChanged,
|
||||
this, &QMakeStepConfigWidget::qmakeBuildConfigChanged);
|
||||
connect(step->target(), &Target::kitChanged, this, &QMakeStepConfigWidget::qtVersionChanged);
|
||||
connect(m_ui->abisListWidget, &QListWidget::itemChanged, this, &QMakeStepConfigWidget::abisChanged);
|
||||
auto chooser = new Core::VariableChooser(m_ui->qmakeAdditonalArgumentsLineEdit);
|
||||
chooser->addMacroExpanderProvider([step] { return step->macroExpander(); });
|
||||
chooser->addSupportedWidget(m_ui->qmakeAdditonalArgumentsLineEdit);
|
||||
@@ -665,6 +666,36 @@ void QMakeStepConfigWidget::separateDebugInfoChanged()
|
||||
updateEffectiveQMakeCall();
|
||||
}
|
||||
|
||||
void QMakeStepConfigWidget::abisChanged()
|
||||
{
|
||||
if (m_abisParam.isEmpty())
|
||||
return;
|
||||
|
||||
QStringList args = m_step->extraArguments();
|
||||
for (auto it = args.begin(); it != args.end(); ++it) {
|
||||
if (it->startsWith(m_abisParam)) {
|
||||
args.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QStringList abis;
|
||||
for (int i = 0; i < m_ui->abisListWidget->count(); ++i) {
|
||||
auto item = m_ui->abisListWidget->item(i);
|
||||
if (item->checkState() == Qt::CheckState::Checked)
|
||||
abis << item->text();
|
||||
}
|
||||
if (abis.isEmpty()) {
|
||||
m_ui->abisListWidget->item(m_preferredAbiIndex)->setCheckState(Qt::CheckState::Checked);
|
||||
return;
|
||||
}
|
||||
args << QStringLiteral("%1\"%2\"").arg(m_abisParam, abis.join(' '));
|
||||
m_step->setExtraArguments(args);
|
||||
|
||||
updateSummaryLabel();
|
||||
updateEffectiveQMakeCall();
|
||||
}
|
||||
|
||||
void QMakeStepConfigWidget::qmakeArgumentsLineEdited()
|
||||
{
|
||||
m_ignoreChange = true;
|
||||
@@ -754,6 +785,32 @@ void QMakeStepConfigWidget::updateSummaryLabel()
|
||||
setSummaryText(tr("<b>qmake:</b> No Qt version set. Cannot run qmake."));
|
||||
return;
|
||||
}
|
||||
bool enableAbisSelect = qtVersion->qtAbis().size() > 1;
|
||||
m_ui->abisLabel->setVisible(enableAbisSelect);
|
||||
m_ui->abisListWidget->setVisible(enableAbisSelect);
|
||||
if (enableAbisSelect && m_ui->abisListWidget->count() != qtVersion->qtAbis().size()) {
|
||||
m_ui->abisListWidget->clear();
|
||||
bool isAndroid = true;
|
||||
m_preferredAbiIndex = -1;
|
||||
for (const auto &abi : qtVersion->qtAbis()) {
|
||||
auto item = new QListWidgetItem{abi.param(), m_ui->abisListWidget};
|
||||
item->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
|
||||
item->setCheckState(Qt::Unchecked);
|
||||
isAndroid = isAndroid && abi.osFlavor() == Abi::OSFlavor::AndroidLinuxFlavor;
|
||||
if (isAndroid && (item->text() == "arm64-v8a" ||
|
||||
(m_preferredAbiIndex == -1 && item->text() == "armeabi-v7a"))) {
|
||||
m_preferredAbiIndex = m_ui->abisListWidget->count() - 1;
|
||||
}
|
||||
}
|
||||
if (isAndroid)
|
||||
m_abisParam = "ANDROID_ABIS=";
|
||||
|
||||
if (m_preferredAbiIndex == -1)
|
||||
m_preferredAbiIndex = 0;
|
||||
m_ui->abisListWidget->item(m_preferredAbiIndex)->setCheckState(Qt::Checked);
|
||||
abisChanged();
|
||||
}
|
||||
|
||||
// We don't want the full path to the .pro file
|
||||
const QString args = m_step->allArguments(
|
||||
qtVersion,
|
||||
|
@@ -211,6 +211,7 @@ private:
|
||||
void linkQmlDebuggingLibraryChanged();
|
||||
void useQtQuickCompilerChanged();
|
||||
void separateDebugInfoChanged();
|
||||
void abisChanged();
|
||||
|
||||
// slots for dealing with user changes in our UI
|
||||
void qmakeArgumentsLineEdited();
|
||||
@@ -230,6 +231,8 @@ private:
|
||||
Internal::Ui::QMakeStep *m_ui = nullptr;
|
||||
QMakeStep *m_step = nullptr;
|
||||
bool m_ignoreChange = false;
|
||||
int m_preferredAbiIndex = -1;
|
||||
QString m_abisParam;
|
||||
};
|
||||
|
||||
} // namespace QmakeProjectManager
|
||||
|
@@ -6,26 +6,11 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>440</width>
|
||||
<height>250</height>
|
||||
<width>738</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::ExpandingFieldsGrow</enum>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_0">
|
||||
<property name="text">
|
||||
@@ -275,6 +260,19 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="abisLabel">
|
||||
<property name="text">
|
||||
<string>ABIs:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QListWidget" name="abisListWidget"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
|
Reference in New Issue
Block a user