• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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;
29 struct DepfileParserOptions;
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 {
NodeNode40   Node(const std::string& path, uint64_t slash_bits)
41       : path_(path),
42         slash_bits_(slash_bits),
43         mtime_(-1),
44         exists_(ExistenceStatusUnknown),
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
54   void UpdatePhonyMtime(TimeStamp mtime);
55 
56   /// Return false on error.
StatIfNecessaryNode57   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.
ResetStateNode64   void ResetState() {
65     mtime_ = -1;
66     exists_ = ExistenceStatusUnknown;
67     dirty_ = false;
68   }
69 
70   /// Mark the Node as already-stat()ed and missing.
MarkMissingNode71   void MarkMissing() {
72     if (mtime_ == -1) {
73       mtime_ = 0;
74     }
75     exists_ = ExistenceStatusMissing;
76   }
77 
existsNode78   bool exists() const {
79     return exists_ == ExistenceStatusExists;
80   }
81 
status_knownNode82   bool status_known() const {
83     return exists_ != ExistenceStatusUnknown;
84   }
85 
pathNode86   const std::string& path() const { return path_; }
87   /// Get |path()| but use slash_bits to convert back to original slash styles.
PathDecanonicalizedNode88   std::string PathDecanonicalized() const {
89     return PathDecanonicalized(path_, slash_bits_);
90   }
91   static std::string PathDecanonicalized(const std::string& path,
92                                          uint64_t slash_bits);
slash_bitsNode93   uint64_t slash_bits() const { return slash_bits_; }
94 
mtimeNode95   TimeStamp mtime() const { return mtime_; }
96 
dirtyNode97   bool dirty() const { return dirty_; }
set_dirtyNode98   void set_dirty(bool dirty) { dirty_ = dirty; }
MarkDirtyNode99   void MarkDirty() { dirty_ = true; }
100 
dyndep_pendingNode101   bool dyndep_pending() const { return dyndep_pending_; }
set_dyndep_pendingNode102   void set_dyndep_pending(bool pending) { dyndep_pending_ = pending; }
103 
in_edgeNode104   Edge* in_edge() const { return in_edge_; }
set_in_edgeNode105   void set_in_edge(Edge* edge) { in_edge_ = edge; }
106 
idNode107   int id() const { return id_; }
set_idNode108   void set_id(int id) { id_ = id; }
109 
out_edgesNode110   const std::vector<Edge*>& out_edges() const { return out_edges_; }
validation_out_edgesNode111   const std::vector<Edge*>& validation_out_edges() const { return validation_out_edges_; }
AddOutEdgeNode112   void AddOutEdge(Edge* edge) { out_edges_.push_back(edge); }
AddValidationOutEdgeNode113   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|.
122   uint64_t slash_bits_;
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
128   TimeStamp mtime_;
129 
130   enum ExistenceStatus {
131     /// The file hasn't been examined.
132     ExistenceStatusUnknown,
133     /// The file doesn't exist. mtime_ will be the latest mtime of its dependencies.
134     ExistenceStatusMissing,
135     /// The path is an actual file. mtime_ will be the file's mtime.
136     ExistenceStatusExists
137   };
138   ExistenceStatus exists_;
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.
147   bool dyndep_pending_;
148 
149   /// The Edge that produces this Node, or NULL when there is no
150   /// known edge to produce it.
151   Edge* in_edge_;
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 {
166     VisitNone,
167     VisitInStack,
168     VisitDone
169   };
170 
EdgeEdge171   Edge()
172       : rule_(NULL), pool_(NULL), dyndep_(NULL), env_(NULL), mark_(VisitNone),
173         id_(0), outputs_ready_(false), deps_loaded_(false),
174         deps_missing_(false), generated_by_dep_loader_(false),
175         implicit_deps_(0), order_only_deps_(0), implicit_outs_(0) {}
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_;
202   Pool* pool_;
203   std::vector<Node*> inputs_;
204   std::vector<Node*> outputs_;
205   std::vector<Node*> validations_;
206   Node* dyndep_;
207   BindingEnv* env_;
208   VisitMark mark_;
209   size_t id_;
210   bool outputs_ready_;
211   bool deps_loaded_;
212   bool deps_missing_;
213   bool generated_by_dep_loader_;
214 
ruleEdge215   const Rule& rule() const { return *rule_; }
poolEdge216   Pool* pool() const { return pool_; }
weightEdge217   int weight() const { return 1; }
outputs_readyEdge218   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.
228   int implicit_deps_;
229   int order_only_deps_;
is_implicitEdge230   bool is_implicit(size_t index) {
231     return index >= inputs_.size() - order_only_deps_ - implicit_deps_ &&
232         !is_order_only(index);
233   }
is_order_onlyEdge234   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.
243   int implicit_outs_;
is_implicit_outEdge244   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 {
operatorEdgeCmp254   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.
263 struct ImplicitDepLoader {
ImplicitDepLoaderImplicitDepLoader264   ImplicitDepLoader(State* state, DepsLog* deps_log,
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 
deps_logImplicitDepLoader275   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 
303   State* state_;
304   DiskInterface* disk_interface_;
305   DepsLog* deps_log_;
306   DepfileParserOptions const* depfile_parser_options_;
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.
312 struct DependencyScan {
DependencyScanDependencyScan313   DependencyScan(State* state, BuildLog* build_log, DepsLog* deps_log,
314                  DiskInterface* disk_interface,
315                  DepfileParserOptions const* depfile_parser_options)
316       : build_log_(build_log),
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 
build_logDependencyScan335   BuildLog* build_log() const {
336     return build_log_;
337   }
set_build_logDependencyScan338   void set_build_log(BuildLog* log) {
339     build_log_ = log;
340   }
341 
deps_logDependencyScan342   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 
363   BuildLog* build_log_;
364   DiskInterface* disk_interface_;
365   ImplicitDepLoader dep_loader_;
366   DyndepLoader dyndep_loader_;
367 };
368 
369 #endif  // NINJA_GRAPH_H_
370