|
Ninja
|
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_
1.7.5.1