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