aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/android/androidbuildapkstep.cpp74
-rw-r--r--src/plugins/android/androidbuildapkstep.h3
-rw-r--r--src/plugins/android/androiddeployqtstep.cpp84
3 files changed, 161 insertions, 0 deletions
diff --git a/src/plugins/android/androidbuildapkstep.cpp b/src/plugins/android/androidbuildapkstep.cpp
index 6cbe6367713..0ed1c12516a 100644
--- a/src/plugins/android/androidbuildapkstep.cpp
+++ b/src/plugins/android/androidbuildapkstep.cpp
@@ -1045,6 +1045,13 @@ QtTaskTree::GroupItem AndroidBuildApkStep::runRecipe()
Task::Warning);
return SetupResult::StopWithSuccess;
}
+
+ if (!needsApkRegeneration()) {
+ emit addOutput(Tr::tr("No changes detected, skipping APK regeneration."),
+ OutputFormat::NormalMessage);
+ return SetupResult::StopWithSuccess;
+ }
+
if (setupHelper())
return SetupResult::Continue;
reportWarningOrError(Tr::tr("Cannot set up \"%1\", not building an APK.")
@@ -1052,6 +1059,7 @@ QtTaskTree::GroupItem AndroidBuildApkStep::runRecipe()
return SetupResult::StopWithError;
};
const auto onDone = [this] {
+ updateBuildTimestamp();
if (m_openPackageLocationForRun)
QTimer::singleShot(0, this, &AndroidBuildApkStep::showInGraphicalShell);
};
@@ -1064,6 +1072,72 @@ QtTaskTree::GroupItem AndroidBuildApkStep::runRecipe()
return root;
}
+bool AndroidBuildApkStep::needsApkRegeneration()
+{
+ const FilePath androidBuildDir = androidBuildDirectory(buildConfiguration());
+ const FilePath apkOutputDir = androidBuildDir / "build/outputs/apk";
+ if (!apkOutputDir.exists()) {
+ emit addOutput(Tr::tr("APK output directory does not exist, regenerating APK."),
+ OutputFormat::NormalMessage);
+ return true;
+ }
+
+ const FilePath timestampFile = androidBuildDir / "AndroidBuildTimestamp";
+ if (!m_lastBuildTime.isValid()) {
+ if (timestampFile.exists()) {
+ m_lastBuildTime = timestampFile.lastModified();
+ qCDebug(buildapkstepLog) << "Loaded build timestamp from file:" << m_lastBuildTime;
+ } else {
+ emit addOutput(Tr::tr("First build in session, regenerating APK."),
+ OutputFormat::NormalMessage);
+ return true;
+ }
+ }
+
+ if (m_inputFile.exists() && m_inputFile.lastModified() > m_lastBuildTime) {
+ emit addOutput(Tr::tr("Deployment settings changed since last build, regenerating APK."),
+ OutputFormat::NormalMessage);
+ return true;
+ }
+
+ BuildSystem *bs = buildSystem();
+ const QStringList androidAbis = bs->property(Constants::AndroidAbis).toStringList();
+ for (const QString &abi : androidAbis) {
+ const FilePath libsDir = androidBuildDir / "libs" / abi;
+ if (libsDir.exists()) {
+ const FilePaths files = libsDir.dirEntries(QDir::Files);
+ for (const FilePath &file : files) {
+ if (file.lastModified() > m_lastBuildTime) {
+ emit addOutput(Tr::tr("Library %1 changed since last build, regenerating APK.")
+ .arg(file.fileName()),
+ OutputFormat::NormalMessage);
+ return true;
+ }
+ }
+ }
+ }
+
+ const QString buildKey = buildConfiguration()->activeBuildKey();
+ const ProjectNode *node = project()->findNodeForBuildKey(buildKey);
+ if (node) {
+ const FilePath apk = FilePath::fromString(node->data(Constants::AndroidApk).toString());
+ if (!apk.isEmpty() && apk.exists() && apk.lastModified() > m_lastBuildTime) {
+ emit addOutput(Tr::tr("Application binary changed since last build, regenerating APK."),
+ OutputFormat::NormalMessage);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void AndroidBuildApkStep::updateBuildTimestamp()
+{
+ m_lastBuildTime = QDateTime::currentDateTime();
+ const FilePath timestampFile = androidBuildDirectory(buildConfiguration()) / "AndroidBuildTimestamp";
+ timestampFile.writeFileContents(QByteArray());
+}
+
void AndroidBuildApkStep::reportWarningOrError(const QString &message, Task::TaskType type)
{
qCDebug(buildapkstepLog) << message;
diff --git a/src/plugins/android/androidbuildapkstep.h b/src/plugins/android/androidbuildapkstep.h
index 3d3a6e025b5..34b08607cb7 100644
--- a/src/plugins/android/androidbuildapkstep.h
+++ b/src/plugins/android/androidbuildapkstep.h
@@ -65,6 +65,8 @@ private:
void reportWarningOrError(const QString &message, ProjectExplorer::Task::TaskType type);
void updateBuildToolsVersionInJsonFile();
+ bool needsApkRegeneration();
+ void updateBuildTimestamp();
bool m_signPackage = false;
bool m_openPackageLocationForRun = false;
@@ -81,6 +83,7 @@ private:
ProjectExplorer::ProcessParameters m_concealedParams;
bool m_skipBuilding = false;
Utils::FilePath m_inputFile;
+ QDateTime m_lastBuildTime;
};
void setupAndroidBuildApkStep();
diff --git a/src/plugins/android/androiddeployqtstep.cpp b/src/plugins/android/androiddeployqtstep.cpp
index cccc75347c3..04ca2d76606 100644
--- a/src/plugins/android/androiddeployqtstep.cpp
+++ b/src/plugins/android/androiddeployqtstep.cpp
@@ -40,6 +40,7 @@
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
+#include <QDateTime>
#include <QLoggingCategory>
#include <QMessageBox>
#include <QPushButton>
@@ -114,6 +115,8 @@ private:
void reportWarningOrError(const QString &message, Task::TaskType type);
void setInstallApkError(const QString &details);
+ bool needsPackageRegeneration();
+ void updateDeploymentTimestamp();
QString m_serialNumber;
QString m_avdName;
@@ -128,6 +131,7 @@ private:
Environment m_environment;
Task m_installApkError;
QSingleTaskTreeRunner m_taskTreeRunner;
+ QDateTime m_lastDeploymentTime;
};
AndroidDeployQtStep::AndroidDeployQtStep(BuildStepList *parent, Id id)
@@ -294,6 +298,79 @@ bool AndroidDeployQtStep::init()
return true;
}
+bool AndroidDeployQtStep::needsPackageRegeneration()
+{
+ const FilePath jsonFile = AndroidQtVersion::androidDeploymentSettings(buildConfiguration());
+ if (!jsonFile.exists()) {
+ emit addOutput(Tr::tr("Deployment settings JSON file does not exist, regenerating package."),
+ OutputFormat::NormalMessage);
+ return true;
+ }
+
+ const FilePath androidBuildDir = androidBuildDirectory(buildConfiguration());
+ const FilePath apkOutputDir = androidBuildDir / "build/outputs/apk";
+ if (!apkOutputDir.exists()) {
+ emit addOutput(Tr::tr("APK output directory does not exist, regenerating package."),
+ OutputFormat::NormalMessage);
+ return true;
+ }
+
+ const FilePath timestampFile = androidBuildDir / "AndroidDeployTimestamp";
+ if (!m_lastDeploymentTime.isValid()) {
+ if (timestampFile.exists()) {
+ m_lastDeploymentTime = timestampFile.lastModified();
+ } else {
+ emit addOutput(Tr::tr("First deployment in session, regenerating package."),
+ OutputFormat::NormalMessage);
+ return true;
+ }
+ }
+
+ const BuildSystem *bs = buildSystem();
+ const QString buildKey = buildConfiguration()->activeBuildKey();
+
+ if (jsonFile.lastModified() > m_lastDeploymentTime) {
+ emit addOutput(Tr::tr("Deployment settings changed since last deploy, regenerating package."),
+ OutputFormat::NormalMessage);
+ return true;
+ }
+
+ const ProjectNode *node = project()->findNodeForBuildKey(buildKey);
+ if (node) {
+ const FilePath apk = FilePath::fromString(node->data(Constants::AndroidApk).toString());
+ if (!apk.isEmpty() && apk.exists() && apk.lastModified() > m_lastDeploymentTime) {
+ emit addOutput(Tr::tr("Application binary changed since last deploy, regenerating package."),
+ OutputFormat::NormalMessage);
+ return true;
+ }
+ }
+
+ const QStringList androidAbis = bs->property(Constants::AndroidAbis).toStringList();
+ for (const QString &abi : androidAbis) {
+ const FilePath libsDir = androidBuildDir / "libs" / abi;
+ if (libsDir.exists()) {
+ const FilePaths files = libsDir.dirEntries(QDir::Files);
+ for (const FilePath &file : files) {
+ if (file.lastModified() > m_lastDeploymentTime) {
+ emit addOutput(Tr::tr("Library %1 changed since last deploy, regenerating package.")
+ .arg(file.fileName()),
+ OutputFormat::NormalMessage);
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+void AndroidDeployQtStep::updateDeploymentTimestamp()
+{
+ m_lastDeploymentTime = QDateTime::currentDateTime();
+ const FilePath timestampFile = androidBuildDirectory(buildConfiguration()) / "AndroidDeployTimestamp";
+ timestampFile.writeFileContents(QByteArray());
+}
+
GroupItem AndroidDeployQtStep::runRecipe()
{
const Storage<QString> serialNumberStorage;
@@ -357,6 +434,12 @@ Group AndroidDeployQtStep::deployRecipe()
};
const auto onInstallSetup = [this, storage](Process &process) {
+ if (!needsPackageRegeneration()) {
+ emit addOutput(Tr::tr("No changes detected, skipping package regeneration."),
+ OutputFormat::NormalMessage);
+ return SetupResult::StopWithSuccess;
+ }
+
CommandLine cmd(m_command);
if (m_apkPath.isEmpty()) {
cmd.addArgs(m_androiddeployqtArgs.arguments(), CommandLine::Raw);
@@ -397,6 +480,7 @@ Group AndroidDeployQtStep::deployRecipe()
if (exitStatus == QProcess::NormalExit && exitCode == 0) {
emit addOutput(Tr::tr("The process \"%1\" exited normally.").arg(m_command.toUserOutput()),
OutputFormat::NormalMessage);
+ updateDeploymentTimestamp();
} else if (exitStatus == QProcess::NormalExit) {
const QString error = Tr::tr("The process \"%1\" exited with code %2.")
.arg(m_command.toUserOutput(), QString::number(exitCode));