summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--misc/ninja_syntax.py4
-rw-r--r--src/graph.cc44
-rw-r--r--src/graph.h11
3 files changed, 47 insertions, 12 deletions
diff --git a/misc/ninja_syntax.py b/misc/ninja_syntax.py
index ece7eb5..519330e 100644
--- a/misc/ninja_syntax.py
+++ b/misc/ninja_syntax.py
@@ -38,7 +38,7 @@ class Writer(object):
def rule(self, name, command, description=None, depfile=None,
generator=False, pool=None, restat=False, rspfile=None,
- rspfile_content=None):
+ rspfile_content=None, special=None):
self._line('rule %s' % name)
self.variable('command', command, indent=1)
if description:
@@ -55,6 +55,8 @@ class Writer(object):
self.variable('rspfile', rspfile, indent=1)
if rspfile_content:
self.variable('rspfile_content', rspfile_content, indent=1)
+ if special:
+ self.variable('special', special, indent=1)
def build(self, outputs, rule, inputs=None, implicit=None, order_only=None,
variables=None):
diff --git a/src/graph.cc b/src/graph.cc
index 43f4304..2f86785 100644
--- a/src/graph.cc
+++ b/src/graph.cc
@@ -53,22 +53,19 @@ bool Rule::IsReservedBinding(const string& var) {
var == "pool" ||
var == "restat" ||
var == "rspfile" ||
- var == "rspfile_content";
+ var == "rspfile_content" ||
+ var == "special";
}
bool DependencyScan::RecomputeDirty(Edge* edge, string* err) {
bool dirty = false;
edge->outputs_ready_ = true;
- string depfile = edge->GetBinding("depfile");
- if (!depfile.empty()) {
- if (!dep_loader_.LoadDepFile(edge, depfile, err)) {
- if (!err->empty())
- return false;
- EXPLAIN("Edge targets are dirty because depfile '%s' is missing",
- depfile.c_str());
- dirty = true;
- }
+ if (!dep_loader_.LoadDeps(edge, err)) {
+ if (!err->empty())
+ return false;
+ // Failed to load dependency info: rebuild to regenerate it.
+ dirty = true;
}
// Visit all inputs; we're dirty if any of the inputs are dirty.
@@ -325,6 +322,33 @@ void Node::Dump(const char* prefix) const {
}
}
+bool ImplicitDepLoader::LoadDeps(Edge* edge, string* err) {
+ string special = edge->GetBinding("special");
+ if (!special.empty() && special == "gcc") {
+ if (!LoadDepsFromLog(edge, err)) {
+ if (!err->empty())
+ return false;
+ EXPLAIN("deps for %s are missing", edge->outputs_[0]->path().c_str());
+ return false;
+ }
+ return true;
+ }
+
+ string depfile = edge->GetBinding("depfile");
+ if (!depfile.empty()) {
+ if (!LoadDepFile(edge, depfile, err)) {
+ if (!err->empty())
+ return false;
+ EXPLAIN("depfile '%s' is missing", depfile.c_str());
+ return false;
+ }
+ return true;
+ }
+
+ // No deps to load.
+ return true;
+}
+
bool ImplicitDepLoader::LoadDepFile(Edge* edge, const string& path,
string* err) {
METRIC_RECORD("depfile load");
diff --git a/src/graph.h b/src/graph.h
index d943702..a7b60db 100644
--- a/src/graph.h
+++ b/src/graph.h
@@ -192,10 +192,19 @@ struct ImplicitDepLoader {
DiskInterface* disk_interface)
: state_(state), disk_interface_(disk_interface), deps_log_(deps_log) {}
+ /// Load implicit dependencies for \a edge.
+ /// @return false on error (without filling \a err if info is just missing).
+ bool LoadDeps(Edge* edge, string* err);
+
+ private:
+ /// Load implicit dependencies for \a edge from a depfile attribute.
+ /// @return false on error (without filling \a err if info is just missing).
bool LoadDepFile(Edge* edge, const string& path, string* err);
+
+ /// Load implicit dependencies for \a edge from the DepsLog.
+ /// @return false on error (without filling \a err if info is just missing).
bool LoadDepsFromLog(Edge* edge, string* err);
- private:
/// Preallocate \a count spaces in the input array on \a edge, returning
/// an iterator pointing at the first new space.
vector<Node*>::iterator PreallocateSpace(Edge* edge, int count);