summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarvin Scholz <epirat07@gmail.com>2018-10-28 01:52:15 +0200
committerMarvin Scholz <epirat07@gmail.com>2019-06-29 02:26:23 +0200
commita03270f8917a5e5e6fd0c3ffcf3fb4f705e8cffa (patch)
tree69da567f3c422ca201b4b3df0e7d679e54bf1d27
parent9520ba5a73cd9d6cb8ef47f10837b92494c8221e (diff)
rcc: Add -d option to output a Makefile-syntax depfile
The -d option makes rcc output a dependency file with the specified file name. The resulting dependency file is useful for make or ninja based build systems. [ChangeLog][Tools][rcc] Added -d option to generate a dependency file. Fixes: QTBUG-45460 Change-Id: I495ade50f8d9865d4c00dce9373b2b6d1a6c8f2f Reviewed-by: Jörg Bornemann <joerg.bornemann@qt.io>
-rw-r--r--src/tools/rcc/main.cpp58
-rw-r--r--tests/auto/tools/rcc/data/depfile/simple.d.expected1
-rw-r--r--tests/auto/tools/rcc/data/depfile/simple.qrc6
-rw-r--r--tests/auto/tools/rcc/data/depfile/specialchar$file.txt1
-rw-r--r--tests/auto/tools/rcc/data/depfile/specialchar.d.expected1
-rw-r--r--tests/auto/tools/rcc/data/depfile/specialchar.qrc6
-rw-r--r--tests/auto/tools/rcc/tst_rcc.cpp48
7 files changed, 121 insertions, 0 deletions
diff --git a/src/tools/rcc/main.cpp b/src/tools/rcc/main.cpp
index 0eb6766b5a..ac87e48e39 100644
--- a/src/tools/rcc/main.cpp
+++ b/src/tools/rcc/main.cpp
@@ -99,6 +99,37 @@ int createProject(const QString &outFileName)
return 0;
}
+// Escapes a path for use in a Depfile (Makefile syntax)
+QString makefileEscape(const QString &filepath)
+{
+ // Always use forward slashes
+ QString result = QDir::cleanPath(filepath);
+ // Spaces are escaped with a backslash
+ result.replace(QLatin1Char(' '), QLatin1String("\\ "));
+ // Pipes are escaped with a backslash
+ result.replace(QLatin1Char('|'), QLatin1String("\\|"));
+ // Dollars are escaped with a dollar
+ result.replace(QLatin1Char('$'), QLatin1String("$$"));
+
+ return result;
+}
+
+void writeDepFile(QIODevice &iodev, const QStringList &depsList, const QString &targetName)
+{
+ QTextStream out(&iodev);
+ out << qPrintable(makefileEscape(targetName));
+ out << QLatin1Char(':');
+
+ // Write depfile
+ for (int i = 0; i < depsList.size(); ++i) {
+ out << QLatin1Char(' ');
+
+ out << qPrintable(makefileEscape(depsList.at(i)));
+ }
+
+ out << QLatin1Char('\n');
+}
+
int runRcc(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
@@ -176,6 +207,10 @@ int runRcc(int argc, char *argv[])
QStringLiteral("Only output a mapping of resource paths to file system paths defined in the .qrc file, do not generate code."));
parser.addOption(mapOption);
+ QCommandLineOption depFileOption(QStringList{QStringLiteral("d"), QStringLiteral("depfile")},
+ QStringLiteral("Write a depfile with the .qrc dependencies to <file>."), QStringLiteral("file"));
+ parser.addOption(depFileOption);
+
QCommandLineOption projectOption(QStringLiteral("project"), QStringLiteral("Output a resource file containing all files from the current directory."));
parser.addOption(projectOption);
@@ -266,6 +301,7 @@ int runRcc(int argc, char *argv[])
QString outFilename = parser.value(outputOption);
QString tempFilename = parser.value(tempOption);
+ QString depFilename = parser.value(depFileOption);
if (projectRequested) {
return createProject(outFilename);
@@ -352,6 +388,28 @@ int runRcc(int argc, char *argv[])
return 0;
}
+ // Write depfile
+ if (!depFilename.isEmpty()) {
+ QFile depout;
+ depout.setFileName(depFilename);
+
+ if (outFilename.isEmpty() || outFilename == QLatin1String("-")) {
+ const QString msg = QString::fromUtf8("Unable to write depfile when outputting to stdout!\n");
+ errorDevice.write(msg.toUtf8());
+ return 1;
+ }
+
+ if (!depout.open(QIODevice::WriteOnly | QIODevice::Text)) {
+ const QString msg = QString::fromUtf8("Unable to open depfile %1 for writing: %2\n")
+ .arg(depout.fileName(), depout.errorString());
+ errorDevice.write(msg.toUtf8());
+ return 1;
+ }
+
+ writeDepFile(depout, library.dataFiles(), outFilename);
+ depout.close();
+ }
+
QFile temp;
if (!tempFilename.isEmpty()) {
temp.setFileName(tempFilename);
diff --git a/tests/auto/tools/rcc/data/depfile/simple.d.expected b/tests/auto/tools/rcc/data/depfile/simple.d.expected
new file mode 100644
index 0000000000..a89b61bdc7
--- /dev/null
+++ b/tests/auto/tools/rcc/data/depfile/simple.d.expected
@@ -0,0 +1 @@
+simple.qrc.cpp: ../images/images/circle.png ../images/images/square.png
diff --git a/tests/auto/tools/rcc/data/depfile/simple.qrc b/tests/auto/tools/rcc/data/depfile/simple.qrc
new file mode 100644
index 0000000000..521dc4d4a0
--- /dev/null
+++ b/tests/auto/tools/rcc/data/depfile/simple.qrc
@@ -0,0 +1,6 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file>../images/images/circle.png</file>
+ <file>../images/images/square.png</file>
+</qresource>
+</RCC>
diff --git a/tests/auto/tools/rcc/data/depfile/specialchar$file.txt b/tests/auto/tools/rcc/data/depfile/specialchar$file.txt
new file mode 100644
index 0000000000..5da849b5c6
--- /dev/null
+++ b/tests/auto/tools/rcc/data/depfile/specialchar$file.txt
@@ -0,0 +1 @@
+ABC
diff --git a/tests/auto/tools/rcc/data/depfile/specialchar.d.expected b/tests/auto/tools/rcc/data/depfile/specialchar.d.expected
new file mode 100644
index 0000000000..9dd1af0958
--- /dev/null
+++ b/tests/auto/tools/rcc/data/depfile/specialchar.d.expected
@@ -0,0 +1 @@
+specialchar.qrc.cpp: specialchar$$file.txt ../images/images/subdir/triangle.png
diff --git a/tests/auto/tools/rcc/data/depfile/specialchar.qrc b/tests/auto/tools/rcc/data/depfile/specialchar.qrc
new file mode 100644
index 0000000000..133cbc7655
--- /dev/null
+++ b/tests/auto/tools/rcc/data/depfile/specialchar.qrc
@@ -0,0 +1,6 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file>../images/images/subdir/triangle.png</file>
+ <file>specialchar$file.txt</file>
+</qresource>
+</RCC>
diff --git a/tests/auto/tools/rcc/tst_rcc.cpp b/tests/auto/tools/rcc/tst_rcc.cpp
index 24fd79cf19..42a4134e5f 100644
--- a/tests/auto/tools/rcc/tst_rcc.cpp
+++ b/tests/auto/tools/rcc/tst_rcc.cpp
@@ -89,6 +89,9 @@ private slots:
void readback_data();
void readback();
+ void depFileGeneration_data();
+ void depFileGeneration();
+
void python();
void cleanupTestCase();
@@ -416,6 +419,49 @@ void tst_rcc::readback()
QCOMPARE(resourceData, fileSystemData);
}
+void tst_rcc::depFileGeneration_data()
+{
+ QTest::addColumn<QString>("qrcfile");
+ QTest::addColumn<QString>("depfile");
+ QTest::addColumn<QString>("expected");
+
+ QTest::newRow("simple") << "simple.qrc" << "simple.d" << "simple.d.expected";
+ QTest::newRow("specialchar") << "specialchar.qrc" << "specialchar.d" << "specialchar.d.expected";
+}
+
+void tst_rcc::depFileGeneration()
+{
+ QFETCH(QString, qrcfile);
+ QFETCH(QString, depfile);
+ QFETCH(QString, expected);
+ const QString directory = m_dataPath + QLatin1String("/depfile");
+
+ QProcess process;
+ process.setWorkingDirectory(directory);
+ process.start(m_rcc, { "-d", depfile, "-o", qrcfile + ".cpp", qrcfile });
+ QVERIFY2(process.waitForStarted(), msgProcessStartFailed(process).constData());
+ if (!process.waitForFinished()) {
+ process.kill();
+ QFAIL(msgProcessTimeout(process).constData());
+ }
+ QVERIFY2(process.exitStatus() == QProcess::NormalExit,
+ msgProcessCrashed(process).constData());
+ QVERIFY2(process.exitCode() == 0,
+ msgProcessFailed(process).constData());
+
+ QFile depFileOutput(directory + QLatin1String("/") + depfile);
+ QVERIFY(depFileOutput.open(QIODevice::ReadOnly | QIODevice::Text));
+ QByteArray depFileData = depFileOutput.readAll();
+ depFileOutput.close();
+
+ QFile depFileExpected(directory + QLatin1String("/") + expected);
+ QVERIFY(depFileExpected.open(QIODevice::ReadOnly | QIODevice::Text));
+ QByteArray expectedData = depFileExpected.readAll();
+ depFileExpected.close();
+
+ QCOMPARE(depFileData, expectedData);
+}
+
void tst_rcc::python()
{
const QString path = m_dataPath + QLatin1String("/sizes");
@@ -450,6 +496,8 @@ void tst_rcc::cleanupTestCase()
{
QDir dataDir(m_dataPath + QLatin1String("/binary"));
QFileInfoList entries = dataDir.entryInfoList(QStringList() << QLatin1String("*.rcc"));
+ QDir dataDepDir(m_dataPath + QLatin1String("/depfile"));
+ entries += dataDepDir.entryInfoList({QLatin1String("*.d"), QLatin1String("*.qrc.cpp")});
foreach (const QFileInfo &entry, entries)
QFile::remove(entry.absoluteFilePath());
}