summaryrefslogtreecommitdiffstats
path: root/src/tools
diff options
context:
space:
mode:
authorAndreas Buhr <andreas.buhr@qt.io>2021-06-18 15:09:58 +0200
committerAndreas Buhr <andreas.buhr@qt.io>2021-07-08 17:30:20 +0200
commit857be50b2e193b92de37c3e2bb5124d24d21a253 (patch)
treeb446bb5df0b8362dd807cb1bab287b4edfa5a156 /src/tools
parent85e25d93b3b99fbeae8541586252df2cb099081d (diff)
Let androiddeployqt write a dependency file
Let androiddeployqt write a dependency file so that the build system knows when to re-run it. Fixes: QTBUG-94567 Change-Id: I5985d707f257b22789013a74f0a6f7c4de6e5e88 Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
Diffstat (limited to 'src/tools')
-rw-r--r--src/tools/androiddeployqt/CMakeLists.txt2
-rw-r--r--src/tools/androiddeployqt/main.cpp52
-rw-r--r--src/tools/moc/CMakeLists.txt1
-rw-r--r--src/tools/moc/main.cpp45
-rw-r--r--src/tools/shared/depfile_shared.h80
5 files changed, 136 insertions, 44 deletions
diff --git a/src/tools/androiddeployqt/CMakeLists.txt b/src/tools/androiddeployqt/CMakeLists.txt
index 4eec7b8164..941e160318 100644
--- a/src/tools/androiddeployqt/CMakeLists.txt
+++ b/src/tools/androiddeployqt/CMakeLists.txt
@@ -13,6 +13,8 @@ qt_internal_add_app(androiddeployqt
QT_NO_FOREACH
PUBLIC_LIBRARIES
Qt::Core # special case
+ INCLUDE_DIRECTORIES
+ ../shared
)
set_target_properties(androiddeployqt PROPERTIES
WIN32_EXECUTABLE FALSE
diff --git a/src/tools/androiddeployqt/main.cpp b/src/tools/androiddeployqt/main.cpp
index 7993a0cfb8..fcfb6d36f5 100644
--- a/src/tools/androiddeployqt/main.cpp
+++ b/src/tools/androiddeployqt/main.cpp
@@ -42,6 +42,8 @@
#include <QDirIterator>
#include <QRegularExpression>
+#include <depfile_shared.h>
+
#include <algorithm>
#if defined(Q_OS_WIN32)
@@ -73,6 +75,8 @@ public:
static const bool mustReadOutputAnyway = true; // pclose seems to return the wrong error code unless we read the output
+static QStringList dependenciesForDepfile;
+
void deleteRecursively(const QString &dirName)
{
QDir dir(dirName);
@@ -169,6 +173,8 @@ struct Options
QString applicationArguments;
QString rootPath;
QString rccBinaryPath;
+ QString depFilePath;
+ QString buildDirectory;
QStringList qmlImportPaths;
QStringList qrcFiles;
@@ -474,6 +480,16 @@ Options parseOptions()
options.helpRequested = true;
else
options.apkPath = arguments.at(++i);
+ } else if (argument.compare(QLatin1String("--depfile"), Qt::CaseInsensitive) == 0) {
+ if (i + 1 == arguments.size())
+ options.helpRequested = true;
+ else
+ options.depFilePath = arguments.at(++i);
+ } else if (argument.compare(QLatin1String("--builddir"), Qt::CaseInsensitive) == 0) {
+ if (i + 1 == arguments.size())
+ options.helpRequested = true;
+ else
+ options.buildDirectory = arguments.at(++i);
} else if (argument.compare(QLatin1String("--sign"), Qt::CaseInsensitive) == 0) {
if (i + 2 >= arguments.size()) {
const QString keyStore = qEnvironmentVariable("QT_ANDROID_KEYSTORE_PATH");
@@ -560,6 +576,9 @@ Options parseOptions()
}
}
+ if (options.buildDirectory.isEmpty() && !options.depFilePath.isEmpty())
+ options.helpRequested = true;
+
if (options.inputFileName.isEmpty())
options.inputFileName = QLatin1String("android-%1-deployment-settings.json").arg(QDir::current().dirName());
@@ -668,6 +687,11 @@ void printHelp()
" qmlimportscanner binary is located using the Qt directory\n"
" specified in the input file.\n"
"\n"
+ " --depfile <path/to/depfile>: Output a dependency file.\n"
+ "\n"
+ " --builddir <path/to/build/directory>: build directory. Necessary when\n"
+ " generating a depfile because ninja requires relative paths.\n"
+ "\n"
" --help: Displays this information.\n",
qPrintable(QCoreApplication::arguments().at(0))
);
@@ -703,6 +727,7 @@ bool copyFileIfNewer(const QString &sourceFileName,
const Options &options,
bool forceOverwrite = false)
{
+ dependenciesForDepfile << sourceFileName;
if (QFile::exists(destinationFileName)) {
QFileInfo destinationFileInfo(destinationFileName);
QFileInfo sourceFileInfo(sourceFileName);
@@ -840,6 +865,7 @@ bool readInputFile(Options *options)
fprintf(stderr, "Cannot read from input file: %s\n", qPrintable(options->inputFileName));
return false;
}
+ dependenciesForDepfile << options->inputFileName;
QJsonDocument jsonDocument = QJsonDocument::fromJson(file.readAll());
if (jsonDocument.isNull()) {
@@ -2950,6 +2976,29 @@ enum ErrorCode
CannotCreateRcc = 21
};
+bool writeDependencyFile(const Options &options)
+{
+ if (options.verbose)
+ fprintf(stdout, "Writing dependency file.\n");
+
+ QFile depFile(options.depFilePath);
+
+ QString relativeApkPath = QDir(options.buildDirectory).relativeFilePath(options.apkPath);
+
+ if (depFile.open(QIODevice::WriteOnly)) {
+ depFile.write(escapeAndEncodeDependencyPath(relativeApkPath));
+ depFile.write(u8": ");
+
+ for (const auto &file : dependenciesForDepfile) {
+ depFile.write(u8" \\\n ");
+ depFile.write(escapeAndEncodeDependencyPath(file));
+ }
+
+ depFile.write(u8"\n");
+ }
+ return true;
+}
+
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
@@ -3090,6 +3139,9 @@ int main(int argc, char *argv[])
if (Q_UNLIKELY(options.timing))
fprintf(stdout, "[TIMING] %d ms: Installed APK\n", options.timer.elapsed());
+ if (!options.depFilePath.isEmpty())
+ writeDependencyFile(options);
+
fprintf(stdout, "Android package built successfully in %.3f ms.\n", options.timer.elapsed() / 1000.);
if (options.installApk)
diff --git a/src/tools/moc/CMakeLists.txt b/src/tools/moc/CMakeLists.txt
index 09c4927a53..88dce045f8 100644
--- a/src/tools/moc/CMakeLists.txt
+++ b/src/tools/moc/CMakeLists.txt
@@ -32,6 +32,7 @@ qt_internal_add_tool(${target_name}
INCLUDE_DIRECTORIES
${CMAKE_CURRENT_SOURCE_DIR}
../../3rdparty/tinycbor/src
+ ../shared
)
#### Keys ignored in scope 1:.:.:moc.pro:<TRUE>:
diff --git a/src/tools/moc/main.cpp b/src/tools/moc/main.cpp
index a2790fa1f7..3e98fbf2b8 100644
--- a/src/tools/moc/main.cpp
+++ b/src/tools/moc/main.cpp
@@ -27,6 +27,7 @@
**
****************************************************************************/
+#include <depfile_shared.h>
#include "preprocessor.h"
#include "moc.h"
#include "outputrevision.h"
@@ -177,50 +178,6 @@ static QStringList argumentsFromCommandLineAndFile(const QStringList &arguments,
return allArguments;
}
-// Escape characters in given path. Dependency paths are Make-style, not NMake/Jom style.
-// The paths can also be consumed by Ninja.
-// "$" replaced by "$$"
-// "#" replaced by "\#"
-// " " replaced by "\ "
-// "\#" replaced by "\\#"
-// "\ " replaced by "\\\ "
-//
-// The escape rules are according to what clang / llvm escapes when generating a Make-style
-// dependency file.
-// Is a template function, because input param can be either a QString or a QByteArray.
-template <typename T> struct CharType;
-template <> struct CharType<QString> { using type = QLatin1Char; };
-template <> struct CharType<QByteArray> { using type = char; };
-template <typename StringType>
-StringType escapeDependencyPath(const StringType &path)
-{
- using CT = typename CharType<StringType>::type;
- StringType escapedPath;
- int size = path.size();
- escapedPath.reserve(size);
- for (int i = 0; i < size; ++i) {
- if (path[i] == CT('$')) {
- escapedPath.append(CT('$'));
- } else if (path[i] == CT('#')) {
- escapedPath.append(CT('\\'));
- } else if (path[i] == CT(' ')) {
- escapedPath.append(CT('\\'));
- int backwards_it = i - 1;
- while (backwards_it > 0 && path[backwards_it] == CT('\\')) {
- escapedPath.append(CT('\\'));
- --backwards_it;
- }
- }
- escapedPath.append(path[i]);
- }
- return escapedPath;
-}
-
-QByteArray escapeAndEncodeDependencyPath(const QString &path)
-{
- return QFile::encodeName(escapeDependencyPath(path));
-}
-
int runMoc(int argc, char **argv)
{
QCoreApplication app(argc, argv);
diff --git a/src/tools/shared/depfile_shared.h b/src/tools/shared/depfile_shared.h
new file mode 100644
index 0000000000..9fb9bbb863
--- /dev/null
+++ b/src/tools/shared/depfile_shared.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** 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.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTBASE_DEPFILE_SHARED_H
+#define QTBASE_DEPFILE_SHARED_H
+
+#include <QByteArray>
+#include <QString>
+#include <QFile>
+
+// Escape characters in given path. Dependency paths are Make-style, not NMake/Jom style.
+// The paths can also be consumed by Ninja.
+// "$" replaced by "$$"
+// "#" replaced by "\#"
+// " " replaced by "\ "
+// "\#" replaced by "\\#"
+// "\ " replaced by "\\\ "
+//
+// The escape rules are according to what clang / llvm escapes when generating a Make-style
+// dependency file.
+// Is a template function, because input param can be either a QString or a QByteArray.
+template <typename T> struct CharType;
+template <> struct CharType<QString> { using type = QLatin1Char; };
+template <> struct CharType<QByteArray> { using type = char; };
+template <typename StringType>
+StringType escapeDependencyPath(const StringType &path)
+{
+ using CT = typename CharType<StringType>::type;
+ StringType escapedPath;
+ int size = path.size();
+ escapedPath.reserve(size);
+ for (int i = 0; i < size; ++i) {
+ if (path[i] == CT('$')) {
+ escapedPath.append(CT('$'));
+ } else if (path[i] == CT('#')) {
+ escapedPath.append(CT('\\'));
+ } else if (path[i] == CT(' ')) {
+ escapedPath.append(CT('\\'));
+ int backwards_it = i - 1;
+ while (backwards_it > 0 && path[backwards_it] == CT('\\')) {
+ escapedPath.append(CT('\\'));
+ --backwards_it;
+ }
+ }
+ escapedPath.append(path[i]);
+ }
+ return escapedPath;
+}
+
+static inline QByteArray escapeAndEncodeDependencyPath(const QString &path)
+{
+ return QFile::encodeName(escapeDependencyPath(path));
+}
+
+#endif // QTBASE_DEPFILE_SHARED_H