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 "eval_env.h"
23 #include "timestamp.h"
24 #include "util.h"
25 
26 struct BuildLog;
27 struct DiskInterface;
28 struct DepsLog;
29 struct Edge;
30 struct Node;
31 struct Pool;
32 struct State;
33 
34 /// Information about a node in the dependency graph: the file, whether
35 /// it's dirty, mtime, etc.
36 struct Node {
NodeNode37   Node(const string& path, uint64_t slash_bits)
38       : path_(path),
39         slash_bits_(slash_bits),
40         mtime_(-1),
41         dirty_(false),
42         in_edge_(NULL),
43         id_(-1) {}
44 
45   /// Return false on error.
46   bool Stat(DiskInterface* disk_interface, string* err);
47 
48   /// Return false on error.
StatIfNecessaryNode49   bool StatIfNecessary(DiskInterface* disk_interface, string* err) {
50     if (status_known())
51       return true;
52     return Stat(disk_interface, err);
53   }
54 
55   /// Mark as not-yet-stat()ed and not dirty.
ResetStateNode56   void ResetState() {
57     mtime_ = -1;
58     dirty_ = false;
59   }
60 
61   /// Mark the Node as already-stat()ed and missing.
MarkMissingNode62   void MarkMissing() {
63     mtime_ = 0;
64   }
65 
existsNode66   bool exists() const {
67     return mtime_ != 0;
68   }
69 
status_knownNode70   bool status_known() const {
71     return mtime_ != -1;
72   }
73 
pathNode74   const string& path() const { return path_; }
75   /// Get |path()| but use slash_bits to convert back to original slash styles.
PathDecanonicalizedNode76   string PathDecanonicalized() const {
77     return PathDecanonicalized(path_, slash_bits_);
78   }
79   static string PathDecanonicalized(const string& path,
80                                     uint64_t slash_bits);
slash_bitsNode81   uint64_t slash_bits() const { return slash_bits_; }
82 
mtimeNode83   TimeStamp mtime() const { return mtime_; }
84 
dirtyNode85   bool dirty() const { return dirty_; }
set_dirtyNode86   void set_dirty(bool dirty) { dirty_ = dirty; }
MarkDirtyNode87   void MarkDirty() { dirty_ = true; }
88 
in_edgeNode89   Edge* in_edge() const { return in_edge_; }
set_in_edgeNode90   void set_in_edge(Edge* edge) { in_edge_ = edge; }
91 
idNode92   int id() const { return id_; }
set_idNode93   void set_id(int id) { id_ = id; }
94 
out_edgesNode95   const vector<Edge*>& out_edges() const { return out_edges_; }
AddOutEdgeNode96   void AddOutEdge(Edge* edge) { out_edges_.push_back(edge); }
97 
98   void Dump(const char* prefix="") const;
99 
100 private:
101   string path_;
102 
103   /// Set bits starting from lowest for backslashes that were normalized to
104   /// forward slashes by CanonicalizePath. See |PathDecanonicalized|.
105   uint64_t slash_bits_;
106 
107   /// Possible values of mtime_:
108   ///   -1: file hasn't been examined
109   ///   0:  we looked, and file doesn't exist
110   ///   >0: actual file's mtime
111   TimeStamp mtime_;
112 
113   /// Dirty is true when the underlying file is out-of-date.
114   /// But note that Edge::outputs_ready_ is also used in judging which
115   /// edges to build.
116   bool dirty_;
117 
118   /// The Edge that produces this Node, or NULL when there is no
119   /// known edge to produce it.
120   Edge* in_edge_;
121 
122   /// All Edges that use this Node as an input.
123   vector<Edge*> out_edges_;
124 
125   /// A dense integer id for the node, assigned and used by DepsLog.
126   int id_;
127 };
128 
129 /// An edge in the dependency graph; links between Nodes using Rules.
130 struct Edge {
131   enum VisitMark {
132     VisitNone,
133     VisitInStack,
134     VisitDone
135   };
136 
EdgeEdge137   Edge() : rule_(NULL), pool_(NULL), env_(NULL), mark_(VisitNone),
138            outputs_ready_(false), deps_missing_(false),
139            implicit_deps_(0), order_only_deps_(0), implicit_outs_(0) {}
140 
141   /// Return true if all inputs' in-edges are ready.
142   bool AllInputsReady() const;
143 
144   /// Expand all variables in a command and return it as a string.
145   /// If incl_rsp_file is enabled, the string will also contain the
146   /// full contents of a response file (if applicable)
147   string EvaluateCommand(bool incl_rsp_file = false);
148 
149   /// Returns the shell-escaped value of |key|.
150   string GetBinding(const string& key);
151   bool GetBindingBool(const string& key);
152 
153   /// Like GetBinding("depfile"), but without shell escaping.
154   string GetUnescapedDepfile();
155   /// Like GetBinding("rspfile"), but without shell escaping.
156   string GetUnescapedRspfile();
157 
158   void Dump(const char* prefix="") const;
159 
160   const Rule* rule_;
161   Pool* pool_;
162   vector<Node*> inputs_;
163   vector<Node*> outputs_;
164   BindingEnv* env_;
165   VisitMark mark_;
166   bool outputs_ready_;
167   bool deps_missing_;
168 
ruleEdge169   const Rule& rule() const { return *rule_; }
poolEdge170   Pool* pool() const { return pool_; }
weightEdge171   int weight() const { return 1; }
outputs_readyEdge172   bool outputs_ready() const { return outputs_ready_; }
173 
174   // There are three types of inputs.
175   // 1) explicit deps, which show up as $in on the command line;
176   // 2) implicit deps, which the target depends on implicitly (e.g. C headers),
177   //                   and changes in them cause the target to rebuild;
178   // 3) order-only deps, which are needed before the target builds but which
179   //                     don't cause the target to rebuild.
180   // These are stored in inputs_ in that order, and we keep counts of
181   // #2 and #3 when we need to access the various subsets.
182   int implicit_deps_;
183   int order_only_deps_;
is_implicitEdge184   bool is_implicit(size_t index) {
185     return index >= inputs_.size() - order_only_deps_ - implicit_deps_ &&
186         !is_order_only(index);
187   }
is_order_onlyEdge188   bool is_order_only(size_t index) {
189     return index >= inputs_.size() - order_only_deps_;
190   }
191 
192   // There are two types of outputs.
193   // 1) explicit outs, which show up as $out on the command line;
194   // 2) implicit outs, which the target generates but are not part of $out.
195   // These are stored in outputs_ in that order, and we keep a count of
196   // #2 to use when we need to access the various subsets.
197   int implicit_outs_;
is_implicit_outEdge198   bool is_implicit_out(size_t index) const {
199     return index >= outputs_.size() - implicit_outs_;
200   }
201 
202   bool is_phony() const;
203   bool use_console() const;
204   bool maybe_phonycycle_diagnostic() const;
205 };
206 
207 
208 /// ImplicitDepLoader loads implicit dependencies, as referenced via the
209 /// "depfile" attribute in build files.
210 struct ImplicitDepLoader {
ImplicitDepLoaderImplicitDepLoader211   ImplicitDepLoader(State* state, DepsLog* deps_log,
212                     DiskInterface* disk_interface)
213       : state_(state), disk_interface_(disk_interface), deps_log_(deps_log) {}
214 
215   /// Load implicit dependencies for \a edge.
216   /// @return false on error (without filling \a err if info is just missing
217   //                          or out of date).
218   bool LoadDeps(Edge* edge, string* err);
219 
deps_logImplicitDepLoader220   DepsLog* deps_log() const {
221     return deps_log_;
222   }
223 
224  private:
225   /// Load implicit dependencies for \a edge from a depfile attribute.
226   /// @return false on error (without filling \a err if info is just missing).
227   bool LoadDepFile(Edge* edge, const string& path, string* err);
228 
229   /// Load implicit dependencies for \a edge from the DepsLog.
230   /// @return false on error (without filling \a err if info is just missing).
231   bool LoadDepsFromLog(Edge* edge, string* err);
232 
233   /// Preallocate \a count spaces in the input array on \a edge, returning
234   /// an iterator pointing at the first new space.
235   vector<Node*>::iterator PreallocateSpace(Edge* edge, int count);
236 
237   /// If we don't have a edge that generates this input already,
238   /// create one; this makes us not abort if the input is missing,
239   /// but instead will rebuild in that circumstance.
240   void CreatePhonyInEdge(Node* node);
241 
242   State* state_;
243   DiskInterface* disk_interface_;
244   DepsLog* deps_log_;
245 };
246 
247 
248 /// DependencyScan manages the process of scanning the files in a graph
249 /// and updating the dirty/outputs_ready state of all the nodes and edges.
250 struct DependencyScan {
DependencyScanDependencyScan251   DependencyScan(State* state, BuildLog* build_log, DepsLog* deps_log,
252                  DiskInterface* disk_interface)
253       : build_log_(build_log),
254         disk_interface_(disk_interface),
255         dep_loader_(state, deps_log, disk_interface) {}
256 
257   /// Update the |dirty_| state of the given node by inspecting its input edge.
258   /// Examine inputs, outputs, and command lines to judge whether an edge
259   /// needs to be re-run, and update outputs_ready_ and each outputs' |dirty_|
260   /// state accordingly.
261   /// Returns false on failure.
262   bool RecomputeDirty(Node* node, string* err);
263 
264   /// Recompute whether any output of the edge is dirty, if so sets |*dirty|.
265   /// Returns false on failure.
266   bool RecomputeOutputsDirty(Edge* edge, Node* most_recent_input,
267                              bool* dirty, string* err);
268 
build_logDependencyScan269   BuildLog* build_log() const {
270     return build_log_;
271   }
set_build_logDependencyScan272   void set_build_log(BuildLog* log) {
273     build_log_ = log;
274   }
275 
deps_logDependencyScan276   DepsLog* deps_log() const {
277     return dep_loader_.deps_log();
278   }
279 
280  private:
281   bool RecomputeDirty(Node* node, vector<Node*>* stack, string* err);
282   bool VerifyDAG(Node* node, vector<Node*>* stack, string* err);
283 
284   /// Recompute whether a given single output should be marked dirty.
285   /// Returns true if so.
286   bool RecomputeOutputDirty(Edge* edge, Node* most_recent_input,
287                             const string& command, Node* output);
288 
289   BuildLog* build_log_;
290   DiskInterface* disk_interface_;
291   ImplicitDepLoader dep_loader_;
292 };
293 
294 #endif  // NINJA_GRAPH_H_
295