Ninja
build.h
Go to the documentation of this file.
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 "graph.h" // XXX needed for DependencyScan; should rearrange.
27 #include "exit_status.h"
28 #include "line_printer.h"
29 #include "metrics.h"
30 #include "util.h" // int64_t
31 
32 struct BuildLog;
33 struct BuildStatus;
34 struct DiskInterface;
35 struct Edge;
36 struct Node;
37 struct State;
38 
39 /// Plan stores the state of a build plan: what we intend to build,
40 /// which steps we're ready to execute.
41 struct Plan {
42  Plan();
43 
44  /// Add a target to our plan (including all its dependencies).
45  /// Returns false if we don't need to build this target; may
46  /// fill in |err| with an error message if there's a problem.
47  bool AddTarget(Node* node, string* err);
48 
49  // Pop a ready edge off the queue of edges to build.
50  // Returns NULL if there's no work to do.
51  Edge* FindWork();
52 
53  /// Returns true if there's more work to be done.
54  bool more_to_do() const { return wanted_edges_; }
55 
56  /// Dumps the current state of the plan.
57  void Dump();
58 
59  /// Mark an edge as done building. Used internally and by
60  /// tests.
61  void EdgeFinished(Edge* edge);
62 
63  /// Clean the given node during the build.
64  void CleanNode(DependencyScan* scan, Node* node);
65 
66  /// Number of edges with commands to run.
67  int command_edge_count() const { return command_edges_; }
68 
69 private:
70  bool AddSubTarget(Node* node, vector<Node*>* stack, string* err);
71  bool CheckDependencyCycle(Node* node, vector<Node*>* stack, string* err);
72  void NodeFinished(Node* node);
73 
74  /// Submits a ready edge as a candidate for execution.
75  /// The edge may be delayed from running, for example if it's a member of a
76  /// currently-full pool.
77  void ScheduleWork(Edge* edge);
78 
79  /// Allows jobs blocking on |edge| to potentially resume.
80  /// For example, if |edge| is a member of a pool, calling this may schedule
81  /// previously pending jobs in that pool.
82  void ResumeDelayedJobs(Edge* edge);
83 
84  /// Keep track of which edges we want to build in this plan. If this map does
85  /// not contain an entry for an edge, we do not want to build the entry or its
86  /// dependents. If an entry maps to false, we do not want to build it, but we
87  /// might want to build one of its dependents. If the entry maps to true, we
88  /// want to build it.
89  map<Edge*, bool> want_;
90 
91  set<Edge*> ready_;
92 
93  /// Total number of edges that have commands (not phony).
95 
96  /// Total remaining number of wanted edges.
98 };
99 
100 /// CommandRunner is an interface that wraps running the build
101 /// subcommands. This allows tests to abstract out running commands.
102 /// RealCommandRunner is an implementation that actually runs commands.
104  virtual ~CommandRunner() {}
105  virtual bool CanRunMore() = 0;
106  virtual bool StartCommand(Edge* edge) = 0;
107 
108  /// The result of waiting for a command.
109  struct Result {
110  Result() : edge(NULL) {}
113  string output;
114  bool success() const { return status == ExitSuccess; }
115  };
116  /// Wait for a command to complete, or return false if interrupted.
117  virtual bool WaitForCommand(Result* result) = 0;
118 
119  virtual vector<Edge*> GetActiveEdges() { return vector<Edge*>(); }
120  virtual void Abort() {}
121 };
122 
123 /// Options (e.g. verbosity, parallelism) passed to a build.
124 struct BuildConfig {
126  failures_allowed(1), max_load_average(-0.0f) {}
127 
128  enum Verbosity {
130  QUIET, // No output -- used when testing.
132  };
134  bool dry_run;
137  /// The maximum load average we must not exceed. A negative value
138  /// means that we do not have any limit.
140 };
141 
142 /// Builder wraps the build process: starting commands, updating status.
143 struct Builder {
144  Builder(State* state, const BuildConfig& config,
145  BuildLog* build_log, DepsLog* deps_log,
146  DiskInterface* disk_interface);
147  ~Builder();
148 
149  /// Clean up after interrupted commands by deleting output files.
150  void Cleanup();
151 
152  Node* AddTarget(const string& name, string* err);
153 
154  /// Add a target to the build, scanning dependencies.
155  /// @return false on error.
156  bool AddTarget(Node* target, string* err);
157 
158  /// Returns true if the build targets are already up to date.
159  bool AlreadyUpToDate() const;
160 
161  /// Run the build. Returns false on error.
162  /// It is an error to call this function when AlreadyUpToDate() is true.
163  bool Build(string* err);
164 
165  bool StartEdge(Edge* edge, string* err);
166  void FinishCommand(CommandRunner::Result* result);
167 
168  /// Used for tests.
169  void SetBuildLog(BuildLog* log) {
170  scan_.set_build_log(log);
171  }
172 
176  auto_ptr<CommandRunner> command_runner_;
178 
179  private:
180  bool ExtractDeps(CommandRunner::Result* result, const string& deps_type,
181  vector<Node*>* deps_nodes, string* err);
182 
185 
186  // Unimplemented copy ctor and operator= ensure we don't copy the auto_ptr.
187  Builder(const Builder &other); // DO NOT IMPLEMENT
188  void operator=(const Builder &other); // DO NOT IMPLEMENT
189 };
190 
191 /// Tracks the status of a build: completion fraction, printing updates.
192 struct BuildStatus {
193  explicit BuildStatus(const BuildConfig& config);
194  void PlanHasTotalEdges(int total);
195  void BuildEdgeStarted(Edge* edge);
196  void BuildEdgeFinished(Edge* edge, bool success, const string& output,
197  int* start_time, int* end_time);
198  void BuildFinished();
199 
200  /// Format the progress status string by replacing the placeholders.
201  /// See the user manual for more information about the available
202  /// placeholders.
203  /// @param progress_status_format The format of the progress status.
204  string FormatProgressStatus(const char* progress_status_format) const;
205 
206  private:
207  void PrintStatus(Edge* edge);
208 
210 
211  /// Time the build started.
213 
215 
216  /// Map of running edge to time the edge started running.
217  typedef map<Edge*, int> RunningEdgeMap;
219 
220  /// Prints progress output.
222 
223  /// The custom progress status format to use.
225 
226  template<size_t S>
227  void snprinfRate(double rate, char(&buf)[S], const char* format) const {
228  if (rate == -1) snprintf(buf, S, "?");
229  else snprintf(buf, S, format, rate);
230  }
231 
232  struct RateInfo {
233  RateInfo() : rate_(-1) {}
234 
235  void Restart() { stopwatch_.Restart(); }
236  double Elapsed() const { return stopwatch_.Elapsed(); }
237  double rate() { return rate_; }
238 
239  void UpdateRate(int edges) {
240  if (edges && stopwatch_.Elapsed())
241  rate_ = edges / stopwatch_.Elapsed();
242  }
243 
244  private:
245  double rate_;
247  };
248 
250  SlidingRateInfo(int n) : rate_(-1), N(n), last_update_(-1) {}
251 
252  void Restart() { stopwatch_.Restart(); }
253  double rate() { return rate_; }
254 
255  void UpdateRate(int update_hint) {
256  if (update_hint == last_update_)
257  return;
258  last_update_ = update_hint;
259 
260  if (times_.size() == N)
261  times_.pop();
262  times_.push(stopwatch_.Elapsed());
263  if (times_.back() != times_.front())
264  rate_ = times_.size() / (times_.back() - times_.front());
265  }
266 
267  private:
268  double rate_;
270  const size_t N;
271  queue<double> times_;
273  };
274 
277 };
278 
279 #endif // NINJA_BUILD_H_