Line | Count | Source |
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 <string> |
22 | | #include <vector> |
23 | | |
24 | | #include "build_result.h" |
25 | | #include "depfile_parser.h" |
26 | | #include "exit_status.h" |
27 | | #include "graph.h" |
28 | | #include "jobserver.h" |
29 | | #include "util.h" // int64_t |
30 | | |
31 | | struct BuildLog; |
32 | | struct Builder; |
33 | | struct DiskInterface; |
34 | | struct Edge; |
35 | | struct Explanations; |
36 | | struct Node; |
37 | | struct State; |
38 | | struct Status; |
39 | | |
40 | | /// Plan stores the state of a build plan: what we intend to build, |
41 | | /// which steps we're ready to execute. |
42 | | struct Plan { |
43 | | Plan(Builder* builder = NULL); |
44 | | |
45 | | /// Add a target to our plan (including all its dependencies). |
46 | | /// Returns false if we don't need to build this target; may |
47 | | /// fill in |err| with an error message if there's a problem. |
48 | | bool AddTarget(const Node* target, std::string* err); |
49 | | |
50 | | // Pop a ready edge off the queue of edges to build. |
51 | | // Returns NULL if there's no work to do. |
52 | | Edge* FindWork(); |
53 | | |
54 | | /// Returns true if there's more work to be done. |
55 | 0 | bool more_to_do() const { return wanted_edges_ > 0 && command_edges_ > 0; } |
56 | | |
57 | | /// Returns true if there's more work ready to be done. |
58 | 0 | bool work_ready() const { return !ready_.empty(); } |
59 | | |
60 | | /// Dumps the current state of the plan. |
61 | | void Dump() const; |
62 | | |
63 | | enum EdgeResult { |
64 | | kEdgeFailed, |
65 | | kEdgeSucceeded |
66 | | }; |
67 | | |
68 | | /// Mark an edge as done building (whether it succeeded or failed). |
69 | | /// If any of the edge's outputs are dyndep bindings of their dependents, |
70 | | /// this loads dynamic dependencies from the nodes' paths. |
71 | | /// Returns 'false' if loading dyndep info fails and 'true' otherwise. |
72 | | bool EdgeFinished(Edge* edge, EdgeResult result, std::string* err); |
73 | | |
74 | | /// Clean the given node during the build. |
75 | | /// Return false on error. |
76 | | bool CleanNode(DependencyScan* scan, Node* node, std::string* err); |
77 | | |
78 | | /// Number of edges with commands to run. |
79 | 0 | int command_edge_count() const { return command_edges_; } |
80 | | |
81 | | /// Reset state. Clears want and ready sets. |
82 | | void Reset(); |
83 | | |
84 | | // After all targets have been added, prepares the ready queue for find work. |
85 | | void PrepareQueue(); |
86 | | |
87 | | /// Update the build plan to account for modifications made to the graph |
88 | | /// by information loaded from a dyndep file. |
89 | | bool DyndepsLoaded(DependencyScan* scan, const Node* node, |
90 | | const DyndepFile& ddf, std::string* err); |
91 | | |
92 | | /// Enumerate possible steps we want for an edge. |
93 | | enum Want |
94 | | { |
95 | | /// We do not want to build the edge, but we might want to build one of |
96 | | /// its dependents. |
97 | | kWantNothing, |
98 | | /// We want to build the edge, but have not yet scheduled it. |
99 | | kWantToStart, |
100 | | /// We want to build the edge, have scheduled it, and are waiting |
101 | | /// for it to complete. |
102 | | kWantToFinish |
103 | | }; |
104 | | |
105 | | private: |
106 | | void ComputeCriticalPath(); |
107 | | bool RefreshDyndepDependents(DependencyScan* scan, const Node* node, std::string* err); |
108 | | void UnmarkDependents(const Node* node, std::set<Node*>* dependents); |
109 | | bool AddSubTarget(const Node* node, const Node* dependent, std::string* err, |
110 | | std::set<Edge*>* dyndep_walk); |
111 | | |
112 | | // Add edges that kWantToStart into the ready queue |
113 | | // Must be called after ComputeCriticalPath and before FindWork |
114 | | void ScheduleInitialEdges(); |
115 | | |
116 | | /// Update plan with knowledge that the given node is up to date. |
117 | | /// If the node is a dyndep binding on any of its dependents, this |
118 | | /// loads dynamic dependencies from the node's path. |
119 | | /// Returns 'false' if loading dyndep info fails and 'true' otherwise. |
120 | | bool NodeFinished(Node* node, std::string* err); |
121 | | |
122 | | void EdgeWanted(const Edge* edge); |
123 | | bool EdgeMaybeReady(std::map<Edge*, Want>::iterator want_e, std::string* err); |
124 | | |
125 | | /// Submits a ready edge as a candidate for execution. |
126 | | /// The edge may be delayed from running, for example if it's a member of a |
127 | | /// currently-full pool. |
128 | | void ScheduleWork(std::map<Edge*, Want>::iterator want_e); |
129 | | |
130 | | /// Keep track of which edges we want to build in this plan. If this map does |
131 | | /// not contain an entry for an edge, we do not want to build the entry or its |
132 | | /// dependents. If it does contain an entry, the enumeration indicates what |
133 | | /// we want for the edge. |
134 | | std::map<Edge*, Want> want_; |
135 | | |
136 | | EdgePriorityQueue ready_; |
137 | | |
138 | | Builder* builder_; |
139 | | /// user provided targets in build order, earlier one have higher priority |
140 | | std::vector<const Node*> targets_; |
141 | | |
142 | | /// Total number of edges that have commands (not phony). |
143 | | int command_edges_; |
144 | | |
145 | | /// Total remaining number of wanted edges. |
146 | | int wanted_edges_; |
147 | | }; |
148 | | |
149 | | struct BuildConfig; |
150 | | |
151 | | /// CommandRunner is an interface that wraps running the build |
152 | | /// subcommands. This allows tests to abstract out running commands. |
153 | | /// RealCommandRunner is an implementation that actually runs commands. |
154 | | struct CommandRunner { |
155 | 0 | virtual ~CommandRunner() {} |
156 | | virtual size_t CanRunMore() const = 0; |
157 | | virtual bool StartCommand(Edge* edge) = 0; |
158 | | |
159 | | /// Wait for a command to complete, or return false if interrupted. |
160 | | virtual BuildResult WaitForCommand() = 0; |
161 | | |
162 | | /// Wait for a command to complete or a jobserver token to become available, or |
163 | | /// return false if interrupted. Default implementation waits for a command to complete. |
164 | | /// Overridden by RealCommandRunner to also wait for jobserver tokens. |
165 | 0 | virtual BuildResult WaitForCommandOrJobserverToken(bool watch_jobserver) { |
166 | 0 | (void)watch_jobserver; |
167 | 0 | return WaitForCommand(); |
168 | 0 | } |
169 | | |
170 | 0 | virtual std::vector<Edge*> GetActiveEdges() { return std::vector<Edge*>(); } |
171 | 0 | virtual void Abort() {} |
172 | | |
173 | | /// Creates the RealCommandRunner. \arg jobserver can be nullptr if there |
174 | | /// is no jobserver pool to use. |
175 | | static CommandRunner* factory(const BuildConfig& config, |
176 | | Jobserver::Client* jobserver); |
177 | | }; |
178 | | |
179 | | /// Options (e.g. verbosity, parallelism) passed to a build. |
180 | | struct BuildConfig { |
181 | | BuildConfig() = default; |
182 | | |
183 | | enum Verbosity { |
184 | | QUIET, // No output -- used when testing. |
185 | | NO_STATUS_UPDATE, // just regular output but suppress status update |
186 | | NORMAL, // regular output and status update |
187 | | VERBOSE |
188 | | }; |
189 | | Verbosity verbosity = NORMAL; |
190 | | bool dry_run = false; |
191 | | int parallelism = 1; |
192 | | bool disable_jobserver_client = false; |
193 | | int failures_allowed = 1; |
194 | | /// The maximum load average we must not exceed. A negative value |
195 | | /// means that we do not have any limit. |
196 | | double max_load_average = -0.0f; |
197 | | /// Progress status format, as set by --status. Overrides $NINJA_STATUS |
198 | | /// when non-null. |
199 | | const char* progress_status_format = nullptr; |
200 | | DepfileParserOptions depfile_parser_options; |
201 | | }; |
202 | | |
203 | | /// Builder wraps the build process: starting commands, updating status. |
204 | | struct Builder { |
205 | | Builder(State* state, const BuildConfig& config, BuildLog* build_log, |
206 | | DepsLog* deps_log, DiskInterface* disk_interface, Status* status, |
207 | | int64_t start_time_millis); |
208 | | ~Builder(); |
209 | | |
210 | | /// Set Jobserver client instance for this builder. |
211 | 0 | void SetJobserverClient(std::unique_ptr<Jobserver::Client> jobserver_client) { |
212 | 0 | jobserver_ = std::move(jobserver_client); |
213 | 0 | } |
214 | | |
215 | | /// Clean up after interrupted commands by deleting output files. |
216 | | void Cleanup(); |
217 | | |
218 | | Node* AddTarget(const std::string& name, std::string* err); |
219 | | |
220 | | /// Add a target to the build, scanning dependencies. |
221 | | /// @return false on error. |
222 | | bool AddTarget(Node* target, std::string* err); |
223 | | |
224 | | /// Returns true if the build targets are already up to date. |
225 | | bool AlreadyUpToDate() const; |
226 | | |
227 | | /// Run the build. Returns ExitStatus or the exit code of the last failed job. |
228 | | /// It is an error to call this function when AlreadyUpToDate() is true. |
229 | | ExitStatus Build(std::string* err); |
230 | | |
231 | | bool StartEdge(Edge* edge, std::string* err); |
232 | | |
233 | | /// Update status ninja logs following a command termination. |
234 | | /// @return false if the build can not proceed further due to a fatal error. |
235 | | bool FinishCommand(BuildResult::CommandCompleted& result, std::string* err); |
236 | | |
237 | | /// Used for tests. |
238 | 0 | void SetBuildLog(BuildLog* log) { |
239 | 0 | scan_.set_build_log(log); |
240 | 0 | } |
241 | | |
242 | | /// Load the dyndep information provided by the given node. |
243 | | bool LoadDyndeps(Node* node, std::string* err); |
244 | | |
245 | | State* state_; |
246 | | const BuildConfig& config_; |
247 | | Plan plan_; |
248 | | std::unique_ptr<Jobserver::Client> jobserver_; |
249 | | std::unique_ptr<CommandRunner> command_runner_; |
250 | | Status* status_; |
251 | | |
252 | | /// Returns ExitStatus or the exit code of the last failed job |
253 | | /// (doesn't need to be an enum value of ExitStatus) |
254 | 0 | ExitStatus GetExitCode() const { return exit_code_; } |
255 | | |
256 | | private: |
257 | | /// Parses the CommandCompleted result to extract dependencies. |
258 | | /// May modify result.output to extract dependency messages out of it |
259 | | /// (such as MSVC /showIncludes). |
260 | | /// @return true if successful, false otherwise. |
261 | | bool ExtractDeps(BuildResult::CommandCompleted& result, |
262 | | const std::string& deps_type, const std::string& deps_prefix, |
263 | | std::vector<Node*>* deps_nodes, std::string* err); |
264 | | |
265 | | /// Map of running edge to time the edge started running. |
266 | | typedef std::map<const Edge*, int> RunningEdgeMap; |
267 | | RunningEdgeMap running_edges_; |
268 | | |
269 | | /// Time the build started. |
270 | | int64_t start_time_millis_; |
271 | | |
272 | | std::string lock_file_path_; |
273 | | DiskInterface* disk_interface_; |
274 | | |
275 | | // Only create an Explanations class if '-d explain' is used. |
276 | | std::unique_ptr<Explanations> explanations_; |
277 | | |
278 | | DependencyScan scan_; |
279 | | |
280 | | /// Keep the global exit code for the build |
281 | | ExitStatus exit_code_ = ExitSuccess; |
282 | | void SetFailureCode(ExitStatus code); |
283 | | |
284 | | // Unimplemented copy ctor and operator= ensure we don't copy the auto_ptr. |
285 | | Builder(const Builder &other); // DO NOT IMPLEMENT |
286 | | void operator=(const Builder &other); // DO NOT IMPLEMENT |
287 | | }; |
288 | | |
289 | | #endif // NINJA_BUILD_H_ |