Coverage Report

Created: 2026-05-24 07:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ninja/src/build.h
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_