diff options
author | Christian Kandeler <christian.kandeler@qt.io> | 2020-03-05 10:15:11 +0100 |
---|---|---|
committer | Christian Kandeler <christian.kandeler@qt.io> | 2020-03-05 11:04:24 +0000 |
commit | ee2509dcc7ed822e6b4a67016b83934e6375bbf3 (patch) | |
tree | dbe2dacecfd70e829687e62f82aa43b10dce1298 /tests | |
parent | 8eebdd24745c57be3baf0d56d3ac6780a38921f1 (diff) |
Rule execution: Fix potential infinite loop
Dependency scanning can generate inverse dependencies. For instance, a
Qt C++ file "myobject.cpp" containing the Q_OBJECT macro will typically
include a file "myobject.moc", which is generated from the cpp file.
When scanning the inputs of "myobject.moc", the artifact will encounter
itself as a scan dependency. There is code that prevents a dependency
cycle in this case.
Let's now consider the case where such a rule has a second output
artifact: When scanning the inputs of that artifact, we will encounter
the first artifact as a scan dependency. This case was not handled,
leading to an infinite loop in rule execution. We fix this by rejecting
scan dependencies that have the same transformer as the artifact whose
inputs are being scanned.
Change-Id: I767ceaad387c2e315738070e01ef9322764afb65
Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
Diffstat (limited to 'tests')
4 files changed, 43 insertions, 0 deletions
diff --git a/tests/auto/blackbox/testdata/dependency-scanning-loop/dependency-scanning-loop.qbs b/tests/auto/blackbox/testdata/dependency-scanning-loop/dependency-scanning-loop.qbs new file mode 100644 index 000000000..ac8e7258c --- /dev/null +++ b/tests/auto/blackbox/testdata/dependency-scanning-loop/dependency-scanning-loop.qbs @@ -0,0 +1,34 @@ +import qbs.FileInfo +import qbs.TextFile + +CppApplication { + name: "app" + cpp.includePaths: buildDirectory + Group { + files: "main.cpp" + fileTags: ["cpp", "custom.in"] + } + Rule { + inputs: "custom.in" + Artifact { + filePath: FileInfo.completeBaseName(input.filePath) + ".h" + fileTags: "hpp" + } + Artifact { + filePath: "custom.txt" + fileTags: "whatever" + } + prepare: { + var cmd = new JavaScriptCommand(); + cmd.description = "generating " + outputs.hpp[0].fileName; + cmd.sourceCode = function() { + var f = new TextFile(outputs.hpp[0].filePath, TextFile.WriteOnly); + f.writeLine("int main() {}"); + f.close(); + f = new TextFile(outputs.whatever[0].filePath, TextFile.WriteOnly); + f.close(); + } + return cmd; + } + } +} diff --git a/tests/auto/blackbox/testdata/dependency-scanning-loop/main.cpp b/tests/auto/blackbox/testdata/dependency-scanning-loop/main.cpp new file mode 100644 index 000000000..5e8dda41b --- /dev/null +++ b/tests/auto/blackbox/testdata/dependency-scanning-loop/main.cpp @@ -0,0 +1 @@ +#include <main.h> diff --git a/tests/auto/blackbox/tst_blackbox.cpp b/tests/auto/blackbox/tst_blackbox.cpp index 324723ce3..1a3a1943c 100644 --- a/tests/auto/blackbox/tst_blackbox.cpp +++ b/tests/auto/blackbox/tst_blackbox.cpp @@ -942,6 +942,13 @@ void TestBlackbox::dependenciesProperty() QCOMPARE(product2_cpp_defines.first().toString(), QLatin1String("DIGEDAG")); } +void TestBlackbox::dependencyScanningLoop() +{ + QDir::setCurrent(testDataDir + "/dependency-scanning-loop"); + QCOMPARE(runQbs(), 0); + QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); +} + void TestBlackbox::deprecatedProperty() { QDir::setCurrent(testDataDir + "/deprecated-property"); diff --git a/tests/auto/blackbox/tst_blackbox.h b/tests/auto/blackbox/tst_blackbox.h index ec6b9f7e4..fb36d85e9 100644 --- a/tests/auto/blackbox/tst_blackbox.h +++ b/tests/auto/blackbox/tst_blackbox.h @@ -86,6 +86,7 @@ private slots: void conanfileProbe(); void cpuFeatures(); void dependenciesProperty(); + void dependencyScanningLoop(); void deprecatedProperty(); void disappearedProfile(); void discardUnusedData(); |