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_BUILD_H_ 16 #define NINJA_BUILD_H_ 17 18 #include <cstdio> 19 #include <map> 20 #include <memory> 21 #include <queue> 22 #include <set> 23 #include <string> 24 #include <vector> 25 26 #include "depfile_parser.h" 27 #include "graph.h" // XXX needed for DependencyScan; should rearrange. 28 #include "exit_status.h" 29 #include "line_printer.h" 30 #include "metrics.h" 31 #include "util.h" // int64_t 32 33 struct BuildLog; 34 struct BuildStatus; 35 struct Builder; 36 struct DiskInterface; 37 struct Edge; 38 struct Node; 39 struct State; 40 41 /// Plan stores the state of a build plan: what we intend to build, 42 /// which steps we're ready to execute. 43 struct Plan { 44 Plan(Builder* builder = NULL); 45 46 /// Add a target to our plan (including all its dependencies). 47 /// Returns false if we don't need to build this target; may 48 /// fill in |err| with an error message if there's a problem. 49 bool AddTarget(const Node* node, string* err); 50 51 // Pop a ready edge off the queue of edges to build. 52 // Returns NULL if there's no work to do. 53 Edge* FindWork(); 54 55 /// Returns true if there's more work to be done. more_to_doPlan56 bool more_to_do() const { return wanted_edges_ > 0 && command_edges_ > 0; } 57 58 /// Dumps the current state of the plan. 59 void Dump() const; 60 61 enum EdgeResult { 62 kEdgeFailed, 63 kEdgeSucceeded 64 }; 65 66 /// Mark an edge as done building (whether it succeeded or failed). 67 /// If any of the edge's outputs are dyndep bindings of their dependents, 68 /// this loads dynamic dependencies from the nodes' paths. 69 /// Returns 'false' if loading dyndep info fails and 'true' otherwise. 70 bool EdgeFinished(Edge* edge, EdgeResult result, string* err); 71 72 /// Clean the given node during the build. 73 /// Return false on error. 74 bool CleanNode(DependencyScan* scan, Node* node, string* err); 75 76 /// Number of edges with commands to run. command_edge_countPlan77 int command_edge_count() const { return command_edges_; } 78 79 /// Reset state. Clears want and ready sets. 80 void Reset(); 81 82 /// Update the build plan to account for modifications made to the graph 83 /// by information loaded from a dyndep file. 84 bool DyndepsLoaded(DependencyScan* scan, const Node* node, 85 const DyndepFile& ddf, string* err); 86 private: 87 bool RefreshDyndepDependents(DependencyScan* scan, const Node* node, string* err); 88 void UnmarkDependents(const Node* node, set<Node*>* dependents); 89 bool AddSubTarget(const Node* node, const Node* dependent, string* err, 90 set<Edge*>* dyndep_walk); 91 92 /// Update plan with knowledge that the given node is up to date. 93 /// If the node is a dyndep binding on any of its dependents, this 94 /// loads dynamic dependencies from the node's path. 95 /// Returns 'false' if loading dyndep info fails and 'true' otherwise. 96 bool NodeFinished(Node* node, string* err); 97 98 /// Enumerate possible steps we want for an edge. 99 enum Want 100 { 101 /// We do not want to build the edge, but we might want to build one of 102 /// its dependents. 103 kWantNothing, 104 /// We want to build the edge, but have not yet scheduled it. 105 kWantToStart, 106 /// We want to build the edge, have scheduled it, and are waiting 107 /// for it to complete. 108 kWantToFinish 109 }; 110 111 void EdgeWanted(const Edge* edge); 112 bool EdgeMaybeReady(map<Edge*, Want>::iterator want_e, string* err); 113 114 /// Submits a ready edge as a candidate for execution. 115 /// The edge may be delayed from running, for example if it's a member of a 116 /// currently-full pool. 117 void ScheduleWork(map<Edge*, Want>::iterator want_e); 118 119 /// Keep track of which edges we want to build in this plan. If this map does 120 /// not contain an entry for an edge, we do not want to build the entry or its 121 /// dependents. If it does contain an entry, the enumeration indicates what 122 /// we want for the edge. 123 map<Edge*, Want> want_; 124 125 set<Edge*> ready_; 126 127 Builder* builder_; 128 129 /// Total number of edges that have commands (not phony). 130 int command_edges_; 131 132 /// Total remaining number of wanted edges. 133 int wanted_edges_; 134 }; 135 136 /// CommandRunner is an interface that wraps running the build 137 /// subcommands. This allows tests to abstract out running commands. 138 /// RealCommandRunner is an implementation that actually runs commands. 139 struct CommandRunner { ~CommandRunnerCommandRunner140 virtual ~CommandRunner() {} 141 virtual bool CanRunMore() const = 0; 142 virtual bool StartCommand(Edge* edge) = 0; 143 144 /// The result of waiting for a command. 145 struct Result { ResultCommandRunner::Result146 Result() : edge(NULL) {} 147 Edge* edge; 148 ExitStatus status; 149 string output; successCommandRunner::Result150 bool success() const { return status == ExitSuccess; } 151 }; 152 /// Wait for a command to complete, or return false if interrupted. 153 virtual bool WaitForCommand(Result* result) = 0; 154 GetActiveEdgesCommandRunner155 virtual vector<Edge*> GetActiveEdges() { return vector<Edge*>(); } AbortCommandRunner156 virtual void Abort() {} 157 }; 158 159 /// Options (e.g. verbosity, parallelism) passed to a build. 160 struct BuildConfig { BuildConfigBuildConfig161 BuildConfig() : verbosity(NORMAL), dry_run(false), parallelism(1), 162 failures_allowed(1), max_load_average(-0.0f) {} 163 164 enum Verbosity { 165 NORMAL, 166 QUIET, // No output -- used when testing. 167 VERBOSE 168 }; 169 Verbosity verbosity; 170 bool dry_run; 171 int parallelism; 172 int failures_allowed; 173 /// The maximum load average we must not exceed. A negative value 174 /// means that we do not have any limit. 175 double max_load_average; 176 DepfileParserOptions depfile_parser_options; 177 }; 178 179 /// Builder wraps the build process: starting commands, updating status. 180 struct Builder { 181 Builder(State* state, const BuildConfig& config, 182 BuildLog* build_log, DepsLog* deps_log, 183 DiskInterface* disk_interface); 184 ~Builder(); 185 186 /// Clean up after interrupted commands by deleting output files. 187 void Cleanup(); 188 189 Node* AddTarget(const string& name, string* err); 190 191 /// Add a target to the build, scanning dependencies. 192 /// @return false on error. 193 bool AddTarget(Node* target, string* err); 194 195 /// Returns true if the build targets are already up to date. 196 bool AlreadyUpToDate() const; 197 198 /// Run the build. Returns false on error. 199 /// It is an error to call this function when AlreadyUpToDate() is true. 200 bool Build(string* err); 201 202 bool StartEdge(Edge* edge, string* err); 203 204 /// Update status ninja logs following a command termination. 205 /// @return false if the build can not proceed further due to a fatal error. 206 bool FinishCommand(CommandRunner::Result* result, string* err); 207 208 /// Used for tests. SetBuildLogBuilder209 void SetBuildLog(BuildLog* log) { 210 scan_.set_build_log(log); 211 } 212 213 /// Load the dyndep information provided by the given node. 214 bool LoadDyndeps(Node* node, string* err); 215 216 State* state_; 217 const BuildConfig& config_; 218 Plan plan_; 219 #if __cplusplus < 201703L 220 auto_ptr<CommandRunner> command_runner_; 221 #else 222 unique_ptr<CommandRunner> command_runner_; // auto_ptr was removed in C++17. 223 #endif 224 BuildStatus* status_; 225 226 private: 227 bool ExtractDeps(CommandRunner::Result* result, const string& deps_type, 228 const string& deps_prefix, vector<Node*>* deps_nodes, 229 string* err); 230 231 DiskInterface* disk_interface_; 232 DependencyScan scan_; 233 234 // Unimplemented copy ctor and operator= ensure we don't copy the auto_ptr. 235 Builder(const Builder &other); // DO NOT IMPLEMENT 236 void operator=(const Builder &other); // DO NOT IMPLEMENT 237 }; 238 239 /// Tracks the status of a build: completion fraction, printing updates. 240 struct BuildStatus { 241 explicit BuildStatus(const BuildConfig& config); 242 void PlanHasTotalEdges(int total); 243 void BuildEdgeStarted(const Edge* edge); 244 void BuildEdgeFinished(Edge* edge, bool success, const string& output, 245 int* start_time, int* end_time); 246 void BuildLoadDyndeps(); 247 void BuildStarted(); 248 void BuildFinished(); 249 250 enum EdgeStatus { 251 kEdgeStarted, 252 kEdgeFinished, 253 }; 254 255 /// Format the progress status string by replacing the placeholders. 256 /// See the user manual for more information about the available 257 /// placeholders. 258 /// @param progress_status_format The format of the progress status. 259 /// @param status The status of the edge. 260 string FormatProgressStatus(const char* progress_status_format, 261 EdgeStatus status) const; 262 263 private: 264 void PrintStatus(const Edge* edge, EdgeStatus status); 265 266 const BuildConfig& config_; 267 268 /// Time the build started. 269 int64_t start_time_millis_; 270 271 int started_edges_, finished_edges_, total_edges_; 272 273 /// Map of running edge to time the edge started running. 274 typedef map<const Edge*, int> RunningEdgeMap; 275 RunningEdgeMap running_edges_; 276 277 /// Prints progress output. 278 LinePrinter printer_; 279 280 /// The custom progress status format to use. 281 const char* progress_status_format_; 282 283 template<size_t S> SnprintfRateBuildStatus284 void SnprintfRate(double rate, char(&buf)[S], const char* format) const { 285 if (rate == -1) 286 snprintf(buf, S, "?"); 287 else 288 snprintf(buf, S, format, rate); 289 } 290 291 struct RateInfo { RateInfoBuildStatus::RateInfo292 RateInfo() : rate_(-1) {} 293 RestartBuildStatus::RateInfo294 void Restart() { stopwatch_.Restart(); } ElapsedBuildStatus::RateInfo295 double Elapsed() const { return stopwatch_.Elapsed(); } rateBuildStatus::RateInfo296 double rate() { return rate_; } 297 UpdateRateBuildStatus::RateInfo298 void UpdateRate(int edges) { 299 if (edges && stopwatch_.Elapsed()) 300 rate_ = edges / stopwatch_.Elapsed(); 301 } 302 303 private: 304 double rate_; 305 Stopwatch stopwatch_; 306 }; 307 308 struct SlidingRateInfo { SlidingRateInfoBuildStatus::SlidingRateInfo309 SlidingRateInfo(int n) : rate_(-1), N(n), last_update_(-1) {} 310 RestartBuildStatus::SlidingRateInfo311 void Restart() { stopwatch_.Restart(); } rateBuildStatus::SlidingRateInfo312 double rate() { return rate_; } 313 UpdateRateBuildStatus::SlidingRateInfo314 void UpdateRate(int update_hint) { 315 if (update_hint == last_update_) 316 return; 317 last_update_ = update_hint; 318 319 if (times_.size() == N) 320 times_.pop(); 321 times_.push(stopwatch_.Elapsed()); 322 if (times_.back() != times_.front()) 323 rate_ = times_.size() / (times_.back() - times_.front()); 324 } 325 326 private: 327 double rate_; 328 Stopwatch stopwatch_; 329 const size_t N; 330 queue<double> times_; 331 int last_update_; 332 }; 333 334 mutable RateInfo overall_rate_; 335 mutable SlidingRateInfo current_rate_; 336 }; 337 338 #endif // NINJA_BUILD_H_ 339