QmakeAndroid: Replace remaining AndroidQtSupport

This uses the same approach as in the previous patches: Have some
generic interface in the base classes (here ProjectNode::targetData()
setTargetData()) and implement on the qmake project side.

Implementation for Cmake/QBS is architecture-wise possible, but
not used right now, and left for later.

Change-Id: I3bbf66170020cf9027a894cd66db15ec7ffbf499
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
hjk
2018-12-05 10:29:48 +01:00
parent 41a88b0763
commit 93257a56a0
25 changed files with 203 additions and 360 deletions

View File

@@ -6,7 +6,6 @@ else:ANDROID_EXPERIMENTAL_STR="false"
QT += xml network QT += xml network
HEADERS += \ HEADERS += \
androidqtsupport.h \
androidconstants.h \ androidconstants.h \
androidconfigurations.h \ androidconfigurations.h \
androidmanager.h \ androidmanager.h \

View File

@@ -78,7 +78,6 @@ Project {
"androidpotentialkit.h", "androidpotentialkit.h",
"androidqmltoolingsupport.cpp", "androidqmltoolingsupport.cpp",
"androidqmltoolingsupport.h", "androidqmltoolingsupport.h",
"androidqtsupport.h",
"androidqtversion.cpp", "androidqtversion.cpp",
"androidqtversion.h", "androidqtversion.h",
"androidqtversionfactory.cpp", "androidqtversionfactory.cpp",

View File

@@ -31,7 +31,6 @@
#include "androidconstants.h" #include "androidconstants.h"
#include "androidmanager.h" #include "androidmanager.h"
#include "androidsdkmanager.h" #include "androidsdkmanager.h"
#include "androidqtsupport.h"
#include "certificatesmodel.h" #include "certificatesmodel.h"
#include "javaparser.h" #include "javaparser.h"
@@ -43,6 +42,8 @@
#include <projectexplorer/processparameters.h> #include <projectexplorer/processparameters.h>
#include <projectexplorer/project.h> #include <projectexplorer/project.h>
#include <projectexplorer/projectexplorerconstants.h> #include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/projectnodes.h>
#include <projectexplorer/runconfiguration.h>
#include <projectexplorer/target.h> #include <projectexplorer/target.h>
#include <qtsupport/qtkitinformation.h> #include <qtsupport/qtkitinformation.h>
@@ -182,8 +183,10 @@ bool AndroidBuildApkStep::init(QList<const BuildStep *> &earlierSteps)
parser->setProjectFileList(Utils::transform(target()->project()->files(ProjectExplorer::Project::AllFiles), parser->setProjectFileList(Utils::transform(target()->project()->files(ProjectExplorer::Project::AllFiles),
&Utils::FileName::toString)); &Utils::FileName::toString));
AndroidQtSupport *qtSupport = AndroidManager::androidQtSupport(target()); RunConfiguration *rc = target()->activeRunConfiguration();
QFileInfo sourceDirInfo(qtSupport->targetData(Constants::AndroidPackageSourceDir, target()).toString()); const ProjectNode *node = rc ? target()->project()->findNodeForBuildKey(rc->buildKey()) : nullptr;
QFileInfo sourceDirInfo(node ? node->targetData(Constants::AndroidPackageSourceDir, target()).toString() : QString());
parser->setSourceDirectory(Utils::FileName::fromString(sourceDirInfo.canonicalFilePath())); parser->setSourceDirectory(Utils::FileName::fromString(sourceDirInfo.canonicalFilePath()));
parser->setBuildDirectory(Utils::FileName::fromString(bc->buildDirectory().appendPath(Constants::ANDROID_BUILDDIRECTORY).toString())); parser->setBuildDirectory(Utils::FileName::fromString(bc->buildDirectory().appendPath(Constants::ANDROID_BUILDDIRECTORY).toString()));
setOutputParser(parser); setOutputParser(parser);
@@ -204,8 +207,10 @@ bool AndroidBuildApkStep::init(QList<const BuildStep *> &earlierSteps)
QString outputDir = bc->buildDirectory().appendPath(Constants::ANDROID_BUILDDIRECTORY).toString(); QString outputDir = bc->buildDirectory().appendPath(Constants::ANDROID_BUILDDIRECTORY).toString();
QString inputFile = AndroidManager::androidQtSupport(target()) QString inputFile;
->targetData(Constants::AndroidDeploySettingsFile, target()).toString(); if (node)
inputFile = node->targetData(Constants::AndroidDeploySettingsFile, target()).toString();
if (inputFile.isEmpty()) { if (inputFile.isEmpty()) {
m_skipBuilding = true; m_skipBuilding = true;
return true; return true;

View File

@@ -30,7 +30,6 @@
#include "androidbuildapkstep.h" #include "androidbuildapkstep.h"
#include "androidextralibrarylistmodel.h" #include "androidextralibrarylistmodel.h"
#include "androidqtsupport.h"
#include <projectexplorer/buildstep.h> #include <projectexplorer/buildstep.h>

View File

@@ -74,5 +74,11 @@ const char ANDROID_EXTRA_LIBS[] = "AndroidExtraLibs";
const char ANDROID_PACKAGENAME[] = "Android.PackageName"; const char ANDROID_PACKAGENAME[] = "Android.PackageName";
const char ANDROID_PACKAGE_INSTALLATION_STEP_ID[] = "Qt4ProjectManager.AndroidPackageInstallationStep"; const char ANDROID_PACKAGE_INSTALLATION_STEP_ID[] = "Qt4ProjectManager.AndroidPackageInstallationStep";
const char AndroidPackageSourceDir[] = "AndroidPackageSourceDir"; // QString
const char AndroidDeploySettingsFile[] = "AndroidDeploySettingsFile"; // QString
const char AndroidExtraLibs[] = "AndroidExtraLibs"; // QStringList
const char AndroidArch[] = "AndroidArch"; // QString
const char AndroidSoLibPath[] = "AndroidSoLibPath"; // QStringList
} // namespace Constants; } // namespace Constants;
} // namespace Android } // namespace Android

View File

@@ -25,10 +25,10 @@
#include "androiddebugsupport.h" #include "androiddebugsupport.h"
#include "androidconstants.h"
#include "androidglobal.h" #include "androidglobal.h"
#include "androidrunner.h" #include "androidrunner.h"
#include "androidmanager.h" #include "androidmanager.h"
#include "androidqtsupport.h"
#include <debugger/debuggerkitinformation.h> #include <debugger/debuggerkitinformation.h>
#include <debugger/debuggerrunconfigurationaspect.h> #include <debugger/debuggerrunconfigurationaspect.h>
@@ -36,6 +36,7 @@
#include <projectexplorer/buildconfiguration.h> #include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/project.h> #include <projectexplorer/project.h>
#include <projectexplorer/projectnodes.h>
#include <projectexplorer/target.h> #include <projectexplorer/target.h>
#include <projectexplorer/toolchain.h> #include <projectexplorer/toolchain.h>
@@ -44,8 +45,9 @@
#include <utils/hostosinfo.h> #include <utils/hostosinfo.h>
#include <QDirIterator> #include <QDirIterator>
#include <QLoggingCategory>
#include <QHostAddress> #include <QHostAddress>
#include <QJsonDocument>
#include <QLoggingCategory>
namespace { namespace {
Q_LOGGING_CATEGORY(androidDebugSupportLog, "qtc.android.run.androiddebugsupport", QtWarningMsg) Q_LOGGING_CATEGORY(androidDebugSupportLog, "qtc.android.run.androiddebugsupport", QtWarningMsg)
@@ -90,6 +92,44 @@ static QStringList uniquePaths(const QStringList &files)
return paths.toList(); return paths.toList();
} }
static QStringList getSoLibSearchPath(const RunConfiguration *rc)
{
Target *target = rc->target();
const ProjectNode *node = target->project()->findNodeForBuildKey(rc->buildKey());
if (!node)
return {};
QStringList res;
node->forEachProjectNode([&res, target](const ProjectNode *node) {
res.append(node->targetData(Constants::AndroidSoLibPath, target).toStringList());
});
const QString jsonFile = node->targetData(Android::Constants::AndroidDeploySettingsFile, target).toString();
QFile deploymentSettings(jsonFile);
if (deploymentSettings.open(QIODevice::ReadOnly)) {
QJsonParseError error;
QJsonDocument doc = QJsonDocument::fromJson(deploymentSettings.readAll(), &error);
if (error.error == QJsonParseError::NoError) {
auto rootObj = doc.object();
auto it = rootObj.find("stdcpp-path");
if (it != rootObj.constEnd())
res.append(QFileInfo(it.value().toString()).absolutePath());
}
}
res.removeDuplicates();
return res;
}
static QStringList getExtraLibs(const RunConfiguration *rc)
{
const ProjectNode *node = rc->target()->project()->findNodeForBuildKey(rc->buildKey());
if (!node)
return {};
return node->targetData(Android::Constants::AndroidExtraLibs, rc->target()).toStringList();
}
static QString toNdkArch(const QString &arch) static QString toNdkArch(const QString &arch)
{ {
if (arch == QLatin1String("armeabi-v7a") || arch == QLatin1String("armeabi")) if (arch == QLatin1String("armeabi-v7a") || arch == QLatin1String("armeabi"))
@@ -131,9 +171,8 @@ void AndroidDebugSupport::start()
if (isCppDebugging()) { if (isCppDebugging()) {
qCDebug(androidDebugSupportLog) << "C++ debugging enabled"; qCDebug(androidDebugSupportLog) << "C++ debugging enabled";
AndroidQtSupport *qtSupport = AndroidManager::androidQtSupport(target); QStringList solibSearchPath = getSoLibSearchPath(runConfig);
QStringList solibSearchPath = qtSupport->soLibSearchPath(target); QStringList extraLibs = getExtraLibs(runConfig);
QStringList extraLibs = qtSupport->targetData(Android::Constants::AndroidExtraLibs, target).toStringList();
solibSearchPath.append(qtSoPaths(qtVersion)); solibSearchPath.append(qtSoPaths(qtVersion));
solibSearchPath.append(uniquePaths(extraLibs)); solibSearchPath.append(uniquePaths(extraLibs));
setSolibSearchPath(solibSearchPath); setSolibSearchPath(solibSearchPath);

View File

@@ -28,7 +28,6 @@
#include "androidconstants.h" #include "androidconstants.h"
#include "androiddeployqtstep.h" #include "androiddeployqtstep.h"
#include "androidmanager.h" #include "androidmanager.h"
#include "androidqtsupport.h"
#include <projectexplorer/buildsteplist.h> #include <projectexplorer/buildsteplist.h>
#include <projectexplorer/project.h> #include <projectexplorer/project.h>

View File

@@ -26,7 +26,6 @@
#include "androiddeployqtstep.h" #include "androiddeployqtstep.h"
#include "androiddeployqtwidget.h" #include "androiddeployqtwidget.h"
#include "androidqtsupport.h"
#include "certificatesmodel.h" #include "certificatesmodel.h"
#include "javaparser.h" #include "javaparser.h"
@@ -43,6 +42,7 @@
#include <projectexplorer/buildsteplist.h> #include <projectexplorer/buildsteplist.h>
#include <projectexplorer/projectexplorerconstants.h> #include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/project.h> #include <projectexplorer/project.h>
#include <projectexplorer/projectnodes.h>
#include <projectexplorer/runconfiguration.h> #include <projectexplorer/runconfiguration.h>
#include <projectexplorer/target.h> #include <projectexplorer/target.h>
#include <projectexplorer/toolchain.h> #include <projectexplorer/toolchain.h>
@@ -170,8 +170,7 @@ bool AndroidDeployQtStep::init(QList<const BuildStep *> &earlierSteps)
if (m_uninstallPreviousPackageRun) if (m_uninstallPreviousPackageRun)
m_manifestName = AndroidManager::manifestPath(target()); m_manifestName = AndroidManager::manifestPath(target());
AndroidQtSupport *qtSupport = AndroidManager::androidQtSupport(target()); m_useAndroiddeployqt = !deployQtLive &&
m_useAndroiddeployqt = !deployQtLive && qtSupport &&
version->qtVersion() >= QtSupport::QtVersionNumber(5, 4, 0); version->qtVersion() >= QtSupport::QtVersionNumber(5, 4, 0);
if (m_useAndroiddeployqt) { if (m_useAndroiddeployqt) {
@@ -192,11 +191,15 @@ bool AndroidDeployQtStep::init(QList<const BuildStep *> &earlierSteps)
Utils::QtcProcess::addArg(&m_androiddeployqtArgs, m_workingDirectory); Utils::QtcProcess::addArg(&m_androiddeployqtArgs, m_workingDirectory);
Utils::QtcProcess::addArg(&m_androiddeployqtArgs, QLatin1String("--no-build")); Utils::QtcProcess::addArg(&m_androiddeployqtArgs, QLatin1String("--no-build"));
Utils::QtcProcess::addArg(&m_androiddeployqtArgs, QLatin1String("--input")); Utils::QtcProcess::addArg(&m_androiddeployqtArgs, QLatin1String("--input"));
const QString jsonFile = qtSupport->targetData(Constants::AndroidDeploySettingsFile, target()).toString();
QString jsonFile;
if (const ProjectNode *node = target()->project()->findNodeForBuildKey(rc->buildKey()))
jsonFile = node->targetData(Constants::AndroidDeploySettingsFile, target()).toString();
if (jsonFile.isEmpty()) { if (jsonFile.isEmpty()) {
emit addOutput(tr("Cannot find the androiddeploy Json file."), OutputFormat::Stderr); emit addOutput(tr("Cannot find the androiddeploy Json file."), OutputFormat::Stderr);
return false; return false;
} }
Utils::QtcProcess::addArg(&m_androiddeployqtArgs, jsonFile); Utils::QtcProcess::addArg(&m_androiddeployqtArgs, jsonFile);
if (androidBuildApkStep && androidBuildApkStep->useMinistro()) { if (androidBuildApkStep && androidBuildApkStep->useMinistro()) {
qCDebug(deployStepLog) << "Using ministro"; qCDebug(deployStepLog) << "Using ministro";

View File

@@ -26,7 +26,7 @@
#include "androidextralibrarylistmodel.h" #include "androidextralibrarylistmodel.h"
#include <android/androidqtsupport.h> #include <android/androidconstants.h>
#include <android/androidmanager.h> #include <android/androidmanager.h>
#include <projectexplorer/project.h> #include <projectexplorer/project.h>
@@ -91,9 +91,6 @@ void AndroidExtraLibraryListModel::updateModel()
const ProjectNode *node = m_target->project()->findNodeForBuildKey(rc->buildKey()); const ProjectNode *node = m_target->project()->findNodeForBuildKey(rc->buildKey());
QTC_ASSERT(node, return); QTC_ASSERT(node, return);
AndroidQtSupport *qtSupport = Android::AndroidManager::androidQtSupport(m_target);
QTC_ASSERT(qtSupport, return);
if (node->parseInProgress()) { if (node->parseInProgress()) {
emit enabledChanged(false); emit enabledChanged(false);
return; return;
@@ -102,7 +99,7 @@ void AndroidExtraLibraryListModel::updateModel()
bool enabled; bool enabled;
beginResetModel(); beginResetModel();
if (node->validParse()) { if (node->validParse()) {
m_entries = qtSupport->targetData(Constants::AndroidExtraLibs, m_target).toStringList(); m_entries = node->targetData(Constants::AndroidExtraLibs, m_target).toStringList();
enabled = true; enabled = true;
} else { } else {
// parsing error // parsing error
@@ -116,9 +113,6 @@ void AndroidExtraLibraryListModel::updateModel()
void AndroidExtraLibraryListModel::addEntries(const QStringList &list) void AndroidExtraLibraryListModel::addEntries(const QStringList &list)
{ {
AndroidQtSupport *qtSupport = Android::AndroidManager::androidQtSupport(m_target);
QTC_ASSERT(qtSupport, return);
RunConfiguration *rc = m_target->activeRunConfiguration(); RunConfiguration *rc = m_target->activeRunConfiguration();
QTC_ASSERT(rc, return); QTC_ASSERT(rc, return);
@@ -131,7 +125,7 @@ void AndroidExtraLibraryListModel::addEntries(const QStringList &list)
for (const QString &path : list) for (const QString &path : list)
m_entries += "$$PWD/" + dir.relativeFilePath(path); m_entries += "$$PWD/" + dir.relativeFilePath(path);
qtSupport->setTargetData(Constants::AndroidExtraLibs, m_entries, m_target); node->setTargetData(Constants::AndroidExtraLibs, m_entries, m_target);
endInsertRows(); endInsertRows();
} }
@@ -161,9 +155,11 @@ void AndroidExtraLibraryListModel::removeEntries(QModelIndexList list)
endRemoveRows(); endRemoveRows();
} }
AndroidQtSupport *qtSupport = AndroidManager::androidQtSupport(m_target); RunConfiguration *rc = m_target->activeRunConfiguration();
QTC_ASSERT(qtSupport, return); QTC_ASSERT(rc, return);
qtSupport->setTargetData(Constants::AndroidExtraLibs, m_entries, m_target); const ProjectNode *node = m_target->project()->findNodeForBuildKey(rc->buildKey());
QTC_ASSERT(node, return);
node->setTargetData(Constants::AndroidExtraLibs, m_entries, m_target);
} }
} // Android } // Android

View File

@@ -31,7 +31,6 @@
#include "androidglobal.h" #include "androidglobal.h"
#include "androidtoolchain.h" #include "androidtoolchain.h"
#include "androiddeployqtstep.h" #include "androiddeployqtstep.h"
#include "androidqtsupport.h"
#include "androidqtversion.h" #include "androidqtversion.h"
#include "androidavdmanager.h" #include "androidavdmanager.h"
#include "androidsdkmanager.h" #include "androidsdkmanager.h"
@@ -42,6 +41,7 @@
#include <projectexplorer/buildconfiguration.h> #include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/project.h> #include <projectexplorer/project.h>
#include <projectexplorer/projectnodes.h>
#include <projectexplorer/projectexplorer.h> #include <projectexplorer/projectexplorer.h>
#include <projectexplorer/session.h> #include <projectexplorer/session.h>
#include <projectexplorer/target.h> #include <projectexplorer/target.h>
@@ -89,6 +89,7 @@ namespace {
} // anonymous namespace } // anonymous namespace
using namespace ProjectExplorer;
using namespace Utils; using namespace Utils;
namespace Android { namespace Android {
@@ -111,16 +112,11 @@ static bool openXmlFile(QDomDocument &doc, const Utils::FileName &fileName);
static bool openManifest(ProjectExplorer::Target *target, QDomDocument &doc); static bool openManifest(ProjectExplorer::Target *target, QDomDocument &doc);
static int parseMinSdk(const QDomElement &manifestElem); static int parseMinSdk(const QDomElement &manifestElem);
static QList<AndroidQtSupport *> g_androidQtSupportProviders; static const ProjectNode *currentProjectNode(Target *target)
AndroidQtSupport::AndroidQtSupport()
{ {
g_androidQtSupportProviders.append(this); if (RunConfiguration *rc = target->activeRunConfiguration())
} return target->project()->findNodeForBuildKey(rc->buildKey());
return nullptr;
AndroidQtSupport::~AndroidQtSupport()
{
g_androidQtSupportProviders.removeOne(this);
} }
QString AndroidManager::packageName(ProjectExplorer::Target *target) QString AndroidManager::packageName(ProjectExplorer::Target *target)
@@ -306,9 +302,9 @@ Utils::FileName AndroidManager::apkPath(const ProjectExplorer::Target *target)
Utils::FileName AndroidManager::manifestSourcePath(ProjectExplorer::Target *target) Utils::FileName AndroidManager::manifestSourcePath(ProjectExplorer::Target *target)
{ {
if (AndroidQtSupport *androidQtSupport = AndroidManager::androidQtSupport(target)) { if (const ProjectNode *node = currentProjectNode(target)) {
const QString packageSource const QString packageSource
= androidQtSupport->targetData(Android::Constants::AndroidPackageSourceDir, target).toString(); = node->targetData(Android::Constants::AndroidPackageSourceDir, target).toString();
if (!packageSource.isEmpty()) { if (!packageSource.isEmpty()) {
const FileName manifest = FileName::fromUserInput(packageSource + "/AndroidManifest.xml"); const FileName manifest = FileName::fromUserInput(packageSource + "/AndroidManifest.xml");
if (manifest.exists()) if (manifest.exists())
@@ -559,15 +555,6 @@ bool AndroidManager::checkCertificateExists(const QString &keystorePath,
return response.result == Utils::SynchronousProcessResponse::Finished && response.exitCode == 0; return response.result == Utils::SynchronousProcessResponse::Finished && response.exitCode == 0;
} }
AndroidQtSupport *AndroidManager::androidQtSupport(ProjectExplorer::Target *target)
{
for (AndroidQtSupport *provider : g_androidQtSupportProviders) {
if (provider->canHandle(target))
return provider;
}
return nullptr;
}
using GradleProperties = QMap<QByteArray, QByteArray>; using GradleProperties = QMap<QByteArray, QByteArray>;
static GradleProperties readGradleProperties(const QString &path) static GradleProperties readGradleProperties(const QString &path)
@@ -636,11 +623,11 @@ bool AndroidManager::updateGradleProperties(ProjectExplorer::Target *target)
if (!version) if (!version)
return false; return false;
AndroidQtSupport *qtSupport = androidQtSupport(target); const ProjectNode *node = currentProjectNode(target);
if (!qtSupport) if (!node)
return false; return false;
QFileInfo sourceDirInfo(qtSupport->targetData(Constants::AndroidPackageSourceDir, target).toString()); QFileInfo sourceDirInfo(node->targetData(Constants::AndroidPackageSourceDir, target).toString());
FileName packageSourceDir = FileName::fromString(sourceDirInfo.canonicalFilePath()); FileName packageSourceDir = FileName::fromString(sourceDirInfo.canonicalFilePath());
if (!packageSourceDir.appendPath("gradlew").exists()) if (!packageSourceDir.appendPath("gradlew").exists())
return false; return false;

View File

@@ -44,8 +44,6 @@ namespace Utils { class FileName; }
namespace Android { namespace Android {
class AndroidQtSupport;
class SdkToolResult { class SdkToolResult {
public: public:
SdkToolResult() = default; SdkToolResult() = default;
@@ -110,7 +108,6 @@ public:
static bool checkCertificatePassword(const QString &keystorePath, const QString &keystorePasswd, const QString &alias, const QString &certificatePasswd); static bool checkCertificatePassword(const QString &keystorePath, const QString &keystorePasswd, const QString &alias, const QString &certificatePasswd);
static bool checkCertificateExists(const QString &keystorePath, const QString &keystorePasswd, static bool checkCertificateExists(const QString &keystorePath, const QString &keystorePasswd,
const QString &alias); const QString &alias);
static AndroidQtSupport *androidQtSupport(ProjectExplorer::Target *target);
static bool updateGradleProperties(ProjectExplorer::Target *target); static bool updateGradleProperties(ProjectExplorer::Target *target);
static int findApiLevel(const Utils::FileName &platformPath); static int findApiLevel(const Utils::FileName &platformPath);

View File

@@ -29,7 +29,6 @@
#include "androidconstants.h" #include "androidconstants.h"
#include "androidmanifestdocument.h" #include "androidmanifestdocument.h"
#include "androidmanager.h" #include "androidmanager.h"
#include "androidqtsupport.h"
#include <coreplugin/icore.h> #include <coreplugin/icore.h>
#include <coreplugin/infobar.h> #include <coreplugin/infobar.h>

View File

@@ -1,74 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2016 BogDan Vatra <bog_dan_ro@yahoo.com>
** 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 "android_global.h"
#include <coreplugin/id.h>
#include <QObject>
namespace ProjectExplorer { class Target; }
namespace Utils { class FileName; }
namespace Android {
namespace Constants {
const char AndroidPackageSourceDir[] = "AndroidPackageSourceDir"; // QString
const char AndroidDeploySettingsFile[] = "AndroidDeploySettingsFile"; // QString
const char AndroidExtraLibs[] = "AndroidExtraLibs"; // QStringList
const char AndroidArch[] = "AndroidArch"; // QString
} // namespace Constants
class ANDROID_EXPORT AndroidQtSupport : public QObject
{
Q_OBJECT
protected:
AndroidQtSupport();
~AndroidQtSupport() override;
public:
enum BuildType {
DebugBuild,
ReleaseBuildUnsigned,
ReleaseBuildSigned
};
virtual bool canHandle(const ProjectExplorer::Target *target) const = 0;
virtual QStringList soLibSearchPath(const ProjectExplorer::Target *target) const = 0;
virtual QVariant targetData(Core::Id role, const ProjectExplorer::Target *target) const = 0;
virtual bool setTargetData(Core::Id role, const QVariant &value,
const ProjectExplorer::Target *target) const = 0;
virtual void addFiles(const ProjectExplorer::Target *target, const QString &buildKey,
const QStringList &addedFiles) const = 0;
};
} // namespace Android

View File

@@ -26,11 +26,13 @@
#include "createandroidmanifestwizard.h" #include "createandroidmanifestwizard.h"
#include <android/androidconfigurations.h> #include <android/androidconfigurations.h>
#include <android/androidconstants.h>
#include <android/androidmanager.h> #include <android/androidmanager.h>
#include <android/androidqtsupport.h>
#include <coreplugin/editormanager/editormanager.h> #include <coreplugin/editormanager/editormanager.h>
#include <projectexplorer/project.h>
#include <projectexplorer/projectnodes.h>
#include <projectexplorer/runconfiguration.h> #include <projectexplorer/runconfiguration.h>
#include <projectexplorer/target.h> #include <projectexplorer/target.h>
@@ -177,13 +179,14 @@ bool ChooseDirectoryPage::isComplete() const
void ChooseDirectoryPage::initializePage() void ChooseDirectoryPage::initializePage()
{ {
const Target *target = m_wizard->target();
const QString buildKey = m_wizard->buildKey(); const QString buildKey = m_wizard->buildKey();
const BuildTargetInfo bti = m_wizard->target()->applicationTargets().buildTargetInfo(buildKey); const BuildTargetInfo bti = target->applicationTargets().buildTargetInfo(buildKey);
const QString projectDir = bti.projectFilePath.toFileInfo().absolutePath(); const QString projectDir = bti.projectFilePath.toFileInfo().absolutePath();
AndroidQtSupport *qtSupport = AndroidManager::androidQtSupport(m_wizard->target()); QString androidPackageDir;
const QString androidPackageDir if (const ProjectNode *node = target->project()->findNodeForBuildKey(buildKey))
= qtSupport->targetData(Android::Constants::AndroidPackageSourceDir, m_wizard->target()).toString(); androidPackageDir = node->targetData(Android::Constants::AndroidPackageSourceDir, target).toString();
if (androidPackageDir.isEmpty()) { if (androidPackageDir.isEmpty()) {
m_label->setText(tr("Select the Android package source directory.\n\n" m_label->setText(tr("Select the Android package source directory.\n\n"
@@ -344,17 +347,19 @@ void CreateAndroidManifestWizard::createAndroidTemplateFiles()
AndroidManager::updateGradleProperties(m_target); AndroidManager::updateGradleProperties(m_target);
} }
AndroidQtSupport *qtSupport = AndroidManager::androidQtSupport(m_target);
qtSupport->addFiles(m_target, m_buildKey, addedFiles);
const QString androidPackageDir QString androidPackageDir;
= qtSupport->targetData(Android::Constants::AndroidPackageSourceDir, m_target).toString(); ProjectNode *node = m_target->project()->findNodeForBuildKey(m_buildKey);
if (node) {
node->addFiles(addedFiles);
androidPackageDir = node->targetData(Android::Constants::AndroidPackageSourceDir, m_target).toString();
}
if (androidPackageDir.isEmpty()) { if (androidPackageDir.isEmpty()) {
// and now time for some magic // and now time for some magic
const BuildTargetInfo bti = m_target->applicationTargets().buildTargetInfo(m_buildKey); const BuildTargetInfo bti = m_target->applicationTargets().buildTargetInfo(m_buildKey);
const QString value = "$$PWD/" + bti.projectFilePath.toFileInfo().absoluteDir().relativeFilePath(m_directory); const QString value = "$$PWD/" + bti.projectFilePath.toFileInfo().absoluteDir().relativeFilePath(m_directory);
bool result = qtSupport->setTargetData(Android::Constants::AndroidPackageSourceDir, value, m_target); bool result = node->setTargetData(Android::Constants::AndroidPackageSourceDir, value, m_target);
if (!result) { if (!result) {
QMessageBox::warning(this, tr("Project File not Updated"), QMessageBox::warning(this, tr("Project File not Updated"),

View File

@@ -883,7 +883,7 @@ bool Project::hasParsingData() const
return d->m_hasParsingData; return d->m_hasParsingData;
} }
const ProjectNode *Project::findNodeForBuildKey(const QString &buildKey) const ProjectNode *Project::findNodeForBuildKey(const QString &buildKey) const
{ {
if (!d->m_rootProjectNode) if (!d->m_rootProjectNode)
return nullptr; return nullptr;

View File

@@ -171,7 +171,7 @@ public:
bool isParsing() const; bool isParsing() const;
bool hasParsingData() const; bool hasParsingData() const;
const ProjectNode *findNodeForBuildKey(const QString &buildKey) const; ProjectNode *findNodeForBuildKey(const QString &buildKey) const;
template<typename S, typename R, typename T, typename ...Args1, typename ...Args2> template<typename S, typename R, typename T, typename ...Args1, typename ...Args2>
void subscribeSignal(void (S::*sig)(Args1...), R*recv, T (R::*sl)(Args2...)) { void subscribeSignal(void (S::*sig)(Args1...), R*recv, T (R::*sl)(Args2...)) {

View File

@@ -525,16 +525,16 @@ void FolderNode::forEachProjectNode(const std::function<void(const ProjectNode *
} }
} }
const ProjectNode *FolderNode::findProjectNode(const std::function<bool(const ProjectNode *)> &predicate) const ProjectNode *FolderNode::findProjectNode(const std::function<bool(const ProjectNode *)> &predicate)
{ {
if (const ProjectNode *projectNode = asProjectNode()) { if (ProjectNode *projectNode = asProjectNode()) {
if (predicate(projectNode)) if (predicate(projectNode))
return projectNode; return projectNode;
} }
for (const std::unique_ptr<Node> &n : m_nodes) { for (const std::unique_ptr<Node> &n : m_nodes) {
if (FolderNode *fn = n->asFolderNode()) { if (FolderNode *fn = n->asFolderNode()) {
if (const ProjectNode *pn = fn->findProjectNode(predicate)) if (ProjectNode *pn = fn->findProjectNode(predicate))
return pn; return pn;
} }
} }
@@ -883,6 +883,21 @@ ProjectNode *ProjectNode::projectNode(const Utils::FileName &file) const
return nullptr; return nullptr;
} }
QVariant ProjectNode::targetData(Core::Id role, const Target *target) const
{
Q_UNUSED(role);
Q_UNUSED(target);
return QVariant();
}
bool ProjectNode::setTargetData(Core::Id role, const QVariant &value, const Target *target) const
{
Q_UNUSED(role);
Q_UNUSED(target);
Q_UNUSED(value);
return false;
}
bool FolderNode::isEmpty() const bool FolderNode::isEmpty() const
{ {
return m_nodes.size() == 0; return m_nodes.size() == 0;

View File

@@ -31,8 +31,11 @@
#include <QIcon> #include <QIcon>
#include <QStringList> #include <QStringList>
#include <coreplugin/id.h>
#include <utils/fileutils.h> #include <utils/fileutils.h>
#include <utils/optional.h> #include <utils/optional.h>
#include <functional> #include <functional>
namespace Utils { class MimeType; } namespace Utils { class MimeType; }
@@ -40,6 +43,7 @@ namespace Utils { class MimeType; }
namespace ProjectExplorer { namespace ProjectExplorer {
class Project; class Project;
class Target;
enum class NodeType : quint16 { enum class NodeType : quint16 {
File = 1, File = 1,
@@ -219,7 +223,7 @@ public:
const std::function<bool(const FolderNode *)> &folderFilterTask = {}) const; const std::function<bool(const FolderNode *)> &folderFilterTask = {}) const;
void forEachGenericNode(const std::function<void(Node *)> &genericTask) const; void forEachGenericNode(const std::function<void(Node *)> &genericTask) const;
void forEachProjectNode(const std::function<void(const ProjectNode *)> &genericTask) const; void forEachProjectNode(const std::function<void(const ProjectNode *)> &genericTask) const;
const ProjectNode *findProjectNode(const std::function<bool(const ProjectNode *)> &predicate) const; ProjectNode *findProjectNode(const std::function<bool(const ProjectNode *)> &predicate);
const QList<Node *> nodes() const; const QList<Node *> nodes() const;
QList<FileNode *> fileNodes() const; QList<FileNode *> fileNodes() const;
FileNode *fileNode(const Utils::FileName &file) const; FileNode *fileNode(const Utils::FileName &file) const;
@@ -344,7 +348,10 @@ public:
virtual QStringList targetApplications() const { return {}; } virtual QStringList targetApplications() const { return {}; }
virtual bool parseInProgress() const { return false; } virtual bool parseInProgress() const { return false; }
virtual bool validParse() const { return false; } virtual bool validParse() const { return false; }
virtual QVariant targetData(Core::Id role, const Target *target) const;
virtual bool setTargetData(Core::Id role, const QVariant &value, const Target *target) const;
protected: protected:
explicit ProjectNode(const Utils::FileName &projectFilePath, const QByteArray &id = {}); explicit ProjectNode(const Utils::FileName &projectFilePath, const QByteArray &id = {});

View File

@@ -1,156 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2016 BogDan Vatra <bog_dan_ro@yahoo.com>
** 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 "qmakeandroidsupport.h"
#include "androidqmakebuildconfigurationfactory.h"
#include <android/androidbuildapkstep.h>
#include <android/androidconstants.h>
#include <android/androidglobal.h>
#include <projectexplorer/runconfiguration.h>
#include <projectexplorer/target.h>
#include <qtsupport/qtkitinformation.h>
#include <qmakeprojectmanager/qmakeproject.h>
#include <utils/qtcassert.h>
#include <QJsonDocument>
#include <QJsonObject>
#include <QRegularExpression>
using namespace ProjectExplorer;
using namespace QmakeProjectManager;
using namespace Utils;
namespace QmakeAndroidSupport {
namespace Internal {
bool QmakeAndroidSupport::canHandle(const ProjectExplorer::Target *target) const
{
return qobject_cast<QmakeProject*>(target->project());
}
QVariant QmakeAndroidSupport::targetData(Core::Id role, const Target *target) const
{
RunConfiguration *rc = target->activeRunConfiguration();
if (!rc)
return {};
const FileName projectFilePath = FileName::fromString(rc->buildKey());
const ProjectNode *projectNode = target->project()->findNodeForBuildKey(rc->buildKey());
auto profileNode = dynamic_cast<const QmakeProFileNode *>(projectNode);
QTC_ASSERT(profileNode, return {});
if (role == Android::Constants::AndroidPackageSourceDir)
return profileNode->singleVariableValue(Variable::AndroidPackageSourceDir);
if (role == Android::Constants::AndroidDeploySettingsFile)
return profileNode->singleVariableValue(Variable::AndroidDeploySettingsFile);
if (role == Android::Constants::AndroidExtraLibs)
return profileNode->variableValue(Variable::AndroidExtraLibs);
if (role == Android::Constants::AndroidArch)
return profileNode->singleVariableValue(Variable::AndroidArch);
QTC_CHECK(false);
return {};
}
static QmakeProFile *applicationProFile(const Target *target)
{
ProjectExplorer::RunConfiguration *rc = target->activeRunConfiguration();
if (!rc)
return nullptr;
auto project = static_cast<QmakeProject *>(target->project());
return project->rootProFile()->findProFile(FileName::fromString(rc->buildKey()));
}
bool QmakeAndroidSupport::setTargetData(Core::Id role, const QVariant &value, const Target *target) const
{
QmakeProFile *pro = applicationProFile(target);
if (!pro)
return false;
const QString arch = pro->singleVariableValue(Variable::AndroidArch);
const QString scope = "contains(ANDROID_TARGET_ARCH," + arch + ')';
auto flags = QmakeProjectManager::Internal::ProWriter::ReplaceValues
| QmakeProjectManager::Internal::ProWriter::MultiLine;
if (role == Android::Constants::AndroidExtraLibs)
return pro->setProVariable("ANDROID_EXTRA_LIBS", value.toStringList(), scope, flags);
if (role == Android::Constants::AndroidPackageSourceDir)
return pro->setProVariable("ANDROID_PACKAGE_SOURCE_DIR", {value.toString()}, scope, flags);
return false;
}
QStringList QmakeAndroidSupport::soLibSearchPath(const ProjectExplorer::Target *target) const
{
QSet<QString> res;
ProjectNode *root = target->project()->rootProjectNode();
root->forEachProjectNode([&res](const ProjectNode *node) {
auto qmakeNode = dynamic_cast<const QmakeProFileNode *>(node);
if (!qmakeNode)
return;
TargetInformation info = qmakeNode->targetInformation();
res.insert(info.buildDir.toString());
Utils::FileName destDir = info.destDir;
if (!destDir.isEmpty()) {
if (destDir.toFileInfo().isRelative())
destDir = Utils::FileName::fromString(QDir::cleanPath(info.buildDir.toString()
+ '/' + destDir.toString()));
res.insert(destDir.toString());
}
});
const QString jsonFile = targetData(Android::Constants::AndroidDeploySettingsFile, target).toString();
QFile deploymentSettings(jsonFile);
if (deploymentSettings.open(QIODevice::ReadOnly)) {
QJsonParseError error;
QJsonDocument doc = QJsonDocument::fromJson(deploymentSettings.readAll(), &error);
if (error.error == QJsonParseError::NoError) {
auto rootObj = doc.object();
auto it = rootObj.find("stdcpp-path");
if (it != rootObj.constEnd())
res.insert(QFileInfo(it.value().toString()).absolutePath());
}
}
return res.toList();
}
void QmakeAndroidSupport::addFiles(const ProjectExplorer::Target *target,
const QString &buildKey,
const QStringList &addedFiles) const
{
auto project = static_cast<QmakeProject *>(target->project());
QmakeProFile *currentRunNode = project->rootProFile()->findProFile(FileName::fromString(buildKey));
QTC_ASSERT(currentRunNode, return);
currentRunNode->addFiles(addedFiles);
}
} // namespace Internal
} // namespace QmakeAndroidSupport

View File

@@ -1,50 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2016 BogDan Vatra <bog_dan_ro@yahoo.com>
** 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 <android/androidqtsupport.h>
namespace QmakeAndroidSupport {
namespace Internal {
class QmakeAndroidSupport : public Android::AndroidQtSupport
{
Q_OBJECT
public:
bool canHandle(const ProjectExplorer::Target *target) const override;
QStringList soLibSearchPath(const ProjectExplorer::Target *target) const override;
QVariant targetData(Core::Id role, const ProjectExplorer::Target *target) const override;
bool setTargetData(Core::Id role, const QVariant &value,
const ProjectExplorer::Target *target) const override;
void addFiles(const ProjectExplorer::Target *target, const QString &buildKey,
const QStringList &addedFiles) const override;
};
} // namespace Internal
} // namespace QmakeAndroidSupport

View File

@@ -5,11 +5,9 @@ DEFINES += \
QMAKEANDROID_LIBRARY QMAKEANDROID_LIBRARY
HEADERS += \ HEADERS += \
qmakeandroidsupport.h \
androidqmakebuildconfigurationfactory.h \ androidqmakebuildconfigurationfactory.h \
qmakeandroidsupportplugin.h qmakeandroidsupportplugin.h
SOURCES += \ SOURCES += \
qmakeandroidsupport.cpp \
androidqmakebuildconfigurationfactory.cpp \ androidqmakebuildconfigurationfactory.cpp \
qmakeandroidsupportplugin.cpp qmakeandroidsupportplugin.cpp

View File

@@ -18,8 +18,6 @@ QtcPlugin {
files: [ files: [
"androidqmakebuildconfigurationfactory.cpp", "androidqmakebuildconfigurationfactory.cpp",
"androidqmakebuildconfigurationfactory.h", "androidqmakebuildconfigurationfactory.h",
"qmakeandroidsupport.cpp",
"qmakeandroidsupport.h",
"qmakeandroidsupportplugin.h", "qmakeandroidsupportplugin.h",
"qmakeandroidsupportplugin.cpp", "qmakeandroidsupportplugin.cpp",
] ]

View File

@@ -26,7 +26,6 @@
#include "qmakeandroidsupportplugin.h" #include "qmakeandroidsupportplugin.h"
#include "androidqmakebuildconfigurationfactory.h" #include "androidqmakebuildconfigurationfactory.h"
#include "qmakeandroidsupport.h"
using namespace ProjectExplorer; using namespace ProjectExplorer;
@@ -37,7 +36,6 @@ class QmakeAndroidSupportPluginPrivate
{ {
public: public:
AndroidQmakeBuildConfigurationFactory buildConfigFactory; AndroidQmakeBuildConfigurationFactory buildConfigFactory;
QmakeAndroidSupport androidSupport;
}; };
QmakeAndroidSupportPlugin::~QmakeAndroidSupportPlugin() QmakeAndroidSupportPlugin::~QmakeAndroidSupportPlugin()

View File

@@ -35,6 +35,12 @@
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <utils/stringutils.h> #include <utils/stringutils.h>
#include <android/androidconstants.h>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonParseError>
using namespace ProjectExplorer; using namespace ProjectExplorer;
using namespace Utils; using namespace Utils;
@@ -241,6 +247,70 @@ QStringList QmakeProFileNode::targetApplications() const
return apps; return apps;
} }
QVariant QmakeProFileNode::targetData(Core::Id role, const Target *target) const
{
RunConfiguration *rc = target->activeRunConfiguration();
if (!rc)
return {};
const FileName projectFilePath = FileName::fromString(rc->buildKey());
const ProjectNode *projectNode = target->project()->findNodeForBuildKey(rc->buildKey());
auto profileNode = dynamic_cast<const QmakeProFileNode *>(projectNode);
QTC_ASSERT(profileNode, return {});
if (role == Android::Constants::AndroidPackageSourceDir)
return profileNode->singleVariableValue(Variable::AndroidPackageSourceDir);
if (role == Android::Constants::AndroidDeploySettingsFile)
return profileNode->singleVariableValue(Variable::AndroidDeploySettingsFile);
if (role == Android::Constants::AndroidExtraLibs)
return profileNode->variableValue(Variable::AndroidExtraLibs);
if (role == Android::Constants::AndroidArch)
return profileNode->singleVariableValue(Variable::AndroidArch);
if (role == Android::Constants::AndroidSoLibPath) {
TargetInformation info = profileNode->targetInformation();
QStringList res = {info.buildDir.toString()};
Utils::FileName destDir = info.destDir;
if (!destDir.isEmpty()) {
if (destDir.toFileInfo().isRelative())
destDir = Utils::FileName::fromString(QDir::cleanPath(info.buildDir.toString()
+ '/' + destDir.toString()));
res.append(destDir.toString());
}
res.removeDuplicates();
return res;
}
QTC_CHECK(false);
return {};
}
static QmakeProFile *applicationProFile(const Target *target)
{
ProjectExplorer::RunConfiguration *rc = target->activeRunConfiguration();
if (!rc)
return nullptr;
auto project = static_cast<QmakeProject *>(target->project());
return project->rootProFile()->findProFile(FileName::fromString(rc->buildKey()));
}
bool QmakeProFileNode::setTargetData(Core::Id role, const QVariant &value, const Target *target) const
{
QmakeProFile *pro = applicationProFile(target);
if (!pro)
return false;
const QString arch = pro->singleVariableValue(Variable::AndroidArch);
const QString scope = "contains(ANDROID_TARGET_ARCH," + arch + ')';
auto flags = QmakeProjectManager::Internal::ProWriter::ReplaceValues
| QmakeProjectManager::Internal::ProWriter::MultiLine;
if (role == Android::Constants::AndroidExtraLibs)
return pro->setProVariable("ANDROID_EXTRA_LIBS", value.toStringList(), scope, flags);
if (role == Android::Constants::AndroidPackageSourceDir)
return pro->setProVariable("ANDROID_PACKAGE_SOURCE_DIR", {value.toString()}, scope, flags);
return false;
}
QmakeProFile *QmakeProFileNode::proFile() const QmakeProFile *QmakeProFileNode::proFile() const
{ {
return static_cast<QmakeProFile*>(QmakePriFileNode::priFile()); return static_cast<QmakeProFile*>(QmakePriFileNode::priFile());

View File

@@ -98,6 +98,10 @@ public:
QStringList targetApplications() const override; QStringList targetApplications() const override;
AddNewInformation addNewInformation(const QStringList &files, Node *context) const override; AddNewInformation addNewInformation(const QStringList &files, Node *context) const override;
QVariant targetData(Core::Id role,
const ProjectExplorer::Target *target) const override;
bool setTargetData(Core::Id role, const QVariant &value,
const ProjectExplorer::Target *target) const override;
QmakeProjectManager::ProjectType projectType() const; QmakeProjectManager::ProjectType projectType() const;
QString buildDir() const; QString buildDir() const;