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