Ninja
graph.h
Go to the documentation of this file.
1 // Copyright 2011 Google Inc. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef NINJA_GRAPH_H_
16 #define NINJA_GRAPH_H_
17 
18 #include <algorithm>
19 #include <set>
20 #include <string>
21 #include <vector>
22 
23 #include "dyndep.h"
24 #include "eval_env.h"
25 #include "timestamp.h"
26 #include "util.h"
27 
28 struct BuildLog;
30 struct DiskInterface;
31 struct DepsLog;
32 struct Edge;
33 struct Node;
34 struct Pool;
35 struct State;
36 
37 /// Information about a node in the dependency graph: the file, whether
38 /// it's dirty, mtime, etc.
39 struct Node {
40  Node(const std::string& path, uint64_t slash_bits)
41  : path_(path),
43  mtime_(-1),
45  dirty_(false),
46  dyndep_pending_(false),
47  in_edge_(NULL),
48  id_(-1) {}
49 
50  /// Return false on error.
51  bool Stat(DiskInterface* disk_interface, std::string* err);
52 
53  /// If the file doesn't exist, set the mtime_ from its dependencies
55 
56  /// Return false on error.
57  bool StatIfNecessary(DiskInterface* disk_interface, std::string* err) {
58  if (status_known())
59  return true;
60  return Stat(disk_interface, err);
61  }
62 
63  /// Mark as not-yet-stat()ed and not dirty.
64  void ResetState() {
65  mtime_ = -1;
67  dirty_ = false;
68  }
69 
70  /// Mark the Node as already-stat()ed and missing.
71  void MarkMissing() {
72  if (mtime_ == -1) {
73  mtime_ = 0;
74  }
76  }
77 
78  bool exists() const {
80  }
81 
82  bool status_known() const {
84  }
85 
86  const std::string& path() const { return path_; }
87  /// Get |path()| but use slash_bits to convert back to original slash styles.
88  std::string PathDecanonicalized() const {
90  }
91  static std::string PathDecanonicalized(const std::string& path,
93  uint64_t slash_bits() const { return slash_bits_; }
94 
95  TimeStamp mtime() const { return mtime_; }
96 
97  bool dirty() const { return dirty_; }
98  void set_dirty(bool dirty) { dirty_ = dirty; }
99  void MarkDirty() { dirty_ = true; }
100 
101  bool dyndep_pending() const { return dyndep_pending_; }
102  void set_dyndep_pending(bool pending) { dyndep_pending_ = pending; }
103 
104  Edge* in_edge() const { return in_edge_; }
105  void set_in_edge(Edge* edge) { in_edge_ = edge; }
106 
107  int id() const { return id_; }
108  void set_id(int id) { id_ = id; }
109 
110  const std::vector<Edge*>& out_edges() const { return out_edges_; }
111  const std::vector<Edge*>& validation_out_edges() const { return validation_out_edges_; }
112  void AddOutEdge(Edge* edge) { out_edges_.push_back(edge); }
113  void AddValidationOutEdge(Edge* edge) { validation_out_edges_.push_back(edge); }
114 
115  void Dump(const char* prefix="") const;
116 
117 private:
118  std::string path_;
119 
120  /// Set bits starting from lowest for backslashes that were normalized to
121  /// forward slashes by CanonicalizePath. See |PathDecanonicalized|.
123 
124  /// Possible values of mtime_:
125  /// -1: file hasn't been examined
126  /// 0: we looked, and file doesn't exist
127  /// >0: actual file's mtime, or the latest mtime of its dependencies if it doesn't exist
129 
131  /// The file hasn't been examined.
133  /// The file doesn't exist. mtime_ will be the latest mtime of its dependencies.
135  /// The path is an actual file. mtime_ will be the file's mtime.
137  };
139 
140  /// Dirty is true when the underlying file is out-of-date.
141  /// But note that Edge::outputs_ready_ is also used in judging which
142  /// edges to build.
143  bool dirty_;
144 
145  /// Store whether dyndep information is expected from this node but
146  /// has not yet been loaded.
148 
149  /// The Edge that produces this Node, or NULL when there is no
150  /// known edge to produce it.
152 
153  /// All Edges that use this Node as an input.
154  std::vector<Edge*> out_edges_;
155 
156  /// All Edges that use this Node as a validation.
157  std::vector<Edge*> validation_out_edges_;
158 
159  /// A dense integer id for the node, assigned and used by DepsLog.
160  int id_;
161 };
162 
163 /// An edge in the dependency graph; links between Nodes using Rules.
164 struct Edge {
165  enum VisitMark {
169  };
170 
172  : rule_(NULL), pool_(NULL), dyndep_(NULL), env_(NULL), mark_(VisitNone),
173  id_(0), outputs_ready_(false), deps_loaded_(false),
176 
177  /// Return true if all inputs' in-edges are ready.
178  bool AllInputsReady() const;
179 
180  /// Expand all variables in a command and return it as a string.
181  /// If incl_rsp_file is enabled, the string will also contain the
182  /// full contents of a response file (if applicable)
183  std::string EvaluateCommand(bool incl_rsp_file = false) const;
184 
185  /// Returns the shell-escaped value of |key|.
186  std::string GetBinding(const std::string& key) const;
187  bool GetBindingBool(const std::string& key) const;
188 
189  /// Like GetBinding("depfile"), but without shell escaping.
190  std::string GetUnescapedDepfile() const;
191  /// Like GetBinding("dyndep"), but without shell escaping.
192  std::string GetUnescapedDyndep() const;
193  /// Like GetBinding("rspfile"), but without shell escaping.
194  std::string GetUnescapedRspfile() const;
195 
196  void Dump(const char* prefix="") const;
197 
198  // Append all edge explicit inputs to |*out|. Possibly with shell escaping.
199  void CollectInputs(bool shell_escape, std::vector<std::string>* out) const;
200 
201  const Rule* rule_;
203  std::vector<Node*> inputs_;
204  std::vector<Node*> outputs_;
205  std::vector<Node*> validations_;
209  size_t id_;
214 
215  const Rule& rule() const { return *rule_; }
216  Pool* pool() const { return pool_; }
217  int weight() const { return 1; }
218  bool outputs_ready() const { return outputs_ready_; }
219 
220  // There are three types of inputs.
221  // 1) explicit deps, which show up as $in on the command line;
222  // 2) implicit deps, which the target depends on implicitly (e.g. C headers),
223  // and changes in them cause the target to rebuild;
224  // 3) order-only deps, which are needed before the target builds but which
225  // don't cause the target to rebuild.
226  // These are stored in inputs_ in that order, and we keep counts of
227  // #2 and #3 when we need to access the various subsets.
230  bool is_implicit(size_t index) {
231  return index >= inputs_.size() - order_only_deps_ - implicit_deps_ &&
232  !is_order_only(index);
233  }
234  bool is_order_only(size_t index) {
235  return index >= inputs_.size() - order_only_deps_;
236  }
237 
238  // There are two types of outputs.
239  // 1) explicit outs, which show up as $out on the command line;
240  // 2) implicit outs, which the target generates but are not part of $out.
241  // These are stored in outputs_ in that order, and we keep a count of
242  // #2 to use when we need to access the various subsets.
244  bool is_implicit_out(size_t index) const {
245  return index >= outputs_.size() - implicit_outs_;
246  }
247 
248  bool is_phony() const;
249  bool use_console() const;
250  bool maybe_phonycycle_diagnostic() const;
251 };
252 
253 struct EdgeCmp {
254  bool operator()(const Edge* a, const Edge* b) const {
255  return a->id_ < b->id_;
256  }
257 };
258 
259 typedef std::set<Edge*, EdgeCmp> EdgeSet;
260 
261 /// ImplicitDepLoader loads implicit dependencies, as referenced via the
262 /// "depfile" attribute in build files.
265  DiskInterface* disk_interface,
266  DepfileParserOptions const* depfile_parser_options)
267  : state_(state), disk_interface_(disk_interface), deps_log_(deps_log),
268  depfile_parser_options_(depfile_parser_options) {}
269 
270  /// Load implicit dependencies for \a edge.
271  /// @return false on error (without filling \a err if info is just missing
272  // or out of date).
273  bool LoadDeps(Edge* edge, std::string* err);
274 
275  DepsLog* deps_log() const {
276  return deps_log_;
277  }
278 
279  protected:
280  /// Process loaded implicit dependencies for \a edge and update the graph
281  /// @return false on error (without filling \a err if info is just missing)
282  virtual bool ProcessDepfileDeps(Edge* edge,
283  std::vector<StringPiece>* depfile_ins,
284  std::string* err);
285 
286  /// Load implicit dependencies for \a edge from a depfile attribute.
287  /// @return false on error (without filling \a err if info is just missing).
288  bool LoadDepFile(Edge* edge, const std::string& path, std::string* err);
289 
290  /// Load implicit dependencies for \a edge from the DepsLog.
291  /// @return false on error (without filling \a err if info is just missing).
292  bool LoadDepsFromLog(Edge* edge, std::string* err);
293 
294  /// Preallocate \a count spaces in the input array on \a edge, returning
295  /// an iterator pointing at the first new space.
296  std::vector<Node*>::iterator PreallocateSpace(Edge* edge, int count);
297 
298  /// If we don't have a edge that generates this input already,
299  /// create one; this makes us not abort if the input is missing,
300  /// but instead will rebuild in that circumstance.
301  void CreatePhonyInEdge(Node* node);
302 
307 };
308 
309 
310 /// DependencyScan manages the process of scanning the files in a graph
311 /// and updating the dirty/outputs_ready state of all the nodes and edges.
314  DiskInterface* disk_interface,
315  DepfileParserOptions const* depfile_parser_options)
317  disk_interface_(disk_interface),
318  dep_loader_(state, deps_log, disk_interface, depfile_parser_options),
319  dyndep_loader_(state, disk_interface) {}
320 
321  /// Update the |dirty_| state of the given nodes by transitively inspecting
322  /// their input edges.
323  /// Examine inputs, outputs, and command lines to judge whether an edge
324  /// needs to be re-run, and update outputs_ready_ and each outputs' |dirty_|
325  /// state accordingly.
326  /// Appends any validation nodes found to the nodes parameter.
327  /// Returns false on failure.
328  bool RecomputeDirty(Node* node, std::vector<Node*>* validation_nodes, std::string* err);
329 
330  /// Recompute whether any output of the edge is dirty, if so sets |*dirty|.
331  /// Returns false on failure.
332  bool RecomputeOutputsDirty(Edge* edge, Node* most_recent_input,
333  bool* dirty, std::string* err);
334 
335  BuildLog* build_log() const {
336  return build_log_;
337  }
338  void set_build_log(BuildLog* log) {
339  build_log_ = log;
340  }
341 
342  DepsLog* deps_log() const {
343  return dep_loader_.deps_log();
344  }
345 
346  /// Load a dyndep file from the given node's path and update the
347  /// build graph with the new information. One overload accepts
348  /// a caller-owned 'DyndepFile' object in which to store the
349  /// information loaded from the dyndep file.
350  bool LoadDyndeps(Node* node, std::string* err) const;
351  bool LoadDyndeps(Node* node, DyndepFile* ddf, std::string* err) const;
352 
353  private:
354  bool RecomputeNodeDirty(Node* node, std::vector<Node*>* stack,
355  std::vector<Node*>* validation_nodes, std::string* err);
356  bool VerifyDAG(Node* node, std::vector<Node*>* stack, std::string* err);
357 
358  /// Recompute whether a given single output should be marked dirty.
359  /// Returns true if so.
360  bool RecomputeOutputDirty(const Edge* edge, const Node* most_recent_input,
361  const std::string& command, Node* output);
362 
367 };
368 
369 #endif // NINJA_GRAPH_H_
bool dyndep_pending() const
Definition: graph.h:101
void AddValidationOutEdge(Edge *edge)
Definition: graph.h:113
bool RecomputeDirty(Node *node, std::vector< Node *> *validation_nodes, std::string *err)
Update the |dirty_| state of the given nodes by transitively inspecting their input edges...
Definition: graph.cc:50
std::vector< Edge * > out_edges_
All Edges that use this Node as an input.
Definition: graph.h:154
bool Stat(DiskInterface *disk_interface, std::string *err)
Return false on error.
Definition: graph.cc:34
The path is an actual file. mtime_ will be the file&#39;s mtime.
Definition: graph.h:136
bool RecomputeOutputDirty(const Edge *edge, const Node *most_recent_input, const std::string &command, Node *output)
Recompute whether a given single output should be marked dirty.
Definition: graph.cc:278
int order_only_deps_
Definition: graph.h:229
void Dump(const char *prefix="") const
Definition: graph.cc:515
int implicit_deps_
Definition: graph.h:228
DepsLog * deps_log() const
Definition: graph.h:275
bool generated_by_dep_loader_
Definition: graph.h:213
The file doesn&#39;t exist. mtime_ will be the latest mtime of its dependencies.
Definition: graph.h:134
Store data loaded from one dyndep file.
Definition: dyndep.h:40
VisitMark mark_
Definition: graph.h:208
void Dump(const char *prefix="") const
Definition: graph.cc:574
Edge * in_edge() const
Definition: graph.h:104
std::vector< Node * > validations_
Definition: graph.h:205
DepfileParserOptions const * depfile_parser_options_
Definition: graph.h:306
bool RecomputeOutputsDirty(Edge *edge, Node *most_recent_input, bool *dirty, std::string *err)
Recompute whether any output of the edge is dirty, if so sets |*dirty|.
Definition: graph.cc:265
void set_dirty(bool dirty)
Definition: graph.h:98
Information about a node in the dependency graph: the file, whether it&#39;s dirty, mtime, etc.
Definition: graph.h:39
virtual bool ProcessDepfileDeps(Edge *edge, std::vector< StringPiece > *depfile_ins, std::string *err)
Process loaded implicit dependencies for edge and update the graph.
Definition: graph.cc:685
bool outputs_ready() const
Definition: graph.h:218
DyndepLoader dyndep_loader_
Definition: graph.h:366
std::vector< Node * >::iterator PreallocateSpace(Edge *edge, int count)
Preallocate count spaces in the input array on edge, returning an iterator pointing at the first new ...
Definition: graph.cc:732
ImplicitDepLoader dep_loader_
Definition: graph.h:365
Interface for accessing the disk.
uint64_t slash_bits() const
Definition: graph.h:93
bool StatIfNecessary(DiskInterface *disk_interface, std::string *err)
Return false on error.
Definition: graph.h:57
bool is_implicit_out(size_t index) const
Definition: graph.h:244
bool LoadDyndeps(Node *node, std::string *err) const
Load a dyndep file from the given node&#39;s path and update the build graph with the new information...
std::vector< Node * > outputs_
Definition: graph.h:204
void AddOutEdge(Edge *edge)
Definition: graph.h:112
bool LoadDepsFromLog(Edge *edge, std::string *err)
Load implicit dependencies for edge from the DepsLog.
Definition: graph.cc:705
An edge in the dependency graph; links between Nodes using Rules.
Definition: graph.h:164
Edge * in_edge_
The Edge that produces this Node, or NULL when there is no known edge to produce it.
Definition: graph.h:151
bool LoadDepFile(Edge *edge, const std::string &path, std::string *err)
Load implicit dependencies for edge from a depfile attribute.
Definition: graph.cc:622
Store a log of every command ran for every build.
Definition: build_log.h:43
std::string PathDecanonicalized() const
Get |path()| but use slash_bits to convert back to original slash styles.
Definition: graph.h:88
bool is_order_only(size_t index)
Definition: graph.h:234
const std::string & path() const
Definition: graph.h:86
int id() const
Definition: graph.h:107
void MarkDirty()
Definition: graph.h:99
int weight() const
Definition: graph.h:217
std::string path_
Definition: graph.h:118
As build commands run they can output extra dependency information (e.g.
Definition: deps_log.h:68
An Env which contains a mapping of variables to values as well as a pointer to a parent scope...
Definition: eval_env.h:81
bool outputs_ready_
Definition: graph.h:210
bool RecomputeNodeDirty(Node *node, std::vector< Node *> *stack, std::vector< Node *> *validation_nodes, std::string *err)
Definition: graph.cc:83
bool is_implicit(size_t index)
Definition: graph.h:230
void set_dyndep_pending(bool pending)
Definition: graph.h:102
void set_id(int id)
Definition: graph.h:108
DiskInterface * disk_interface_
Definition: graph.h:364
DepsLog * deps_log_
Definition: graph.h:305
BindingEnv * env_
Definition: graph.h:207
An invocable build command and associated metadata (description, etc.).
Definition: eval_env.h:59
void ResetState()
Mark as not-yet-stat()ed and not dirty.
Definition: graph.h:64
void MarkMissing()
Mark the Node as already-stat()ed and missing.
Definition: graph.h:71
bool dirty() const
Definition: graph.h:97
void UpdatePhonyMtime(TimeStamp mtime)
If the file doesn&#39;t exist, set the mtime_ from its dependencies.
Definition: graph.cc:44
bool operator()(const Edge *a, const Edge *b) const
Definition: graph.h:254
uint64_t slash_bits_
Set bits starting from lowest for backslashes that were normalized to forward slashes by Canonicalize...
Definition: graph.h:122
std::string GetUnescapedRspfile() const
Like GetBinding("rspfile"), but without shell escaping.
Definition: graph.cc:510
BuildLog * build_log_
Definition: graph.h:363
bool VerifyDAG(Node *node, std::vector< Node *> *stack, std::string *err)
Definition: graph.cc:226
ImplicitDepLoader(State *state, DepsLog *deps_log, DiskInterface *disk_interface, DepfileParserOptions const *depfile_parser_options)
Definition: graph.h:264
DepsLog * deps_log() const
Definition: graph.h:342
std::vector< Edge * > validation_out_edges_
All Edges that use this Node as a validation.
Definition: graph.h:157
BuildLog * build_log() const
Definition: graph.h:335
Edge()
Definition: graph.h:171
Node(const std::string &path, uint64_t slash_bits)
Definition: graph.h:40
int implicit_outs_
Definition: graph.h:243
void CreatePhonyInEdge(Node *node)
If we don&#39;t have a edge that generates this input already, create one; this makes us not abort if the...
Definition: graph.cc:740
int64_t TimeStamp
Definition: timestamp.h:31
bool LoadDeps(Edge *edge, std::string *err)
Load implicit dependencies for edge.
Definition: graph.cc:598
DyndepLoader loads dynamically discovered dependencies, as referenced via the "dyndep" attribute in b...
Definition: dyndep.h:44
A pool for delayed edges.
Definition: state.h:40
void set_build_log(BuildLog *log)
Definition: graph.h:338
TimeStamp mtime_
Possible values of mtime_: -1: file hasn&#39;t been examined 0: we looked, and file doesn&#39;t exist >0: act...
Definition: graph.h:128
std::vector< Node * > inputs_
Definition: graph.h:203
std::string GetUnescapedDepfile() const
Like GetBinding("depfile"), but without shell escaping.
Definition: graph.cc:500
bool status_known() const
Definition: graph.h:82
bool dirty_
Dirty is true when the underlying file is out-of-date.
Definition: graph.h:143
int id_
A dense integer id for the node, assigned and used by DepsLog.
Definition: graph.h:160
Pool * pool_
Definition: graph.h:202
ExistenceStatus
Definition: graph.h:130
std::string GetBinding(const std::string &key) const
Returns the shell-escaped value of |key|.
Definition: graph.cc:491
TimeStamp mtime() const
Definition: graph.h:95
DependencyScan manages the process of scanning the files in a graph and updating the dirty/outputs_re...
Definition: graph.h:312
const Rule * rule_
Definition: graph.h:201
ImplicitDepLoader loads implicit dependencies, as referenced via the "depfile" attribute in build fil...
Definition: graph.h:263
VisitMark
Definition: graph.h:165
const Rule & rule() const
Definition: graph.h:215
Pool * pool() const
Definition: graph.h:216
std::string EvaluateCommand(bool incl_rsp_file=false) const
Expand all variables in a command and return it as a string.
Definition: graph.cc:481
bool AllInputsReady() const
Return true if all inputs&#39; in-edges are ready.
Definition: graph.cc:374
bool maybe_phonycycle_diagnostic() const
Definition: graph.cc:551
const std::vector< Edge * > & validation_out_edges() const
Definition: graph.h:111
The file hasn&#39;t been examined.
Definition: graph.h:132
const std::vector< Edge * > & out_edges() const
Definition: graph.h:110
State * state_
Definition: graph.h:303
Global state (file status) for a single run.
Definition: state.h:92
void set_in_edge(Edge *edge)
Definition: graph.h:105
bool deps_loaded_
Definition: graph.h:211
unsigned long long uint64_t
Definition: win32port.h:29
DiskInterface * disk_interface_
Definition: graph.h:304
bool is_phony() const
Definition: graph.cc:543
Definition: graph.h:253
bool use_console() const
Definition: graph.cc:547
bool GetBindingBool(const std::string &key) const
Definition: graph.cc:496
void CollectInputs(bool shell_escape, std::vector< std::string > *out) const
Definition: graph.cc:459
std::string GetUnescapedDyndep() const
Like GetBinding("dyndep"), but without shell escaping.
Definition: graph.cc:505
bool exists() const
Definition: graph.h:78
size_t id_
Definition: graph.h:209
std::set< Edge *, EdgeCmp > EdgeSet
Definition: graph.h:259
ExistenceStatus exists_
Definition: graph.h:138
bool dyndep_pending_
Store whether dyndep information is expected from this node but has not yet been loaded.
Definition: graph.h:147
Node * dyndep_
Definition: graph.h:206
bool deps_missing_
Definition: graph.h:212
DependencyScan(State *state, BuildLog *build_log, DepsLog *deps_log, DiskInterface *disk_interface, DepfileParserOptions const *depfile_parser_options)
Definition: graph.h:313