• 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 <string>
19 #include <vector>
20 using namespace std;
21 
22 #include "dyndep.h"
23 #include "eval_env.h"
24 #include "timestamp.h"
25 #include "util.h"
26 
27 struct BuildLog;
28 struct DepfileParserOptions;
29 struct DiskInterface;
30 struct DepsLog;
31 struct Edge;
32 struct Node;
33 struct Pool;
34 struct State;
35 
36 /// Information about a node in the dependency graph: the file, whether
37 /// it's dirty, mtime, etc.
38 struct Node {
NodeNode39   Node(const string& path, uint64_t slash_bits)
40       : path_(path),
41         slash_bits_(slash_bits),
42         mtime_(-1),
43         dirty_(false),
44         dyndep_pending_(false),
45         in_edge_(NULL),
46         id_(-1) {}
47 
48   /// Return false on error.
49   bool Stat(DiskInterface* disk_interface, string* err);
50 
51   /// Return false on error.
StatIfNecessaryNode52   bool StatIfNecessary(DiskInterface* disk_interface, string* err) {
53     if (status_known())
54       return true;
55     return Stat(disk_interface, err);
56   }
57 
58   /// Mark as not-yet-stat()ed and not dirty.
ResetStateNode59   void ResetState() {
60     mtime_ = -1;
61     dirty_ = false;
62   }
63 
64   /// Mark the Node as already-stat()ed and missing.
MarkMissingNode65   void MarkMissing() {
66     mtime_ = 0;
67   }
68 
existsNode69   bool exists() const {
70     return mtime_ != 0;
71   }
72 
status_knownNode73   bool status_known() const {
74     return mtime_ != -1;
75   }
76 
pathNode77   const string& path() const { return path_; }
78   /// Get |path()| but use slash_bits to convert back to original slash styles.
PathDecanonicalizedNode79   string PathDecanonicalized() const {
80     return PathDecanonicalized(path_, slash_bits_);
81   }
82   static string PathDecanonicalized(const string& path,
83                                     uint64_t slash_bits);
slash_bitsNode84   uint64_t slash_bits() const { return slash_bits_; }
85 
mtimeNode86   TimeStamp mtime() const { return mtime_; }
87 
dirtyNode88   bool dirty() const { return dirty_; }
set_dirtyNode89   void set_dirty(bool dirty) { dirty_ = dirty; }
MarkDirtyNode90   void MarkDirty() { dirty_ = true; }
91 
dyndep_pendingNode92   bool dyndep_pending() const { return dyndep_pending_; }
set_dyndep_pendingNode93   void set_dyndep_pending(bool pending) { dyndep_pending_ = pending; }
94 
in_edgeNode95   Edge* in_edge() const { return in_edge_; }
set_in_edgeNode96   void set_in_edge(Edge* edge) { in_edge_ = edge; }
97 
idNode98   int id() const { return id_; }
set_idNode99   void set_id(int id) { id_ = id; }
100 
out_edgesNode101   const vector<Edge*>& out_edges() const { return out_edges_; }
AddOutEdgeNode102   void AddOutEdge(Edge* edge) { out_edges_.push_back(edge); }
103 
104   void Dump(const char* prefix="") const;
105 
106 private:
107   string path_;
108 
109   /// Set bits starting from lowest for backslashes that were normalized to
110   /// forward slashes by CanonicalizePath. See |PathDecanonicalized|.
111   uint64_t slash_bits_;
112 
113   /// Possible values of mtime_:
114   ///   -1: file hasn't been examined
115   ///   0:  we looked, and file doesn't exist
116   ///   >0: actual file's mtime
117   TimeStamp mtime_;
118 
119   /// Dirty is true when the underlying file is out-of-date.
120   /// But note that Edge::outputs_ready_ is also used in judging which
121   /// edges to build.
122   bool dirty_;
123 
124   /// Store whether dyndep information is expected from this node but
125   /// has not yet been loaded.
126   bool dyndep_pending_;
127 
128   /// The Edge that produces this Node, or NULL when there is no
129   /// known edge to produce it.
130   Edge* in_edge_;
131 
132   /// All Edges that use this Node as an input.
133   vector<Edge*> out_edges_;
134 
135   /// A dense integer id for the node, assigned and used by DepsLog.
136   int id_;
137 };
138 
139 /// An edge in the dependency graph; links between Nodes using Rules.
140 struct Edge {
141   enum VisitMark {
142     VisitNone,
143     VisitInStack,
144     VisitDone
145   };
146 
EdgeEdge147   Edge() : rule_(NULL), pool_(NULL), dyndep_(NULL), env_(NULL),
148            mark_(VisitNone), outputs_ready_(false), deps_loaded_(false),
149            deps_missing_(false), implicit_deps_(0), order_only_deps_(0),
150            implicit_outs_(0) {}
151 
152   /// Return true if all inputs' in-edges are ready.
153   bool AllInputsReady() const;
154 
155   /// Expand all variables in a command and return it as a string.
156   /// If incl_rsp_file is enabled, the string will also contain the
157   /// full contents of a response file (if applicable)
158   std::string EvaluateCommand(bool incl_rsp_file = false) const;
159 
160   /// Returns the shell-escaped value of |key|.
161   std::string GetBinding(const string& key) const;
162   bool GetBindingBool(const string& key) const;
163 
164   /// Like GetBinding("depfile"), but without shell escaping.
165   string GetUnescapedDepfile() const;
166   /// Like GetBinding("dyndep"), but without shell escaping.
167   string GetUnescapedDyndep() const;
168   /// Like GetBinding("rspfile"), but without shell escaping.
169   std::string GetUnescapedRspfile() const;
170 
171   void Dump(const char* prefix="") const;
172 
173   const Rule* rule_;
174   Pool* pool_;
175   vector<Node*> inputs_;
176   vector<Node*> outputs_;
177   Node* dyndep_;
178   BindingEnv* env_;
179   VisitMark mark_;
180   bool outputs_ready_;
181   bool deps_loaded_;
182   bool deps_missing_;
183 
ruleEdge184   const Rule& rule() const { return *rule_; }
poolEdge185   Pool* pool() const { return pool_; }
weightEdge186   int weight() const { return 1; }
outputs_readyEdge187   bool outputs_ready() const { return outputs_ready_; }
188 
189   // There are three types of inputs.
190   // 1) explicit deps, which show up as $in on the command line;
191   // 2) implicit deps, which the target depends on implicitly (e.g. C headers),
192   //                   and changes in them cause the target to rebuild;
193   // 3) order-only deps, which are needed before the target builds but which
194   //                     don't cause the target to rebuild.
195   // These are stored in inputs_ in that order, and we keep counts of
196   // #2 and #3 when we need to access the various subsets.
197   int implicit_deps_;
198   int order_only_deps_;
is_implicitEdge199   bool is_implicit(size_t index) {
200     return index >= inputs_.size() - order_only_deps_ - implicit_deps_ &&
201         !is_order_only(index);
202   }
is_order_onlyEdge203   bool is_order_only(size_t index) {
204     return index >= inputs_.size() - order_only_deps_;
205   }
206 
207   // There are two types of outputs.
208   // 1) explicit outs, which show up as $out on the command line;
209   // 2) implicit outs, which the target generates but are not part of $out.
210   // These are stored in outputs_ in that order, and we keep a count of
211   // #2 to use when we need to access the various subsets.
212   int implicit_outs_;
is_implicit_outEdge213   bool is_implicit_out(size_t index) const {
214     return index >= outputs_.size() - implicit_outs_;
215   }
216 
217   bool is_phony() const;
218   bool use_console() const;
219   bool maybe_phonycycle_diagnostic() const;
220 };
221 
222 
223 /// ImplicitDepLoader loads implicit dependencies, as referenced via the
224 /// "depfile" attribute in build files.
225 struct ImplicitDepLoader {
ImplicitDepLoaderImplicitDepLoader226   ImplicitDepLoader(State* state, DepsLog* deps_log,
227                     DiskInterface* disk_interface,
228                     DepfileParserOptions const* depfile_parser_options)
229       : state_(state), disk_interface_(disk_interface), deps_log_(deps_log),
230         depfile_parser_options_(depfile_parser_options) {}
231 
232   /// Load implicit dependencies for \a edge.
233   /// @return false on error (without filling \a err if info is just missing
234   //                          or out of date).
235   bool LoadDeps(Edge* edge, string* err);
236 
deps_logImplicitDepLoader237   DepsLog* deps_log() const {
238     return deps_log_;
239   }
240 
241  private:
242   /// Load implicit dependencies for \a edge from a depfile attribute.
243   /// @return false on error (without filling \a err if info is just missing).
244   bool LoadDepFile(Edge* edge, const string& path, string* err);
245 
246   /// Load implicit dependencies for \a edge from the DepsLog.
247   /// @return false on error (without filling \a err if info is just missing).
248   bool LoadDepsFromLog(Edge* edge, string* err);
249 
250   /// Preallocate \a count spaces in the input array on \a edge, returning
251   /// an iterator pointing at the first new space.
252   vector<Node*>::iterator PreallocateSpace(Edge* edge, int count);
253 
254   /// If we don't have a edge that generates this input already,
255   /// create one; this makes us not abort if the input is missing,
256   /// but instead will rebuild in that circumstance.
257   void CreatePhonyInEdge(Node* node);
258 
259   State* state_;
260   DiskInterface* disk_interface_;
261   DepsLog* deps_log_;
262   DepfileParserOptions const* depfile_parser_options_;
263 };
264 
265 
266 /// DependencyScan manages the process of scanning the files in a graph
267 /// and updating the dirty/outputs_ready state of all the nodes and edges.
268 struct DependencyScan {
DependencyScanDependencyScan269   DependencyScan(State* state, BuildLog* build_log, DepsLog* deps_log,
270                  DiskInterface* disk_interface,
271                  DepfileParserOptions const* depfile_parser_options)
272       : build_log_(build_log),
273         disk_interface_(disk_interface),
274         dep_loader_(state, deps_log, disk_interface, depfile_parser_options),
275         dyndep_loader_(state, disk_interface) {}
276 
277   /// Update the |dirty_| state of the given node by inspecting its input edge.
278   /// Examine inputs, outputs, and command lines to judge whether an edge
279   /// needs to be re-run, and update outputs_ready_ and each outputs' |dirty_|
280   /// state accordingly.
281   /// Returns false on failure.
282   bool RecomputeDirty(Node* node, string* err);
283 
284   /// Recompute whether any output of the edge is dirty, if so sets |*dirty|.
285   /// Returns false on failure.
286   bool RecomputeOutputsDirty(Edge* edge, Node* most_recent_input,
287                              bool* dirty, string* err);
288 
build_logDependencyScan289   BuildLog* build_log() const {
290     return build_log_;
291   }
set_build_logDependencyScan292   void set_build_log(BuildLog* log) {
293     build_log_ = log;
294   }
295 
deps_logDependencyScan296   DepsLog* deps_log() const {
297     return dep_loader_.deps_log();
298   }
299 
300   /// Load a dyndep file from the given node's path and update the
301   /// build graph with the new information.  One overload accepts
302   /// a caller-owned 'DyndepFile' object in which to store the
303   /// information loaded from the dyndep file.
304   bool LoadDyndeps(Node* node, string* err) const;
305   bool LoadDyndeps(Node* node, DyndepFile* ddf, string* err) const;
306 
307  private:
308   bool RecomputeDirty(Node* node, vector<Node*>* stack, string* err);
309   bool VerifyDAG(Node* node, vector<Node*>* stack, string* err);
310 
311   /// Recompute whether a given single output should be marked dirty.
312   /// Returns true if so.
313   bool RecomputeOutputDirty(const Edge* edge, const Node* most_recent_input,
314                             const string& command, Node* output);
315 
316   BuildLog* build_log_;
317   DiskInterface* disk_interface_;
318   ImplicitDepLoader dep_loader_;
319   DyndepLoader dyndep_loader_;
320 };
321 
322 #endif  // NINJA_GRAPH_H_
323