Ninja
graph.h
Go to the documentation of this file.
00001 // Copyright 2011 Google Inc. All Rights Reserved.
00002 //
00003 // Licensed under the Apache License, Version 2.0 (the "License");
00004 // you may not use this file except in compliance with the License.
00005 // You may obtain a copy of the License at
00006 //
00007 //     http://www.apache.org/licenses/LICENSE-2.0
00008 //
00009 // Unless required by applicable law or agreed to in writing, software
00010 // distributed under the License is distributed on an "AS IS" BASIS,
00011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00012 // See the License for the specific language governing permissions and
00013 // limitations under the License.
00014 
00015 #ifndef NINJA_GRAPH_H_
00016 #define NINJA_GRAPH_H_
00017 
00018 #include <string>
00019 #include <vector>
00020 using namespace std;
00021 
00022 #include "eval_env.h"
00023 
00024 struct DiskInterface;
00025 
00026 struct Node;
00027 
00028 /// Information about a single on-disk file: path, mtime.
00029 struct FileStat {
00030   FileStat(const string& path) : path_(path), mtime_(-1), node_(NULL) {}
00031 
00032   /// Return true if the file exists (mtime_ got a value).
00033   bool Stat(DiskInterface* disk_interface);
00034 
00035   /// Return true if we needed to stat.
00036   bool StatIfNecessary(DiskInterface* disk_interface) {
00037     if (status_known())
00038       return false;
00039     Stat(disk_interface);
00040     return true;
00041   }
00042 
00043   bool exists() const {
00044     return mtime_ != 0;
00045   }
00046 
00047   bool status_known() const {
00048     return mtime_ != -1;
00049   }
00050 
00051   string path_;
00052   // Possible values of mtime_:
00053   //   -1: file hasn't been examined
00054   //   0:  we looked, and file doesn't exist
00055   //   >0: actual file's mtime
00056   time_t mtime_;
00057   Node* node_;
00058 };
00059 
00060 /// An invokable build command and associated metadata (description, etc.).
00061 struct Rule {
00062   Rule(const string& name) : name_(name), generator_(false), restat_(false) { }
00063 
00064   bool ParseCommand(const string& command, string* err) {
00065     return command_.Parse(command, err);
00066   }
00067   string name_;
00068   EvalString command_;
00069   EvalString description_;
00070   EvalString depfile_;
00071   bool generator_, restat_;
00072 };
00073 
00074 struct BuildLog;
00075 struct Node;
00076 struct State;
00077 
00078 /// An edge in the dependency graph; links between Nodes using Rules.
00079 struct Edge {
00080   Edge() : rule_(NULL), env_(NULL), outputs_ready_(false), implicit_deps_(0),
00081            order_only_deps_(0) {}
00082 
00083   bool RecomputeDirty(State* state, DiskInterface* disk_interface, string* err);
00084   void RecomputeOutputDirty(BuildLog* build_log, time_t most_recent_input,
00085                             bool dirty, const string& command, Node* output);
00086   string EvaluateCommand();  // XXX move to env, take env ptr
00087   string GetDescription();
00088   bool LoadDepFile(State* state, DiskInterface* disk_interface, string* err);
00089 
00090   void Dump();
00091 
00092   const Rule* rule_;
00093   vector<Node*> inputs_;
00094   vector<Node*> outputs_;
00095   Env* env_;
00096   bool outputs_ready_;
00097 
00098   bool outputs_ready() const { return outputs_ready_; }
00099 
00100   // XXX There are three types of inputs.
00101   // 1) explicit deps, which show up as $in on the command line;
00102   // 2) implicit deps, which the target depends on implicitly (e.g. C headers),
00103   //                   and changes in them cause the target to rebuild;
00104   // 3) order-only deps, which are needed before the target builds but which
00105   //                     don't cause the target to rebuild.
00106   // Currently we stuff all of these into inputs_ and keep counts of #2 and #3
00107   // when we need to compute subsets.  This is suboptimal; should think of a
00108   // better representation.  (Could make each pointer into a pair of a pointer
00109   // and a type of input, or if memory matters could use the low bits of the
00110   // pointer...)
00111   int implicit_deps_;
00112   int order_only_deps_;
00113   bool is_implicit(int index) {
00114     return index >= ((int)inputs_.size()) - order_only_deps_ - implicit_deps_ &&
00115         !is_order_only(index);
00116   }
00117   bool is_order_only(int index) {
00118     return index >= ((int)inputs_.size()) - order_only_deps_;
00119   }
00120 
00121   bool is_phony() const;
00122 };
00123 
00124 /// Information about a node in the dependency graph: the file, whether
00125 /// it's dirty, etc.
00126 struct Node {
00127   Node(FileStat* file) : file_(file), dirty_(false), in_edge_(NULL) {}
00128 
00129   bool dirty() const { return dirty_; }
00130   bool ready() const { return !in_edge_ || in_edge_->outputs_ready(); }
00131 
00132   FileStat* file_;
00133   bool dirty_;
00134   Edge* in_edge_;
00135   vector<Edge*> out_edges_;
00136 };
00137 
00138 #endif  // NINJA_GRAPH_H_