aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/lib/corelib/buildgraph/executor.cpp100
-rw-r--r--src/lib/corelib/buildgraph/executor.h5
-rw-r--r--src/lib/corelib/tools/buildoptions.cpp25
-rw-r--r--src/lib/corelib/tools/buildoptions.h3
-rw-r--r--src/lib/corelib/tools/filetime.h1
-rw-r--r--src/lib/corelib/tools/filetime_unix.cpp5
-rw-r--r--src/lib/corelib/tools/filetime_win.cpp14
7 files changed, 98 insertions, 55 deletions
diff --git a/src/lib/corelib/buildgraph/executor.cpp b/src/lib/corelib/buildgraph/executor.cpp
index 583fd2396..f54034173 100644
--- a/src/lib/corelib/buildgraph/executor.cpp
+++ b/src/lib/corelib/buildgraph/executor.cpp
@@ -111,7 +111,12 @@ void Executor::retrieveSourceFileTimestamp(Artifact *artifact) const
{
QBS_CHECK(artifact->artifactType == Artifact::SourceFile);
- artifact->setTimestamp(recursiveFileTime(artifact->filePath()));
+ if (m_buildOptions.changedFiles().contains(artifact->filePath()))
+ artifact->setTimestamp(FileTime::currentTime());
+ else if (m_buildOptions.changedFiles().isEmpty())
+ artifact->setTimestamp(recursiveFileTime(artifact->filePath()));
+ else
+ artifact->setTimestamp(FileTime::oldestTime());
artifact->timestampRetrieved = true;
}
@@ -220,21 +225,10 @@ void Executor::setBuildOptions(const BuildOptions &buildOptions)
m_buildOptions = buildOptions;
}
-static void initNodesBottomUp(BuildGraphNode *node)
-{
- if (node->buildState == BuildGraphNode::Untouched)
- return;
- node->buildState = BuildGraphNode::Buildable;
- foreach (BuildGraphNode *parent, node->parents)
- initNodesBottomUp(parent);
-}
void Executor::initLeaves()
{
- if (m_buildOptions.changedFiles().isEmpty())
- updateLeaves(m_roots);
- else
- initLeavesForSelectedFiles();
+ updateLeaves(m_roots);
}
void Executor::updateLeaves(const NodeSet &nodes)
@@ -244,28 +238,6 @@ void Executor::updateLeaves(const NodeSet &nodes)
updateLeaves(node, seenNodes);
}
-void Executor::initLeavesForSelectedFiles()
-{
- ArtifactSet changedArtifacts;
- foreach (const QString &filePath, m_buildOptions.changedFiles()) {
- QList<FileResourceBase *> lookupResults;
- lookupResults.append(m_project->buildData->lookupFiles(filePath));
- if (lookupResults.isEmpty()) {
- m_logger.qbsWarning() << QString::fromLocal8Bit("Out of date file '%1' provided "
- "but not found.").arg(QDir::toNativeSeparators(filePath));
- continue;
- }
- foreach (FileResourceBase *lookupResult, lookupResults)
- if (Artifact *artifact = dynamic_cast<Artifact *>(lookupResult))
- changedArtifacts += artifact;
- }
-
- foreach (Artifact *artifact, changedArtifacts) {
- m_leaves.push(artifact);
- initNodesBottomUp(artifact);
- }
-}
-
void Executor::updateLeaves(BuildGraphNode *node, NodeSet &seenNodes)
{
if (seenNodes.contains(node))
@@ -306,7 +278,8 @@ bool Executor::scheduleJobs()
switch (nodeToBuild->buildState) {
case BuildGraphNode::Untouched:
- QBS_ASSERT(!"untouched node in leaves list", /* ignore */);
+ QBS_ASSERT(!"untouched node in leaves list",
+ qDebug("%s", qPrintable(nodeToBuild->toString())));
break;
case BuildGraphNode::Buildable:
// This is the only state in which we want to build a node.
@@ -582,6 +555,34 @@ QString Executor::configString() const
return tr(" for configuration %1").arg(m_project->id());
}
+bool Executor::transformerHasMatchingOutputTags(const TransformerConstPtr &transformer) const
+{
+ if (m_activeFileTags.isEmpty())
+ return true; // No filtering requested.
+
+ foreach (Artifact * const output, transformer->outputs) {
+ if (m_activeFileTags.matches(output->fileTags))
+ return true;
+ }
+
+ return false;
+}
+
+bool Executor::transformerHasMatchingInputFiles(const TransformerConstPtr &transformer) const
+{
+ if (m_buildOptions.filesToConsider().isEmpty())
+ return true; // No filtering requested.
+
+ foreach (const Artifact * const input, transformer->inputs) {
+ foreach (const QString &filePath, m_buildOptions.filesToConsider()) {
+ if (input->filePath() == filePath)
+ return true;
+ }
+ }
+
+ return false;
+}
+
void Executor::cancelJobs()
{
m_logger.qbsTrace() << "Canceling all jobs.";
@@ -733,8 +734,6 @@ bool Executor::checkForUnbuiltDependencies(Artifact *artifact)
void Executor::potentiallyRunTransformer(const TransformerPtr &transformer)
{
- bool matchingFileTagsExist = m_activeFileTags.isEmpty();
-
foreach (Artifact * const output, transformer->outputs) {
// Rescuing build data can introduce new dependencies, potentially delaying execution of
// this transformer.
@@ -742,20 +741,22 @@ void Executor::potentiallyRunTransformer(const TransformerPtr &transformer)
rescueOldBuildData(output, &childrenAddedDueToRescue);
if (childrenAddedDueToRescue && checkForUnbuiltDependencies(output))
return;
-
- if (!matchingFileTagsExist && m_activeFileTags.matches(output->fileTags))
- matchingFileTagsExist = true;
}
- // Skip if we're building just one file and the file tags do not match.
- if (!matchingFileTagsExist) {
+ if (!transformerHasMatchingOutputTags(transformer)) {
if (m_doDebug)
m_logger.qbsDebug() << "[EXEC] file tags do not match. Skipping.";
finishTransformer(transformer);
return;
}
- // Skip transformers that do not need to be built.
+ if (!transformerHasMatchingInputFiles(transformer)) {
+ if (m_doDebug)
+ m_logger.qbsDebug() << "[EXEC] input files do not match. Skipping.";
+ finishTransformer(transformer);
+ return;
+ }
+
if (!mustExecuteTransformer(transformer)) {
if (m_doDebug)
m_logger.qbsDebug() << "[EXEC] Up to date. Skipping.";
@@ -927,21 +928,18 @@ void Executor::prepareArtifact(Artifact *artifact)
*/
void Executor::prepareReachableNodes()
{
- const BuildGraphNode::BuildState initialBuildState = m_buildOptions.changedFiles().isEmpty()
- ? BuildGraphNode::Buildable : BuildGraphNode::Built;
foreach (BuildGraphNode *root, m_roots)
- prepareReachableNodes_impl(root, initialBuildState);
+ prepareReachableNodes_impl(root);
}
-void Executor::prepareReachableNodes_impl(BuildGraphNode *node,
- const BuildGraphNode::BuildState buildState)
+void Executor::prepareReachableNodes_impl(BuildGraphNode *node)
{
if (node->buildState != BuildGraphNode::Untouched)
return;
- node->buildState = buildState;
+ node->buildState = BuildGraphNode::Buildable;
foreach (BuildGraphNode *child, node->children)
- prepareReachableNodes_impl(child, buildState);
+ prepareReachableNodes_impl(child);
}
void Executor::prepareProducts()
diff --git a/src/lib/corelib/buildgraph/executor.h b/src/lib/corelib/buildgraph/executor.h
index 68afe6083..63dcd7dd2 100644
--- a/src/lib/corelib/buildgraph/executor.h
+++ b/src/lib/corelib/buildgraph/executor.h
@@ -100,13 +100,12 @@ private:
void prepareAllNodes();
void prepareArtifact(Artifact *artifact);
void prepareReachableNodes();
- void prepareReachableNodes_impl(BuildGraphNode *node, const Artifact::BuildState buildState);
+ void prepareReachableNodes_impl(BuildGraphNode *node);
void prepareProducts();
void setupRootNodes();
void initLeaves();
void updateLeaves(const NodeSet &nodes);
void updateLeaves(BuildGraphNode *node, NodeSet &seenNodes);
- void initLeavesForSelectedFiles();
bool scheduleJobs();
void buildArtifact(Artifact *artifact);
void executeRuleNode(RuleNode *ruleNode);
@@ -130,6 +129,8 @@ private:
void retrieveSourceFileTimestamp(Artifact *artifact) const;
FileTime recursiveFileTime(const QString &filePath) const;
QString configString() const;
+ bool transformerHasMatchingOutputTags(const TransformerConstPtr &transformer) const;
+ bool transformerHasMatchingInputFiles(const TransformerConstPtr &transformer) const;
typedef QHash<ExecutorJob *, TransformerPtr> JobMap;
JobMap m_processingJobs;
diff --git a/src/lib/corelib/tools/buildoptions.cpp b/src/lib/corelib/tools/buildoptions.cpp
index 2261124d8..a2d703363 100644
--- a/src/lib/corelib/tools/buildoptions.cpp
+++ b/src/lib/corelib/tools/buildoptions.cpp
@@ -42,6 +42,7 @@ public:
}
QStringList changedFiles;
+ QStringList filesToConsider;
QStringList activeFileTags;
int maxJobCount;
bool dryRun;
@@ -98,6 +99,26 @@ void BuildOptions::setChangedFiles(const QStringList &changedFiles)
}
/*!
+ * \brief The list of files to consider.
+ * \sa setFilesToConsider.
+ * By default, this list is empty.
+ */
+QStringList BuildOptions::filesToConsider() const
+{
+ return d->filesToConsider;
+}
+
+/*!
+ * \brief If the given list is non-empty, qbs will run only commands whose rule has at least one
+ * of these files as an input.
+ * \note The list elements must be absolute file paths.
+ */
+void BuildOptions::setFilesToConsider(const QStringList &files)
+{
+ d->filesToConsider = files;
+}
+
+/*!
* \brief The list of active file tags.
* \sa setActiveFileTags
*/
@@ -109,8 +130,8 @@ QStringList BuildOptions::activeFileTags() const
/*!
* \brief Set the list of active file tags.
* If this list is non-empty, then every transformer with non-matching output file tags is skipped.
- * E.g. set changed files to "foo.cpp" and activeFileTags to ["obj"] to run the compiler
- * on foo.cpp without further processing like linking.
+ * E.g. call \c setFilesToConsider() with "foo.cpp" and \c setActiveFileTags() with "obj" to
+ * run the compiler on foo.cpp without further processing like linking.
* \sa activeFileTags
*/
void BuildOptions::setActiveFileTags(const QStringList &fileTags)
diff --git a/src/lib/corelib/tools/buildoptions.h b/src/lib/corelib/tools/buildoptions.h
index 2c277fc3b..c79e6477b 100644
--- a/src/lib/corelib/tools/buildoptions.h
+++ b/src/lib/corelib/tools/buildoptions.h
@@ -45,6 +45,9 @@ public:
BuildOptions &operator=(const BuildOptions &other);
~BuildOptions();
+ QStringList filesToConsider() const;
+ void setFilesToConsider(const QStringList &files);
+
QStringList changedFiles() const;
void setChangedFiles(const QStringList &changedFiles);
diff --git a/src/lib/corelib/tools/filetime.h b/src/lib/corelib/tools/filetime.h
index 0dc0524df..0f16f3ad3 100644
--- a/src/lib/corelib/tools/filetime.h
+++ b/src/lib/corelib/tools/filetime.h
@@ -68,6 +68,7 @@ public:
QString toString() const;
static FileTime currentTime();
+ static FileTime oldestTime();
friend class FileInfo;
InternalType m_fileTime;
diff --git a/src/lib/corelib/tools/filetime_unix.cpp b/src/lib/corelib/tools/filetime_unix.cpp
index 945be8f44..5dd176c04 100644
--- a/src/lib/corelib/tools/filetime_unix.cpp
+++ b/src/lib/corelib/tools/filetime_unix.cpp
@@ -62,6 +62,11 @@ FileTime FileTime::currentTime()
return time(0);
}
+FileTime FileTime::oldestTime()
+{
+ return 1;
+}
+
QString FileTime::toString() const
{
QDateTime dt;
diff --git a/src/lib/corelib/tools/filetime_win.cpp b/src/lib/corelib/tools/filetime_win.cpp
index b3a7fab67..706dd4752 100644
--- a/src/lib/corelib/tools/filetime_win.cpp
+++ b/src/lib/corelib/tools/filetime_win.cpp
@@ -75,6 +75,20 @@ FileTime FileTime::currentTime()
return result;
}
+FileTime FileTime::oldestTime()
+{
+ SYSTEMTIME st = {
+ 1601,
+ 1,
+ 5,
+ 2
+ };
+ FileTime result;
+ FILETIME *const ft = reinterpret_cast<FILETIME *>(&result.m_fileTime);
+ SystemTimeToFileTime(&st, ft);
+ return result;
+}
+
QString FileTime::toString() const
{
const FILETIME *const ft = reinterpret_cast<const FILETIME *>(&m_fileTime);