• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <string>
23 #include <vector>
24 
25 #include "depfile_parser.h"
26 #include "graph.h"  // XXX needed for DependencyScan; should rearrange.
27 #include "exit_status.h"
28 #include "util.h"  // int64_t
29 
30 struct BuildLog;
31 struct Builder;
32 struct DiskInterface;
33 struct Edge;
34 struct Node;
35 struct State;
36 struct Status;
37 
38 /// Plan stores the state of a build plan: what we intend to build,
39 /// which steps we're ready to execute.
40 struct Plan {
41   Plan(Builder* builder = NULL);
42 
43   /// Add a target to our plan (including all its dependencies).
44   /// Returns false if we don't need to build this target; may
45   /// fill in |err| with an error message if there's a problem.
46   bool AddTarget(const Node* target, std::string* err);
47 
48   // Pop a ready edge off the queue of edges to build.
49   // Returns NULL if there's no work to do.
50   Edge* FindWork();
51 
52   /// Returns true if there's more work to be done.
more_to_doPlan53   bool more_to_do() const { return wanted_edges_ > 0 && command_edges_ > 0; }
54 
55   /// Dumps the current state of the plan.
56   void Dump() const;
57 
58   enum EdgeResult {
59     kEdgeFailed,
60     kEdgeSucceeded
61   };
62 
63   /// Mark an edge as done building (whether it succeeded or failed).
64   /// If any of the edge's outputs are dyndep bindings of their dependents,
65   /// this loads dynamic dependencies from the nodes' paths.
66   /// Returns 'false' if loading dyndep info fails and 'true' otherwise.
67   bool EdgeFinished(Edge* edge, EdgeResult result, std::string* err);
68 
69   /// Clean the given node during the build.
70   /// Return false on error.
71   bool CleanNode(DependencyScan* scan, Node* node, std::string* err);
72 
73   /// Number of edges with commands to run.
command_edge_countPlan74   int command_edge_count() const { return command_edges_; }
75 
76   /// Reset state.  Clears want and ready sets.
77   void Reset();
78 
79   /// Update the build plan to account for modifications made to the graph
80   /// by information loaded from a dyndep file.
81   bool DyndepsLoaded(DependencyScan* scan, const Node* node,
82                      const DyndepFile& ddf, std::string* err);
83 private:
84   bool RefreshDyndepDependents(DependencyScan* scan, const Node* node, std::string* err);
85   void UnmarkDependents(const Node* node, std::set<Node*>* dependents);
86   bool AddSubTarget(const Node* node, const Node* dependent, std::string* err,
87                     std::set<Edge*>* dyndep_walk);
88 
89   /// Update plan with knowledge that the given node is up to date.
90   /// If the node is a dyndep binding on any of its dependents, this
91   /// loads dynamic dependencies from the node's path.
92   /// Returns 'false' if loading dyndep info fails and 'true' otherwise.
93   bool NodeFinished(Node* node, std::string* err);
94 
95   /// Enumerate possible steps we want for an edge.
96   enum Want
97   {
98     /// We do not want to build the edge, but we might want to build one of
99     /// its dependents.
100     kWantNothing,
101     /// We want to build the edge, but have not yet scheduled it.
102     kWantToStart,
103     /// We want to build the edge, have scheduled it, and are waiting
104     /// for it to complete.
105     kWantToFinish
106   };
107 
108   void EdgeWanted(const Edge* edge);
109   bool EdgeMaybeReady(std::map<Edge*, Want>::iterator want_e, std::string* err);
110 
111   /// Submits a ready edge as a candidate for execution.
112   /// The edge may be delayed from running, for example if it's a member of a
113   /// currently-full pool.
114   void ScheduleWork(std::map<Edge*, Want>::iterator want_e);
115 
116   /// Keep track of which edges we want to build in this plan.  If this map does
117   /// not contain an entry for an edge, we do not want to build the entry or its
118   /// dependents.  If it does contain an entry, the enumeration indicates what
119   /// we want for the edge.
120   std::map<Edge*, Want> want_;
121 
122   EdgeSet ready_;
123 
124   Builder* builder_;
125 
126   /// Total number of edges that have commands (not phony).
127   int command_edges_;
128 
129   /// Total remaining number of wanted edges.
130   int wanted_edges_;
131 };
132 
133 /// CommandRunner is an interface that wraps running the build
134 /// subcommands.  This allows tests to abstract out running commands.
135 /// RealCommandRunner is an implementation that actually runs commands.
136 struct CommandRunner {
~CommandRunnerCommandRunner137   virtual ~CommandRunner() {}
138   virtual bool CanRunMore() const = 0;
139   virtual bool StartCommand(Edge* edge) = 0;
140 
141   /// The result of waiting for a command.
142   struct Result {
ResultCommandRunner::Result143     Result() : edge(NULL) {}
144     Edge* edge;
145     ExitStatus status;
146     std::string output;
successCommandRunner::Result147     bool success() const { return status == ExitSuccess; }
148   };
149   /// Wait for a command to complete, or return false if interrupted.
150   virtual bool WaitForCommand(Result* result) = 0;
151 
GetActiveEdgesCommandRunner152   virtual std::vector<Edge*> GetActiveEdges() { return std::vector<Edge*>(); }
AbortCommandRunner153   virtual void Abort() {}
154 };
155 
156 /// Options (e.g. verbosity, parallelism) passed to a build.
157 struct BuildConfig {
BuildConfigBuildConfig158   BuildConfig() : verbosity(NORMAL), dry_run(false), parallelism(1),
159                   failures_allowed(1), max_load_average(-0.0f) {}
160 
161   enum Verbosity {
162     QUIET,  // No output -- used when testing.
163     NO_STATUS_UPDATE,  // just regular output but suppress status update
164     NORMAL,  // regular output and status update
165     VERBOSE
166   };
167   Verbosity verbosity;
168   bool dry_run;
169   int parallelism;
170   int failures_allowed;
171   /// The maximum load average we must not exceed. A negative value
172   /// means that we do not have any limit.
173   double max_load_average;
174   DepfileParserOptions depfile_parser_options;
175 };
176 
177 /// Builder wraps the build process: starting commands, updating status.
178 struct Builder {
179   Builder(State* state, const BuildConfig& config,
180           BuildLog* build_log, DepsLog* deps_log,
181           DiskInterface* disk_interface, Status* status,
182           int64_t start_time_millis);
183   ~Builder();
184 
185   /// Clean up after interrupted commands by deleting output files.
186   void Cleanup();
187 
188   Node* AddTarget(const std::string& name, std::string* err);
189 
190   /// Add a target to the build, scanning dependencies.
191   /// @return false on error.
192   bool AddTarget(Node* target, std::string* err);
193 
194   /// Returns true if the build targets are already up to date.
195   bool AlreadyUpToDate() const;
196 
197   /// Run the build.  Returns false on error.
198   /// It is an error to call this function when AlreadyUpToDate() is true.
199   bool Build(std::string* err);
200 
201   bool StartEdge(Edge* edge, std::string* err);
202 
203   /// Update status ninja logs following a command termination.
204   /// @return false if the build can not proceed further due to a fatal error.
205   bool FinishCommand(CommandRunner::Result* result, std::string* err);
206 
207   /// Used for tests.
SetBuildLogBuilder208   void SetBuildLog(BuildLog* log) {
209     scan_.set_build_log(log);
210   }
211 
212   /// Load the dyndep information provided by the given node.
213   bool LoadDyndeps(Node* node, std::string* err);
214 
215   State* state_;
216   const BuildConfig& config_;
217   Plan plan_;
218 #if __cplusplus < 201703L
219   std::auto_ptr<CommandRunner> command_runner_;
220 #else
221   std::unique_ptr<CommandRunner> command_runner_;  // auto_ptr was removed in C++17.
222 #endif
223   Status* status_;
224 
225  private:
226   bool ExtractDeps(CommandRunner::Result* result, const std::string& deps_type,
227                    const std::string& deps_prefix,
228                    std::vector<Node*>* deps_nodes, std::string* err);
229 
230   /// Map of running edge to time the edge started running.
231   typedef std::map<const Edge*, int> RunningEdgeMap;
232   RunningEdgeMap running_edges_;
233 
234   /// Time the build started.
235   int64_t start_time_millis_;
236 
237   DiskInterface* disk_interface_;
238   DependencyScan scan_;
239 
240   // Unimplemented copy ctor and operator= ensure we don't copy the auto_ptr.
241   Builder(const Builder &other);        // DO NOT IMPLEMENT
242   void operator=(const Builder &other); // DO NOT IMPLEMENT
243 };
244 
245 #endif  // NINJA_BUILD_H_
246