diff options
author | Andreas Buhr <andreas.buhr@qt.io> | 2021-06-18 15:09:58 +0200 |
---|---|---|
committer | Andreas Buhr <andreas.buhr@qt.io> | 2021-07-08 17:30:20 +0200 |
commit | 857be50b2e193b92de37c3e2bb5124d24d21a253 (patch) | |
tree | b446bb5df0b8362dd807cb1bab287b4edfa5a156 /src/tools | |
parent | 85e25d93b3b99fbeae8541586252df2cb099081d (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.txt | 2 | ||||
-rw-r--r-- | src/tools/androiddeployqt/main.cpp | 52 | ||||
-rw-r--r-- | src/tools/moc/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/tools/moc/main.cpp | 45 | ||||
-rw-r--r-- | src/tools/shared/depfile_shared.h | 80 |
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 |