diff options
-rw-r--r-- | src/lib/buildgraph/buildgraphloader.cpp | 2 | ||||
-rw-r--r-- | src/lib/language/language.cpp | 50 | ||||
-rw-r--r-- | src/lib/language/language.h | 10 | ||||
-rw-r--r-- | tests/auto/blackbox/testdata/propertyChanges/modules/TestModule/module.qbs | 28 | ||||
-rw-r--r-- | tests/auto/blackbox/testdata/propertyChanges/project.qbs | 4 | ||||
-rw-r--r-- | tests/auto/blackbox/testdata/propertyChanges/ruletest.qbs | 7 | ||||
-rw-r--r-- | tests/auto/blackbox/testdata/propertyChanges/test.in | 1 | ||||
-rw-r--r-- | tests/auto/blackbox/tst_blackbox.cpp | 71 |
8 files changed, 161 insertions, 12 deletions
diff --git a/src/lib/buildgraph/buildgraphloader.cpp b/src/lib/buildgraph/buildgraphloader.cpp index 130784b31..aa2a5090e 100644 --- a/src/lib/buildgraph/buildgraphloader.cpp +++ b/src/lib/buildgraph/buildgraphloader.cpp @@ -413,6 +413,8 @@ bool BuildGraphLoader::checkProductForChanges(const ResolvedProductPtr &restored { return !transformerListsAreEqual(restoredProduct->transformers, newlyResolvedProduct->transformers) + || !ruleListsAreEqual(restoredProduct->rules.toList(), + newlyResolvedProduct->rules.toList()) || !dependenciesAreEqual(restoredProduct, newlyResolvedProduct) || checkForPropertyChanges(restoredProduct, newlyResolvedProduct); // TODO: Check for more stuff. diff --git a/src/lib/language/language.cpp b/src/lib/language/language.cpp index 3fee4a759..79a0cd260 100644 --- a/src/lib/language/language.cpp +++ b/src/lib/language/language.cpp @@ -987,6 +987,7 @@ template<typename T> bool listsAreEqual(const QList<T> &l1, const QList<T> &l2) QString keyFromElem(const SourceArtifactPtr &sa) { return sa->absoluteFilePath; } QString keyFromElem(const ResolvedTransformerConstPtr &t) { return t->transform->sourceCode; } +QString keyFromElem(const RulePtr &r) { return r->toString(); } bool operator==(const SourceArtifact &sa1, const SourceArtifact &sa2) { @@ -1020,5 +1021,54 @@ bool transformerListsAreEqual(const QList<ResolvedTransformerConstPtr> &l1, return listsAreEqual(l1, l2); } +bool operator==(const Rule &r1, const Rule &r2) +{ + if (&r1 == &r2) + return true; + if (!&r1 != !&r2) + return false; + if (r1.artifacts.count() != r2.artifacts.count()) + return false; + for (int i = 0; i < r1.artifacts.count(); ++i) { + if (*r1.artifacts.at(i) != *r2.artifacts.at(i)) + return false; + } + + return r1.module->name == r2.module->name + && r1.script->sourceCode == r2.script->sourceCode + && r1.inputs == r2.inputs + && r1.auxiliaryInputs == r2.auxiliaryInputs + && r1.usings == r2.usings + && r1.explicitlyDependsOn == r2.explicitlyDependsOn + && r1.multiplex == r2.multiplex; +} + +bool ruleListsAreEqual(const QList<RulePtr> &l1, const QList<RulePtr> &l2) +{ + return listsAreEqual(l1, l2); +} + +bool operator==(const RuleArtifact &a1, const RuleArtifact &a2) +{ + if (&a1 == &a2) + return true; + if (!&a1 != !&a2) + return false; + return a1.fileName == a2.fileName + && a1.fileTags == a2.fileTags + && a1.alwaysUpdated == a2.alwaysUpdated + && a1.bindings.toList().toSet() == a2.bindings.toList().toSet(); +} + +bool operator==(const RuleArtifact::Binding &b1, const RuleArtifact::Binding &b2) +{ + return b1.code == b2.code && b1.name == b2.name; +} + +uint qHash(const RuleArtifact::Binding &b) +{ + return qHash(qMakePair(b.code, b.name.join(QLatin1String(",")))); +} + } // namespace Internal } // namespace qbs diff --git a/src/lib/language/language.h b/src/lib/language/language.h index a467adc4d..77f0425e4 100644 --- a/src/lib/language/language.h +++ b/src/lib/language/language.h @@ -116,6 +116,13 @@ private: void load(PersistentPool &pool); void store(PersistentPool &pool) const; }; +uint qHash(const RuleArtifact::Binding &b); +bool operator==(const RuleArtifact::Binding &b1, const RuleArtifact::Binding &b2); +inline bool operator!=(const RuleArtifact::Binding &b1, const RuleArtifact::Binding &b2) { + return !(b1 == b2); +} +bool operator==(const RuleArtifact &a1, const RuleArtifact &a2); +inline bool operator!=(const RuleArtifact &a1, const RuleArtifact &a2) { return !(a1 == a2); } class SourceArtifact : public PersistentObject { @@ -292,6 +299,9 @@ private: void load(PersistentPool &pool); void store(PersistentPool &pool) const; }; +bool operator==(const Rule &r1, const Rule &r2); +inline bool operator!=(const Rule &r1, const Rule &r2) { return !(r1 == r2); } +bool ruleListsAreEqual(const QList<RulePtr> &l1, const QList<RulePtr> &l2); class ResolvedTransformer : public PersistentObject { diff --git a/tests/auto/blackbox/testdata/propertyChanges/modules/TestModule/module.qbs b/tests/auto/blackbox/testdata/propertyChanges/modules/TestModule/module.qbs new file mode 100644 index 000000000..ef14d3f47 --- /dev/null +++ b/tests/auto/blackbox/testdata/propertyChanges/modules/TestModule/module.qbs @@ -0,0 +1,28 @@ +import qbs +import qbs.File + +Module { + FileTagger { + pattern: "*.in" + fileTags: "test-input" + } + + Rule { + inputs: ['test-input'] + Artifact { + fileTags: "test-output" + fileName: input.fileName + ".out" + } + + prepare: { + var cmd = new JavaScriptCommand(); + cmd.highlight = "codegen"; + cmd.description = "Making output from input"; + cmd.sourceCode = function() { + // print('Change in source code'); + File.copy(input.fileName, output.fileName); + } + return cmd; + } + } +} diff --git a/tests/auto/blackbox/testdata/propertyChanges/project.qbs b/tests/auto/blackbox/testdata/propertyChanges/project.qbs index 4be63101f..9bccb5d06 100644 --- a/tests/auto/blackbox/testdata/propertyChanges/project.qbs +++ b/tests/auto/blackbox/testdata/propertyChanges/project.qbs @@ -44,4 +44,8 @@ Project { } } } + + references: "ruletest.qbs" + + qbsSearchPaths: "." } diff --git a/tests/auto/blackbox/testdata/propertyChanges/ruletest.qbs b/tests/auto/blackbox/testdata/propertyChanges/ruletest.qbs new file mode 100644 index 000000000..02088da7b --- /dev/null +++ b/tests/auto/blackbox/testdata/propertyChanges/ruletest.qbs @@ -0,0 +1,7 @@ +import qbs + +Product { + type: "test-output" + Depends { name: "TestModule" } + files: "test.in" +} diff --git a/tests/auto/blackbox/testdata/propertyChanges/test.in b/tests/auto/blackbox/testdata/propertyChanges/test.in new file mode 100644 index 000000000..8633abf18 --- /dev/null +++ b/tests/auto/blackbox/testdata/propertyChanges/test.in @@ -0,0 +1 @@ +blubb diff --git a/tests/auto/blackbox/tst_blackbox.cpp b/tests/auto/blackbox/tst_blackbox.cpp index 30b62dc41..4161a6d91 100644 --- a/tests/auto/blackbox/tst_blackbox.cpp +++ b/tests/auto/blackbox/tst_blackbox.cpp @@ -1055,41 +1055,45 @@ void TestBlackbox::propertyChanges() { QDir::setCurrent(testDataDir + "/propertyChanges"); QFile projectFile("project.qbs"); + QbsRunParameters params(QStringList() << "-f" << "project.qbs"); // Initial build. - QCOMPARE(runQbs(), 0); + QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("compiling source1.cpp")); QVERIFY(m_qbsStdout.contains("compiling source2.cpp")); QVERIFY(m_qbsStdout.contains("compiling source3.cpp")); QVERIFY(m_qbsStdout.contains("compiling lib.cpp")); QVERIFY(m_qbsStdout.contains("linking product 1.debug")); QVERIFY(m_qbsStdout.contains("generated.txt")); + QVERIFY(m_qbsStdout.contains("Making output from input")); QFile generatedFile(buildDir + QLatin1String("/generated.txt")); QVERIFY(generatedFile.open(QIODevice::ReadOnly)); QCOMPARE(generatedFile.readAll(), QByteArray("contents 1")); generatedFile.close(); // Incremental build with no changes. - QCOMPARE(runQbs(), 0); + QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("compiling source1.cpp")); QVERIFY(!m_qbsStdout.contains("compiling source2.cpp")); QVERIFY(!m_qbsStdout.contains("compiling source3.cpp")); QVERIFY(!m_qbsStdout.contains("compiling lib.cpp.cpp")); QVERIFY(!m_qbsStdout.contains("linking")); QVERIFY(!m_qbsStdout.contains("generated.txt")); + QVERIFY(!m_qbsStdout.contains("Making output from input")); // Incremental build with no changes, but updated project file timestamp. waitForNewTimestamp(); QVERIFY(projectFile.open(QIODevice::ReadWrite | QIODevice::Append)); projectFile.write("\n"); projectFile.close(); - QCOMPARE(runQbs(), 0); + QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("compiling source1.cpp")); QVERIFY(!m_qbsStdout.contains("compiling source2.cpp")); QVERIFY(!m_qbsStdout.contains("compiling source3.cpp")); QVERIFY(!m_qbsStdout.contains("compiling lib.cpp")); QVERIFY(!m_qbsStdout.contains("linking")); QVERIFY(!m_qbsStdout.contains("generated.txt")); + QVERIFY(!m_qbsStdout.contains("Making output from input")); // Incremental build, input property changed for first product waitForNewTimestamp(); @@ -1099,13 +1103,14 @@ void TestBlackbox::propertyChanges() projectFile.resize(0); projectFile.write(contents); projectFile.close(); - QCOMPARE(runQbs(), 0); + QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("compiling source1.cpp")); QVERIFY(m_qbsStdout.contains("linking product 1.debug")); QVERIFY(!m_qbsStdout.contains("linking product 2")); QVERIFY(!m_qbsStdout.contains("linking product 3")); QVERIFY(!m_qbsStdout.contains("linking library")); QVERIFY(!m_qbsStdout.contains("generated.txt")); + QVERIFY(!m_qbsStdout.contains("Making output from input")); // Incremental build, input property changed via project for second product. waitForNewTimestamp(); @@ -1115,26 +1120,29 @@ void TestBlackbox::propertyChanges() projectFile.resize(0); projectFile.write(contents); projectFile.close(); - QCOMPARE(runQbs(), 0); + QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("linking product 1")); QVERIFY(m_qbsStdout.contains("compiling source2.cpp")); QVERIFY(!m_qbsStdout.contains("linking product 3")); QVERIFY(!m_qbsStdout.contains("generated.txt")); + QVERIFY(!m_qbsStdout.contains("Making output from input")); // Incremental build, input property changed via command line for second product. - QCOMPARE(runQbs(QbsRunParameters(QLatin1String("project.projectDefines:blubb002"))), 0); + params.arguments << "project.projectDefines:blubb002"; + QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("linking product 1")); QVERIFY(m_qbsStdout.contains("compiling source2.cpp")); QVERIFY(!m_qbsStdout.contains("linking product 3")); QVERIFY(!m_qbsStdout.contains("generated.txt")); - QCOMPARE(runQbs(), 0); + params.arguments.removeLast(); + QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("linking product 1")); QVERIFY(m_qbsStdout.contains("compiling source2.cpp")); QVERIFY(!m_qbsStdout.contains("linking product 3")); QVERIFY(!m_qbsStdout.contains("generated.txt")); + QVERIFY(!m_qbsStdout.contains("Making output from input")); // Incremental build, input property changed via environment for third product. - QbsRunParameters params; params.environment.insert("QBS_BLACKBOX_DEFINE", "newvalue"); QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("linking product 1")); @@ -1147,21 +1155,25 @@ void TestBlackbox::propertyChanges() QVERIFY(!m_qbsStdout.contains("linking product 2")); QVERIFY(m_qbsStdout.contains("compiling source3.cpp")); QVERIFY(!m_qbsStdout.contains("generated.txt")); + QVERIFY(!m_qbsStdout.contains("Making output from input")); // Incremental build, module property changed via command line. - QCOMPARE(runQbs(QbsRunParameters(QLatin1String("qbs.enableDebugCode:false"))), 0); + params.arguments << "qbs.enableDebugCode:false"; + QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("compiling source1.cpp")); QVERIFY(m_qbsStdout.contains("linking product 1.release")); QVERIFY(m_qbsStdout.contains("compiling source2.cpp")); QVERIFY(m_qbsStdout.contains("compiling source3.cpp")); QVERIFY(m_qbsStdout.contains("compiling lib.cpp")); QVERIFY(!m_qbsStdout.contains("generated.txt")); - QCOMPARE(runQbs(), 0); + params.arguments.removeLast(); + QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("compiling source1.cpp")); QVERIFY(m_qbsStdout.contains("linking product 1.debug")); QVERIFY(m_qbsStdout.contains("compiling source2.cpp")); QVERIFY(m_qbsStdout.contains("compiling source3.cpp")); QVERIFY(!m_qbsStdout.contains("generated.txt")); + QVERIFY(!m_qbsStdout.contains("Making output from input")); // Incremental build, non-essential dependency removed. waitForNewTimestamp(); @@ -1171,12 +1183,13 @@ void TestBlackbox::propertyChanges() projectFile.resize(0); projectFile.write(contents); projectFile.close(); - QCOMPARE(runQbs(), 0); + QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("linking product 1")); QVERIFY(m_qbsStdout.contains("linking product 2")); QVERIFY(!m_qbsStdout.contains("linking product 3")); QVERIFY(!m_qbsStdout.contains("linking library")); QVERIFY(!m_qbsStdout.contains("generated.txt")); + QVERIFY(!m_qbsStdout.contains("Making output from input")); // Incremental build, prepare script of a transformer changed. waitForNewTimestamp(); @@ -1186,15 +1199,49 @@ void TestBlackbox::propertyChanges() projectFile.resize(0); projectFile.write(contents); projectFile.close(); - QCOMPARE(runQbs(), 0); + QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("compiling source1.cpp")); QVERIFY(!m_qbsStdout.contains("compiling source2.cpp")); QVERIFY(!m_qbsStdout.contains("compiling source3.cpp")); QVERIFY(!m_qbsStdout.contains("compiling lib.cpp")); QVERIFY(m_qbsStdout.contains("generated.txt")); + QVERIFY(!m_qbsStdout.contains("Making output from input")); QVERIFY(generatedFile.open(QIODevice::ReadOnly)); QCOMPARE(generatedFile.readAll(), QByteArray("contents 2")); generatedFile.close(); + + // Incremental build, prepare script of a rule in a module changed. + waitForNewTimestamp(); + QFile moduleFile("modules/TestModule/module.qbs"); + QVERIFY(moduleFile.open(QIODevice::ReadWrite)); + contents = moduleFile.readAll(); + contents.replace("// print('Change in source code')", "print('Change in source code')"); + moduleFile.resize(0); + moduleFile.write(contents); + moduleFile.close(); + QCOMPARE(runQbs(params), 0); + QVERIFY(!m_qbsStdout.contains("compiling source1.cpp")); + QVERIFY(!m_qbsStdout.contains("compiling source2.cpp")); + QVERIFY(!m_qbsStdout.contains("compiling source3.cpp")); + QVERIFY(!m_qbsStdout.contains("compiling lib.cpp")); + QVERIFY(!m_qbsStdout.contains("generated.txt")); + QVERIFY(m_qbsStdout.contains("Making output from input")); + + // Incremental build, irrelevant file tag of a rule in a module changed. + waitForNewTimestamp(); + QVERIFY(moduleFile.open(QIODevice::ReadWrite)); + contents = moduleFile.readAll(); + contents.replace("inputs: ['test-input']", "inputs: ['test-input', 'hupe']"); + moduleFile.resize(0); + moduleFile.write(contents); + moduleFile.close(); + QCOMPARE(runQbs(params), 0); + QVERIFY(!m_qbsStdout.contains("compiling source1.cpp")); + QVERIFY(!m_qbsStdout.contains("compiling source2.cpp")); + QVERIFY(!m_qbsStdout.contains("compiling source3.cpp")); + QVERIFY(!m_qbsStdout.contains("compiling lib.cpp")); + QVERIFY(!m_qbsStdout.contains("generated.txt")); + QVERIFY(!m_qbsStdout.contains("Making output from input")); } void TestBlackbox::disabledProduct() |