summaryrefslogtreecommitdiff
path: root/src/lib/buildgraph/executor.cpp
diff options
context:
space:
mode:
authorJoerg Bornemann <joerg.bornemann@digia.com>2013-08-02 13:57:26 +0200
committerJoerg Bornemann <joerg.bornemann@digia.com>2013-11-27 11:49:01 +0100
commit006824f89c4f298f19c45f4f4585b4452cd2d2b9 (patch)
tree0007c73137e7d167cefa4e5611a01803e69fa5fd /src/lib/buildgraph/executor.cpp
parentdbb39fc1fce3686a5161d68e89e96086fc664556 (diff)
downloadqbs-006824f89c4f298f19c45f4f4585b4452cd2d2b9.tar.gz
introduce class BuildGraphNodedynablaster
To support different types of nodes in the build graph, we introduce the base class BuildGraphNode. Artifact now derives from BuildGraphNode. A - yet unused - RuleNode class is introduced that represents a rule in the build graph. Change-Id: Ie1ad5e7a9e65bfd5f99d3e824737516053de0f94 ***new artifacts hash in ProductBuildData Change-Id: I50521ec64f734bfb3662759076fa5e7912ac084e ***automoc fixup Change-Id: Ie2bb228ae38d63deccc600d67d283bc3beda9fec slightly nicer rule debug output Change-Id: I60ddef73cd7f0a67055f2d56e6dbe7fa45ddd450 create RuleNode objects and add them to roots Change-Id: I51a0f89b98cda524d34888ab758d7bd397d82f00 ***execute rule nodes on build Change-Id: I291c32868cd982e37393d6bc8d696f2b63fbff50 ***ArtifactSet::fromNodeSet Change-Id: I7586bcfbe43406c22b1ee1a1fd826beaa247164f ***update after rebase Change-Id: I5f73afc80b746b11eeb83aeadf29c2358accbab8 ***phonytarget Change-Id: I587b7e072e54b866e8d5ea37c874e6a8baa550e0 update after rebase Change-Id: I6017c0cbe9244fea04d513f53e3a2a85092bf962 skip nodes early We must skip Building and Built nodes. m_leaves can contain duplicates now. Change-Id: If275106a47c403a455103f4deeb20049548007f5 debug message Change-Id: I90e238eef72a8a02fb0a9f2c77715f5f15c1442d disable phony thingy Change-Id: I7bb60b850b96b65ab738c11e96c3a84cbe58d2f7 connect each output of a rule to the rule itself Change-Id: I159d76c4b63094058cc9a07ccc2d0b67c7ce06e6 TagScanner Change-Id: I4741e48cd674c0ca830ee1b4d05b59a8c542694f TagScanner deps Change-Id: If3e43a7ac25616cd151229684a085ac8ee787645 update after rebase Change-Id: I58d49a5ed1049a17733fc2154588f12c1cda53e6 only root tag scanners in product Change-Id: Ia94732a5632156a5ec3c5518c9596cd4cefac105 run TagScanners Change-Id: I869a183f2da23a43957a6df45dc5a1b30b10af92 TagScannerRunner Change-Id: Id3c5fac73e6fb84e56d6ab1d48a959f3677f7a67 crash fix Change-Id: Ie3c26dbed41ab4615915a08913c495868c3a8910 more TagScanRunner Change-Id: I80b79f101c0f4d802fb4f6515c0848e369fed066 handle removal of filetags Change-Id: Icdd8d05c2e26953f7b12d968aa5dfcc23928b9ba Qt4 build fix Change-Id: Ie5fcb64e36ddc5004003183bea7243536bc8ab15 do not waste space with type information Change-Id: I7b9354e6fceead228ba335723b9addeb701bef56 update nodes that must get new transformers Change-Id: I06cd7ffe606ae643393350c5959ef6475343929f update after rebase Change-Id: If080e664972f2950c12fd800a3e4b521e65dca3a only run tag scanners on changed sources And do not call RulesApplicator in bgloader. Change-Id: I5140c91c79a842dab933ad7b328100bdec13cb10 Conflicts: src/lib/buildgraph/buildgraphloader.cpp sketch of moc tagscanners impl Change-Id: I7736c2da1b1742bc3556ef660c163e6c32cbd4c9 Conflicts: share/qbs/modules/Qt/core/core.qbs MocTagScanner Change-Id: I87199e8f355b8b20cf2387f4d4190a20bddae0db fix lib.qbs Change-Id: Ibcb5bc290d3839b04828f8c9b155577634bcc9e4 moctagscanner split Change-Id: Iace5d48483c02b5d33d9ccd54ac07162bfc09d27
Diffstat (limited to 'src/lib/buildgraph/executor.cpp')
-rw-r--r--src/lib/buildgraph/executor.cpp351
1 files changed, 223 insertions, 128 deletions
diff --git a/src/lib/buildgraph/executor.cpp b/src/lib/buildgraph/executor.cpp
index 5d8ea52cf..fc80eff87 100644
--- a/src/lib/buildgraph/executor.cpp
+++ b/src/lib/buildgraph/executor.cpp
@@ -29,14 +29,16 @@
#include "executor.h"
#include "artifactvisitor.h"
-#include "automoc.h"
#include "buildgraph.h"
#include "productbuilddata.h"
#include "projectbuilddata.h"
#include "cycledetector.h"
#include "executorjob.h"
#include "inputartifactscanner.h"
+#include "phonytarget.h"
+#include "rulenode.h"
#include "rulesevaluationcontext.h"
+#include "tagscannerrunner.h"
#include <buildgraph/transformer.h>
#include <language/language.h>
@@ -91,7 +93,7 @@ private:
};
-bool Executor::ComparePriority::operator() (const Artifact *x, const Artifact *y) const
+bool Executor::ComparePriority::operator() (const BuildGraphNode *x, const BuildGraphNode *y) const
{
return x->product->buildData->buildPriority < y->product->buildData->buildPriority;
}
@@ -106,10 +108,6 @@ Executor::Executor(const Logger &logger, QObject *parent)
, m_doDebug(logger.debugEnabled())
{
m_inputArtifactScanContext = new InputArtifactScannerContext(&m_scanResultCache);
- m_autoMoc = new AutoMoc(logger);
- connect(m_autoMoc, SIGNAL(reportCommandDescription(QString,QString)),
- this, SIGNAL(reportCommandDescription(QString,QString)));
- m_autoMoc->setScanResultCache(&m_scanResultCache);
}
Executor::~Executor()
@@ -119,7 +117,6 @@ Executor::~Executor()
delete job;
foreach (ExecutorJob *job, m_processingJobs.keys())
delete job;
- delete m_autoMoc; // delete before shared scan result cache
delete m_inputArtifactScanContext;
}
@@ -225,6 +222,7 @@ void Executor::doBuild()
}
QBS_CHECK(m_state == ExecutorIdle);
m_leaves = Leaves();
+ m_changedSourceArtifacts.clear();
m_error.clear();
m_explicitlyCanceled = false;
m_activeFileTags = FileTags::fromStringList(m_buildOptions.activeFileTags());
@@ -250,8 +248,7 @@ void Executor::doBuild()
foreach (ExecutorJob * const job, m_availableJobs)
job->setDryRun(m_buildOptions.dryRun());
- bool sourceFilesChanged = false;
- prepareAllArtifacts(&sourceFilesChanged);
+ prepareAllNodes();
Artifact::BuildState initialBuildState = m_buildOptions.changedFiles().isEmpty()
? Artifact::Buildable : Artifact::Built;
@@ -281,19 +278,22 @@ void Executor::doBuild()
// find the root nodes
m_roots.clear();
foreach (const ResolvedProductPtr &product, m_productsToBuild) {
- foreach (Artifact *targetArtifact, product->buildData->targetArtifacts) {
- m_roots += targetArtifact;
-
- // The user expects that he can delete target artifacts and they get rebuilt.
- // To achieve this we must retrieve their timestamps.
- targetArtifact->setTimestamp(FileInfo(targetArtifact->filePath()).lastModified());
+ foreach (BuildGraphNode *rootNode, product->buildData->roots) {
+ m_roots += rootNode;
+ Artifact *targetArtifact = dynamic_cast<Artifact *>(rootNode);
+ if (targetArtifact && product->buildData->targetArtifacts.contains(targetArtifact)) {
+ // The user expects that he can delete target artifacts and they get rebuilt.
+ // To achieve this we must retrieve their timestamps.
+ targetArtifact->setTimestamp(FileInfo(targetArtifact->filePath()).lastModified());
+ }
}
}
prepareReachableArtifacts(initialBuildState);
- setupProgressObserver(sourceFilesChanged);
- if (sourceFilesChanged)
- runAutoMoc();
+ setupProgressObserver(!m_changedSourceArtifacts.isEmpty());
+ if (!m_changedSourceArtifacts.isEmpty()) {
+ runTagScanners();
+ }
initLeaves(changedArtifacts);
if (!scheduleJobs()) {
m_logger.qbsTrace() << "Nothing to do at all, finishing.";
@@ -306,48 +306,49 @@ void Executor::setBuildOptions(const BuildOptions &buildOptions)
m_buildOptions = buildOptions;
}
-static void initArtifactsBottomUp(Artifact *artifact)
+static void initArtifactsBottomUp(BuildGraphNode *node)
{
- if (artifact->buildState == Artifact::Untouched)
+ if (node->buildState == Artifact::Untouched)
return;
- artifact->buildState = Artifact::Buildable;
- foreach (Artifact *parent, artifact->parents)
+ node->buildState = Artifact::Buildable;
+ foreach (BuildGraphNode *parent, node->parents)
initArtifactsBottomUp(parent);
}
void Executor::initLeaves(const QList<Artifact *> &changedArtifacts)
{
if (changedArtifacts.isEmpty()) {
- QSet<Artifact *> seenArtifacts;
- foreach (Artifact *root, m_roots)
- initLeavesTopDown(root, seenArtifacts);
+ QSet<BuildGraphNode *> seenNodes;
+ foreach (BuildGraphNode *root, m_roots)
+ initLeavesTopDown(root, seenNodes);
} else {
- foreach (Artifact *artifact, changedArtifacts) {
+ foreach (BuildGraphNode *artifact, changedArtifacts) {
m_leaves.push(artifact);
initArtifactsBottomUp(artifact);
}
}
}
-void Executor::initLeavesTopDown(Artifact *artifact, QSet<Artifact *> &seenArtifacts)
+void Executor::initLeavesTopDown(BuildGraphNode *node, QSet<BuildGraphNode *> &seenNodes)
{
- if (seenArtifacts.contains(artifact))
+ if (seenNodes.contains(node))
return;
- seenArtifacts += artifact;
+ seenNodes += node;
// Artifacts that appear in the build graph after
// prepareBuildGraph() has been called, must be initialized.
- if (artifact->buildState == Artifact::Untouched) {
- artifact->buildState = Artifact::Buildable;
- if (artifact->artifactType == Artifact::SourceFile)
+ if (node->buildState == Artifact::Untouched) {
+ node->buildState = Artifact::Buildable;
+ Artifact *artifact = dynamic_cast<Artifact *>(node);
+ if (artifact && artifact->artifactType == Artifact::SourceFile)
retrieveSourceFileTimestamp(artifact);
}
- if (artifact->children.isEmpty()) {
- m_leaves.push(artifact);
+ if (node->children.isEmpty()) {
+ m_leaves.push(node);
} else {
- foreach (Artifact *child, artifact->children)
- initLeavesTopDown(child, seenArtifacts);
+ foreach (BuildGraphNode *child, node->children)
+ initLeavesTopDown(child, seenNodes);
}
}
@@ -356,11 +357,34 @@ bool Executor::scheduleJobs()
{
QBS_CHECK(m_state == ExecutorRunning);
while (!m_leaves.empty() && !m_availableJobs.isEmpty()) {
- Artifact * const artifact = m_leaves.top();
+ BuildGraphNode * const nodeToBuild = m_leaves.top();
m_leaves.pop();
- buildArtifact(artifact);
+
+ switch (nodeToBuild->buildState) {
+ case BuildGraphNode::Untouched:
+ QBS_ASSERT(!"untouched node in leaves list", /* ignore */);
+ continue;
+ case BuildGraphNode::Buildable:
+ // This is the only state in which we want to build a node.
+ break;
+ case BuildGraphNode::Building:
+ if (m_doDebug) {
+ m_logger.qbsDebug() << "[EXEC] " << nodeToBuild->toString();
+ m_logger.qbsDebug() << "[EXEC] node is currently being built. Skipping.";
+ }
+ continue;
+ case BuildGraphNode::Built:
+ if (m_doDebug) {
+ m_logger.qbsDebug() << "[EXEC] " << nodeToBuild->toString();
+ m_logger.qbsDebug() << "[EXEC] node already built. Skipping.";
+ }
+ continue;
+ }
+
+ nodeToBuild->accept(this);
}
return !m_leaves.empty() || !m_processingJobs.isEmpty();
+
}
bool Executor::isUpToDate(Artifact *artifact) const
@@ -387,11 +411,15 @@ bool Executor::isUpToDate(Artifact *artifact) const
return false;
}
- foreach (Artifact *child, artifact->children) {
- QBS_CHECK(child->timestamp().isValid());
+ foreach (BuildGraphNode *child, artifact->children) {
+ Artifact *childArtifact = dynamic_cast<Artifact *>(child);
+ if (!childArtifact)
+ continue;
+ QBS_CHECK(childArtifact->timestamp().isValid());
if (debug)
- m_logger.qbsDebug() << "[UTD] child timestamp " << child->timestamp().toString();
- if (artifact->timestamp() < child->timestamp())
+ m_logger.qbsDebug() << "[UTD] child timestamp "
+ << childArtifact->timestamp().toString();
+ if (artifact->timestamp() < childArtifact->timestamp())
return false;
}
@@ -429,13 +457,6 @@ void Executor::buildArtifact(Artifact *artifact)
if (m_doDebug)
m_logger.qbsDebug() << "[EXEC] " << relativeArtifactFileName(artifact);
- // Skip artifacts that are already built.
- if (artifact->buildState == Artifact::Built) {
- if (m_doDebug)
- m_logger.qbsDebug() << "[EXEC] artifact already built. Skipping.";
- return;
- }
-
// skip artifacts without transformer
if (artifact->artifactType != Artifact::Generated) {
// For source artifacts, that were not reachable when initializing the build, we must
@@ -495,7 +516,7 @@ void Executor::buildArtifact(Artifact *artifact)
// create the output directories
if (!m_buildOptions.dryRun()) {
- ArtifactList::const_iterator it = artifact->transformer->outputs.begin();
+ ArtifactSet::const_iterator it = artifact->transformer->outputs.begin();
for (; it != artifact->transformer->outputs.end(); ++it) {
Artifact *output = *it;
QDir outDir = QFileInfo(output->filePath()).absoluteDir();
@@ -511,8 +532,8 @@ void Executor::buildArtifact(Artifact *artifact)
// postpone the build of this artifact, if new dependencies found
if (scanner.newDependencyAdded()) {
bool buildingDependenciesFound = false;
- QVector<Artifact *> unbuiltDependencies;
- foreach (Artifact *dependency, artifact->children) {
+ QVector<BuildGraphNode *> unbuiltDependencies;
+ foreach (BuildGraphNode *dependency, artifact->children) {
switch (dependency->buildState) {
case Artifact::Untouched:
case Artifact::Buildable:
@@ -548,6 +569,59 @@ void Executor::buildArtifact(Artifact *artifact)
job->run(artifact->transformer.data(), artifact->product);
}
+void Executor::buildPhonyTarget(PhonyTarget *target)
+{
+ if (target->transformer()) {
+ if (m_doDebug)
+ m_logger.qbsDebug() << "[EXEC] " << target->toString();
+
+ // Skip targets that are already built.
+ if (target->buildState == Artifact::Built) {
+ if (m_doDebug)
+ m_logger.qbsDebug() << "[EXEC] phony target already built. Skipping.";
+ return;
+ }
+
+ } else {
+ if (m_doDebug)
+ m_logger.qbsDebug() << "[EXEC] " << target->toString()
+ << " No transformer. Skipping.";
+ }
+ finishNode(target);
+}
+
+void Executor::executeRuleNode(RuleNode *ruleNode)
+{
+ RuleNode::ApplicationResult result;
+ ruleNode->apply(m_logger, &result);
+
+ if (result.upToDate) {
+ if (m_doDebug)
+ m_logger.qbsDebug() << "[EXEC] " << ruleNode->toString()
+ << " is up to date. Skipping.";
+ } else {
+ qDebug() << "EXEC RULE" << ruleNode->toString();
+ if (m_doDebug)
+ m_logger.qbsDebug() << "[EXEC] " << ruleNode->toString();
+ const QVector<BuildGraphNode *> &createdNodes = result.createdNodes;
+ const WeakPointer<ResolvedProduct> &product = ruleNode->product;
+ foreach (BuildGraphNode *node, createdNodes) {
+ if (m_doDebug)
+ m_logger.qbsDebug() << "[EXEC] rule created " << node->toString();
+ loggedConnect(node, ruleNode, m_logger);
+ Artifact *artifact = dynamic_cast<Artifact *>(node);
+ if (!artifact)
+ continue;
+ if (artifact->fileTags.matches(product->fileTags)) {
+ product->buildData->roots += artifact;
+ product->buildData->targetArtifacts += artifact;
+ }
+ }
+ insertLeavesAfterAddingDependencies(createdNodes);
+ }
+ finishNode(ruleNode);
+}
+
void Executor::finishJob(ExecutorJob *job, bool success)
{
QBS_CHECK(job);
@@ -583,27 +657,21 @@ void Executor::finishJob(ExecutorJob *job, bool success)
}
}
-static bool allChildrenBuilt(Artifact *artifact)
+static bool allChildrenBuilt(BuildGraphNode *node)
{
- foreach (Artifact *child, artifact->children)
+ foreach (BuildGraphNode *child, node->children)
if (child->buildState != Artifact::Built)
return false;
return true;
}
-void Executor::finishArtifact(Artifact *leaf)
+void Executor::finishNode(BuildGraphNode *leaf)
{
- QBS_CHECK(leaf);
-
- if (m_doTrace)
- m_logger.qbsTrace() << "[EXEC] finishArtifact " << relativeArtifactFileName(leaf);
-
leaf->buildState = Artifact::Built;
- m_scanResultCache.remove(leaf->filePath());
- foreach (Artifact *parent, leaf->parents) {
+ foreach (BuildGraphNode *parent, leaf->parents) {
if (parent->buildState != Artifact::Buildable) {
if (m_doTrace) {
- m_logger.qbsTrace() << "[EXEC] parent " << relativeArtifactFileName(parent)
+ m_logger.qbsTrace() << "[EXEC] parent " << parent->toString()
<< " build state: " << toString(parent->buildState);
}
continue;
@@ -612,16 +680,26 @@ void Executor::finishArtifact(Artifact *leaf)
if (allChildrenBuilt(parent)) {
m_leaves.push(parent);
if (m_doTrace) {
- m_logger.qbsTrace() << "[EXEC] finishArtifact adds leaf "
- << relativeArtifactFileName(parent) << " " << toString(parent->buildState);
+ m_logger.qbsTrace() << "[EXEC] finishNode adds leaf "
+ << parent->toString() << " " << toString(parent->buildState);
}
} else {
if (m_doTrace) {
- m_logger.qbsTrace() << "[EXEC] parent " << relativeArtifactFileName(parent)
+ m_logger.qbsTrace() << "[EXEC] parent " << parent->toString()
<< " build state: " << toString(parent->buildState);
}
}
}
+}
+
+void Executor::finishArtifact(Artifact *leaf)
+{
+ QBS_CHECK(leaf);
+ if (m_doTrace)
+ m_logger.qbsTrace() << "[EXEC] finishArtifact " << relativeArtifactFileName(leaf);
+
+ finishNode(leaf);
+ m_scanResultCache.remove(leaf->filePath());
if (leaf->transformer)
foreach (Artifact *sideBySideArtifact, leaf->transformer->outputs)
@@ -632,28 +710,28 @@ void Executor::finishArtifact(Artifact *leaf)
m_progressObserver->incrementProgressValue(BuildEffortCalculator::multiplier(leaf));
}
-void Executor::insertLeavesAfterAddingDependencies_recurse(Artifact *const artifact,
- QSet<Artifact *> *seenArtifacts, Leaves *leaves) const
+void Executor::insertLeavesAfterAddingDependencies_recurse(BuildGraphNode *const node,
+ QSet<BuildGraphNode *> *seenNodes, Leaves *leaves) const
{
- if (seenArtifacts->contains(artifact))
+ if (seenNodes->contains(node))
return;
- seenArtifacts->insert(artifact);
+ seenNodes->insert(node);
- if (artifact->buildState == Artifact::Untouched)
- artifact->buildState = Artifact::Buildable;
+ if (node->buildState == Artifact::Untouched)
+ node->buildState = Artifact::Buildable;
bool isLeaf = true;
- foreach (Artifact *child, artifact->children) {
+ foreach (BuildGraphNode *child, node->children) {
if (child->buildState != Artifact::Built) {
isLeaf = false;
- insertLeavesAfterAddingDependencies_recurse(child, seenArtifacts, leaves);
+ insertLeavesAfterAddingDependencies_recurse(child, seenNodes, leaves);
}
}
if (isLeaf) {
if (m_doDebug)
- m_logger.qbsDebug() << "[EXEC] adding leaf " << relativeArtifactFileName(artifact);
- leaves->push(artifact);
+ m_logger.qbsDebug() << "[EXEC] adding leaf " << node->toString();
+ leaves->push(node);
}
}
@@ -662,11 +740,11 @@ QString Executor::configString() const
return tr(" for configuration %1").arg(m_project->id());
}
-void Executor::insertLeavesAfterAddingDependencies(QVector<Artifact *> dependencies)
+void Executor::insertLeavesAfterAddingDependencies(QVector<BuildGraphNode *> dependencies)
{
- QSet<Artifact *> seenArtifacts;
- foreach (Artifact *dependency, dependencies)
- insertLeavesAfterAddingDependencies_recurse(dependency, &seenArtifacts, &m_leaves);
+ QSet<BuildGraphNode *> seenNodes;
+ foreach (BuildGraphNode *dependency, dependencies)
+ insertLeavesAfterAddingDependencies_recurse(dependency, &seenNodes, &m_leaves);
}
void Executor::cancelJobs()
@@ -731,27 +809,19 @@ void Executor::addExecutorJobs(int jobNumber)
}
}
-void Executor::runAutoMoc()
+void Executor::runTagScanners()
{
- bool autoMocApplied = false;
foreach (const ResolvedProductPtr &product, m_productsToBuild) {
if (m_progressObserver && m_progressObserver->canceled())
throw ErrorInfo(Tr::tr("Build canceled%1.").arg(configString()));
- // HACK call the automoc thingy here only if we have use Qt/core module
- foreach (const ResolvedModuleConstPtr &m, product->modules) {
- if (m->name == "Qt/core") {
- autoMocApplied = true;
- m_autoMoc->apply(product);
- break;
- }
- }
+ QHash<FileTag, QList<Artifact *> > sourceArtifacts;
+ foreach (Artifact *artifact, m_changedSourceArtifacts)
+ foreach (const FileTag &tag, artifact->fileTags)
+ sourceArtifacts[tag] += artifact;
+ foreach (const TagScannerConstPtr &rootTagScanner, product->tagScanners)
+ runTagScannersTopOrdered(&m_scanResultCache, product, rootTagScanner, sourceArtifacts,
+ m_logger);
}
- if (autoMocApplied) {
- foreach (const ResolvedProductConstPtr &product, m_productsToBuild)
- CycleDetector(m_logger).visitProduct(product);
- }
- if (m_progressObserver)
- m_progressObserver->incrementProgressValue(m_mocEffort);
}
void Executor::onProcessError(const qbs::ErrorInfo &err)
@@ -800,8 +870,8 @@ void Executor::finish()
QStringList unbuiltProductNames;
foreach (const ResolvedProductPtr &product, m_productsToBuild) {
- foreach (Artifact *artifact, product->buildData->targetArtifacts) {
- if (artifact->buildState != Artifact::Built) {
+ foreach (BuildGraphNode *rootNode, product->buildData->roots) {
+ if (rootNode->buildState != Artifact::Built) {
unbuiltProductNames += product->name;
break;
}
@@ -823,35 +893,59 @@ void Executor::finish()
emit finished();
}
+bool Executor::visit(Artifact *artifact)
+{
+ buildArtifact(artifact);
+ return false;
+}
+
+bool Executor::visit(PhonyTarget *target)
+{
+ buildPhonyTarget(target);
+ return false;
+}
+
+bool Executor::visit(RuleNode *ruleNode)
+{
+ executeRuleNode(ruleNode);
+ return false;
+}
+
/**
* Sets the state of all artifacts in the graph to "untouched".
* This must be done before doing a build.
*
* Retrieves the timestamps of source artifacts.
*
- * This function sets *sourceFilesChanged to true, if the timestamp of a reachable source artifact
- * changed.
+ * This function also fills the list of changed source files.
*/
-void Executor::prepareAllArtifacts(bool *sourceFilesChanged)
+void Executor::prepareAllNodes()
{
foreach (const ResolvedProductPtr &product, m_productsToBuild) {
- foreach (Artifact *artifact, product->buildData->artifacts) {
- artifact->buildState = Artifact::Untouched;
- artifact->inputsScanned = false;
- artifact->timestampRetrieved = false;
+ foreach (BuildGraphNode *node, product->buildData->nodes) {
+ node->buildState = Artifact::Untouched;
+ Artifact *artifact = dynamic_cast<Artifact *>(node);
+ if (artifact)
+ prepareArtifact(artifact);
+ }
+ }
+}
- if (artifact->artifactType == Artifact::SourceFile) {
- const FileTime oldTimestamp = artifact->timestamp();
- retrieveSourceFileTimestamp(artifact);
- if (oldTimestamp != artifact->timestamp())
- *sourceFilesChanged = true;
- }
+void Executor::prepareArtifact(Artifact *artifact)
+{
+ artifact->inputsScanned = false;
+ artifact->timestampRetrieved = false;
- // Timestamps of file dependencies must be invalid for every build.
- foreach (FileDependency *fileDependency, artifact->fileDependencies)
- fileDependency->clearTimestamp();
- }
+ if (artifact->artifactType == Artifact::SourceFile) {
+ const FileTime oldTimestamp = artifact->timestamp();
+ retrieveSourceFileTimestamp(artifact);
+ if (oldTimestamp != artifact->timestamp())
+ m_changedSourceArtifacts.append(artifact);
}
+
+ // Timestamps of file dependencies must be invalid for every build.
+ foreach (FileDependency *fileDependency, artifact->fileDependencies)
+ fileDependency->clearTimestamp();
}
/**
@@ -860,38 +954,39 @@ void Executor::prepareAllArtifacts(bool *sourceFilesChanged)
*/
void Executor::prepareReachableArtifacts(const Artifact::BuildState buildState)
{
- foreach (Artifact *root, m_roots)
+ foreach (BuildGraphNode *root, m_roots)
prepareReachableArtifacts_impl(root, buildState);
}
-void Executor::prepareReachableArtifacts_impl(Artifact *artifact,
+void Executor::prepareReachableArtifacts_impl(BuildGraphNode *node,
const Artifact::BuildState buildState)
{
- if (artifact->buildState != Artifact::Untouched)
+ if (node->buildState != Artifact::Untouched)
return;
- artifact->buildState = buildState;
- foreach (Artifact *child, artifact->children)
+ node->buildState = buildState;
+ foreach (BuildGraphNode *child, node->children)
prepareReachableArtifacts_impl(child, buildState);
}
void Executor::updateBuildGraph(Artifact::BuildState buildState)
{
- QSet<Artifact *> seenArtifacts;
- foreach (Artifact *root, m_roots)
+ QSet<BuildGraphNode *> seenArtifacts;
+ foreach (BuildGraphNode *root, m_roots)
updateBuildGraph_impl(root, buildState, seenArtifacts);
}
-void Executor::updateBuildGraph_impl(Artifact *artifact, Artifact::BuildState buildState, QSet<Artifact *> &seenArtifacts)
+void Executor::updateBuildGraph_impl(BuildGraphNode *node, Artifact::BuildState buildState,
+ QSet<BuildGraphNode *> &seenNodes)
{
- if (seenArtifacts.contains(artifact))
+ if (seenNodes.contains(node))
return;
- seenArtifacts += artifact;
- artifact->buildState = buildState;
+ seenNodes += node;
+ node->buildState = buildState;
- foreach (Artifact *child, artifact->children)
- updateBuildGraph_impl(child, buildState, seenArtifacts);
+ foreach (BuildGraphNode *child, node->children)
+ updateBuildGraph_impl(child, buildState, seenNodes);
}
void Executor::setState(ExecutorState s)