23 #if defined(__SVR4) && defined(__sun) 24 #include <sys/termios.h> 46 virtual ~DryRunCommandRunner() {}
49 virtual bool CanRunMore()
const;
50 virtual bool StartCommand(
Edge* edge);
51 virtual bool WaitForCommand(Result* result);
54 queue<Edge*> finished_;
57 bool DryRunCommandRunner::CanRunMore()
const {
61 bool DryRunCommandRunner::StartCommand(
Edge* edge) {
66 bool DryRunCommandRunner::WaitForCommand(Result* result) {
67 if (finished_.empty())
71 result->edge = finished_.front();
96 set<Edge*>* dyndep_walk) {
102 referenced =
", needed by '" + dependent->
path() +
"',";
103 *err =
"'" + node->
path() +
"'" + referenced +
" missing " 104 "and no known rule to make it";
114 pair<map<Edge*, Want>::iterator,
bool> want_ins =
116 Want& want = want_ins.first->second;
131 dyndep_walk->insert(edge);
133 if (!want_ins.second)
136 for (vector<Node*>::iterator i = edge->
inputs_.begin();
137 i != edge->
inputs_.end(); ++i) {
138 if (!
AddSubTarget(*i, node, err, dyndep_walk) && !err->empty())
154 EdgeSet::iterator e =
ready_.begin();
171 Edge* edge = want_e->first;
183 map<Edge*, Want>::iterator e =
want_.find(edge);
184 assert(e !=
want_.end());
202 for (vector<Node*>::iterator o = edge->
outputs_.begin();
213 assert(
builder_ &&
"dyndep requires Plan to have a Builder");
220 for (vector<Edge*>::const_iterator oe = node->
out_edges().begin();
222 map<Edge*, Want>::iterator want_e =
want_.find(*oe);
223 if (want_e ==
want_.end())
234 Edge* edge = want_e->first;
251 for (vector<Edge*>::const_iterator oe = node->
out_edges().begin();
254 map<Edge*, Want>::iterator want_e =
want_.find(*oe);
259 if ((*oe)->deps_missing_)
264 vector<Node*>::iterator
265 begin = (*oe)->inputs_.begin(),
266 end = (*oe)->inputs_.end() - (*oe)->order_only_deps_;
267 #if __cplusplus < 201703L 268 #define MEM_FN mem_fun 270 #define MEM_FN mem_fn // mem_fun was removed in C++17. 274 Node* most_recent_input = NULL;
275 for (vector<Node*>::iterator i = begin; i != end; ++i) {
276 if (!most_recent_input || (*i)->
mtime() > most_recent_input->
mtime())
277 most_recent_input = *i;
283 bool outputs_dirty =
false;
285 &outputs_dirty, err)) {
288 if (!outputs_dirty) {
289 for (vector<Node*>::iterator o = (*oe)->outputs_.begin();
290 o != (*oe)->outputs_.end(); ++o) {
297 if (!(*oe)->is_phony())
318 std::vector<DyndepFile::const_iterator> dyndep_roots;
319 for (DyndepFile::const_iterator oe = ddf.begin(); oe != ddf.end(); ++oe) {
320 Edge* edge = oe->first;
326 map<Edge*, Want>::iterator want_e =
want_.find(edge);
330 if (want_e ==
want_.end())
334 dyndep_roots.push_back(oe);
338 std::set<Edge*> dyndep_walk;
339 for (std::vector<DyndepFile::const_iterator>::iterator
340 oei = dyndep_roots.begin(); oei != dyndep_roots.end(); ++oei) {
341 DyndepFile::const_iterator oe = *oei;
342 for (vector<Node*>::const_iterator i = oe->second.implicit_inputs_.begin();
343 i != oe->second.implicit_inputs_.end(); ++i) {
344 if (!
AddSubTarget(*i, oe->first->outputs_[0], err, &dyndep_walk) &&
352 for (vector<Edge*>::const_iterator oe = node->
out_edges().begin();
354 map<Edge*, Want>::iterator want_e =
want_.find(*oe);
355 if (want_e ==
want_.end())
357 dyndep_walk.insert(want_e->first);
361 for (set<Edge*>::iterator wi = dyndep_walk.begin();
362 wi != dyndep_walk.end(); ++wi) {
363 map<Edge*, Want>::iterator want_e =
want_.find(*wi);
364 if (want_e ==
want_.end())
377 set<Node*> dependents;
382 for (set<Node*>::iterator i = dependents.begin();
383 i != dependents.end(); ++i) {
387 std::vector<Node*> validation_nodes;
393 for (std::vector<Node*>::iterator v = validation_nodes.begin();
394 v != validation_nodes.end(); ++v) {
395 if (
Edge* in_edge = (*v)->in_edge()) {
396 if (!in_edge->outputs_ready() &&
410 map<Edge*, Want>::iterator want_e =
want_.find(edge);
411 assert(want_e !=
want_.end());
421 for (vector<Edge*>::const_iterator oe = node->
out_edges().begin();
425 map<Edge*, Want>::iterator want_e =
want_.find(edge);
426 if (want_e ==
want_.end())
431 for (vector<Node*>::iterator o = edge->
outputs_.begin();
433 if (dependents->insert(*o).second)
441 printf(
"pending: %d\n", (
int)
want_.size());
442 for (map<Edge*, Want>::const_iterator e =
want_.begin(); e !=
want_.end(); ++e) {
447 printf(
"ready: %d\n", (
int)
ready_.size());
457 virtual void Abort();
468 edges.push_back(e->second);
477 size_t subproc_number =
506 result->
edge = e->second;
517 : state_(state), config_(config), plan_(this), status_(status),
518 start_time_millis_(start_time_millis), disk_interface_(disk_interface),
519 scan_(state, build_log, deps_log, disk_interface,
520 &config_.depfile_parser_options) {
532 for (vector<Edge*>::iterator e = active_edges.begin();
533 e != active_edges.end(); ++e) {
534 string depfile = (*e)->GetUnescapedDepfile();
535 for (vector<Node*>::iterator o = (*e)->outputs_.begin();
536 o != (*e)->outputs_.end(); ++o) {
548 if (!depfile.empty() || (*o)->mtime() != new_mtime)
551 if (!depfile.empty())
560 *err =
"unknown target: '" + name +
"'";
569 std::vector<Node*> validation_nodes;
582 for (std::vector<Node*>::iterator n = validation_nodes.begin();
583 n != validation_nodes.end(); ++n) {
584 if (
Edge* validation_in_edge = (*n)->in_edge()) {
585 if (!validation_in_edge->outputs_ready() &&
603 int pending_commands = 0;
652 if (pending_commands) {
658 *err =
"interrupted by user";
670 if (failures_allowed)
680 if (failures_allowed == 0) {
682 *err =
"subcommands failed";
684 *err =
"subcommand failed";
686 *err =
"cannot make progress due to previous errors";
688 *err =
"stuck [this is a bug]";
709 for (vector<Node*>::iterator o = edge->
outputs_.begin();
718 if (!rspfile.empty()) {
719 string content = edge->
GetBinding(
"rspfile_content");
743 vector<Node*> deps_nodes;
745 const string deps_prefix = edge->
GetBinding(
"msvc_deps_prefix");
746 if (!deps_type.empty()) {
748 if (!
ExtractDeps(result, deps_type, deps_prefix, &deps_nodes,
751 if (!result->
output.empty())
752 result->
output.append(
"\n");
753 result->
output.append(extract_err);
758 int64_t start_time_millis, end_time_millis;
760 start_time_millis = it->second;
776 bool node_cleaned =
false;
778 for (vector<Node*>::iterator o = edge->
outputs_.begin();
783 if (new_mtime > output_mtime)
784 output_mtime = new_mtime;
785 if ((*o)->mtime() == new_mtime && restat) {
799 for (vector<Node*>::iterator i = edge->
inputs_.begin();
802 if (input_mtime == -1)
804 if (input_mtime > restat_mtime)
805 restat_mtime = input_mtime;
809 if (restat_mtime != 0 && deps_type.empty() && !depfile.empty()) {
811 if (depfile_mtime == -1)
813 if (depfile_mtime > restat_mtime)
814 restat_mtime = depfile_mtime;
821 output_mtime = restat_mtime;
835 end_time_millis, output_mtime)) {
836 *err = string(
"Error writing to build log: ") + strerror(errno);
842 assert(!edge->
outputs_.empty() &&
"should have been rejected by parser");
843 for (std::vector<Node*>::const_iterator o = edge->
outputs_.begin();
846 if (deps_mtime == -1)
849 *err = std::string(
"Error writing to deps log: ") + strerror(errno);
858 const string& deps_type,
859 const string& deps_prefix,
860 vector<Node*>* deps_nodes,
862 if (deps_type ==
"msvc") {
865 if (!parser.
Parse(result->
output, deps_prefix, &output, err))
868 for (set<string>::iterator i = parser.
includes_.begin();
876 }
else if (deps_type ==
"gcc") {
878 if (depfile.empty()) {
879 *err = string(
"edge with deps=gcc but no depfile makes no sense");
898 if (!deps.
Parse(&content, err))
902 deps_nodes->reserve(deps.
ins_.size());
903 for (vector<StringPiece>::iterator i = deps.
ins_.begin();
904 i != deps.
ins_.end(); ++i) {
912 *err = string(
"deleting depfile: ") + strerror(errno) + string(
"\n");
917 Fatal(
"unknown deps type '%s'", deps_type.c_str());
Subprocess * Add(const std::string &command, bool use_console=false)
SubprocessSet runs a ppoll/pselect() loop around a set of Subprocesses.
bool dyndep_pending() const
bool Build(std::string *err)
Run the build.
bool RecomputeDirty(Node *node, std::vector< Node *> *validation_nodes, std::string *err)
Update the |dirty_| state of the given nodes by transitively inspecting their input edges...
std::queue< Subprocess * > finished_
bool RefreshDyndepDependents(DependencyScan *scan, const Node *node, std::string *err)
CommandRunner is an interface that wraps running the build subcommands.
std::auto_ptr< CommandRunner > command_runner_
bool RecordCommand(Edge *edge, int start_time, int end_time, TimeStamp mtime=0)
We do not want to build the edge, but we might want to build one of its dependents.
virtual ~RealCommandRunner()
virtual bool WriteFile(const std::string &path, const std::string &contents)=0
Create a file, with the specified name and contents Returns true on success, false on failure...
Store data loaded from one dyndep file.
Subprocess * NextFinished()
double max_load_average
The maximum load average we must not exceed.
Parser for the dependency information emitted by gcc's -M flags.
void EdgeScheduled(const Edge &edge)
informs this Pool that the given edge is committed to be run.
Node * GetNode(StringPiece path, uint64_t slash_bits)
RunningEdgeMap running_edges_
bool RecomputeOutputsDirty(Edge *edge, Node *most_recent_input, bool *dirty, std::string *err)
Recompute whether any output of the edge is dirty, if so sets |*dirty|.
The result of waiting for a command.
virtual void BuildEdgeStarted(const Edge *edge, int64_t start_time_millis)=0
void set_dirty(bool dirty)
virtual int RemoveFile(const std::string &path)=0
Remove the file named path.
Information about a node in the dependency graph: the file, whether it's dirty, mtime, etc.
virtual bool StartCommand(Edge *edge)
bool DyndepsLoaded(DependencyScan *scan, const Node *node, const DyndepFile &ddf, std::string *err)
Update the build plan to account for modifications made to the graph by information loaded from a dyn...
bool Parse(std::string *content, std::string *err)
Parse an input file.
bool outputs_ready() const
Interface for accessing the disk.
const BuildConfig & config_
int64_t GetTimeMillis()
Get the current time as relative to some epoch.
Plan(Builder *builder=NULL)
bool LoadDyndeps(Node *node, std::string *err) const
Load a dyndep file from the given node's path and update the build graph with the new information...
std::vector< Node * > outputs_
Builder(State *state, const BuildConfig &config, BuildLog *build_log, DepsLog *deps_log, DiskInterface *disk_interface, Status *status, int64_t start_time_millis)
bool StartEdge(Edge *edge, std::string *err)
void Dump() const
Dumps the current state of the plan.
int command_edge_count() const
Number of edges with commands to run.
An edge in the dependency graph; links between Nodes using Rules.
Node * LookupNode(StringPiece path) const
Store a log of every command ran for every build.
virtual bool WaitForCommand(Result *result)
Wait for a command to complete, or return false if interrupted.
virtual void BuildLoadDyndeps()=0
const BuildConfig & config_
const std::string & path() const
DiskInterface * disk_interface_
std::map< Edge *, Want > want_
Keep track of which edges we want to build in this plan.
ExitStatus Finish()
Returns ExitSuccess on successful process exit, ExitInterrupted if the process was interrupted...
void ScheduleWork(std::map< Edge *, Want >::iterator want_e)
Submits a ready edge as a candidate for execution.
bool AddSubTarget(const Node *node, const Node *dependent, std::string *err, std::set< Edge *> *dyndep_walk)
Want
Enumerate possible steps we want for an edge.
As build commands run they can output extra dependency information (e.g.
signed long long int64_t
A 64-bit integer type.
Subprocess wraps a single async subprocess.
bool RecordDeps(Node *node, TimeStamp mtime, const std::vector< Node *> &nodes)
virtual void PlanHasTotalEdges(int total)=0
void Reset()
Reset state. Clears want and ready sets.
bool ExtractDeps(CommandRunner::Result *result, const std::string &deps_type, const std::string &deps_prefix, std::vector< Node *> *deps_nodes, std::string *err)
std::set< std::string > includes_
virtual vector< Edge * > GetActiveEdges()
Node * AddTarget(const std::string &name, std::string *err)
std::vector< StringPiece > ins_
std::string GetUnescapedRspfile() const
Like GetBinding("rspfile"), but without shell escaping.
Abstract interface to object that tracks the status of a build: completion fraction, printing updates.
int wanted_edges_
Total remaining number of wanted edges.
map< const Subprocess *, Edge * > subproc_to_edge_
DepsLog * deps_log() const
BuildLog * build_log() const
void DelayEdge(Edge *edge)
adds the given edge to this Pool to be delayed.
void Cleanup()
Clean up after interrupted commands by deleting output files.
A pool for delayed edges.
bool EdgeMaybeReady(std::map< Edge *, Want >::iterator want_e, std::string *err)
We want to build the edge, but have not yet scheduled it.
bool ShouldDelayEdge() const
true if the Pool might delay this edge
int64_t start_time_millis_
Time the build started.
#define METRIC_RECORD(name)
The primary interface to metrics.
std::vector< Node * > inputs_
std::string GetUnescapedDepfile() const
Like GetBinding("depfile"), but without shell escaping.
Builder wraps the build process: starting commands, updating status.
bool LoadDyndeps(Node *node, std::string *err)
Load the dyndep information provided by the given node.
bool EdgeFinished(Edge *edge, EdgeResult result, std::string *err)
Mark an edge as done building (whether it succeeded or failed).
std::string GetBinding(const std::string &key) const
Returns the shell-escaped value of |key|.
bool AddTarget(const Node *target, std::string *err)
Add a target to our plan (including all its dependencies).
void Fatal(const char *msg,...)
Log a fatal message and exit.
virtual void BuildStarted()=0
virtual Status ReadFile(const std::string &path, std::string *contents, std::string *err)=0
Read and store in given string.
bool NodeFinished(Node *node, std::string *err)
Update plan with knowledge that the given node is up to date.
virtual void BuildEdgeFinished(Edge *edge, int64_t end_time_millis, bool success, const std::string &output)=0
Visual Studio's cl.exe requires some massaging to work with Ninja; for example, it emits include info...
DependencyScan manages the process of scanning the files in a graph and updating the dirty/outputs_re...
bool Parse(const std::string &output, const std::string &deps_prefix, std::string *filtered_output, std::string *err)
Parse the full output of cl, filling filtered_output with the text that should be printed (if any)...
virtual void BuildFinished()=0
bool MakeDirs(const std::string &path)
Create all the parent directories for path; like mkdir -p basename path.
const std::string & GetOutput() const
std::string EvaluateCommand(bool incl_rsp_file=false) const
Expand all variables in a command and return it as a string.
bool AllInputsReady() const
Return true if all inputs' in-edges are ready.
void EdgeFinished(const Edge &edge)
informs this Pool that the given edge is no longer runnable, and should relinquish its resources back...
const std::vector< Edge * > & out_edges() const
void CanonicalizePath(string *path, uint64_t *slash_bits)
void EdgeWanted(const Edge *edge)
Options (e.g. verbosity, parallelism) passed to a build.
Global state (file status) for a single run.
We want to build the edge, have scheduled it, and are waiting for it to complete. ...
bool CleanNode(DependencyScan *scan, Node *node, std::string *err)
Clean the given node during the build.
unsigned long long uint64_t
virtual bool CanRunMore() const
bool more_to_do() const
Returns true if there's more work to be done.
virtual TimeStamp Stat(const std::string &path, std::string *err) const =0
stat() a file, returning the mtime, or 0 if missing and -1 on other errors.
bool GetBindingBool(const std::string &key) const
DepfileParserOptions depfile_parser_options
std::vector< Subprocess * > running_
bool AlreadyUpToDate() const
Returns true if the build targets are already up to date.
int command_edges_
Total number of edges that have commands (not phony).
void UnmarkDependents(const Node *node, std::set< Node *> *dependents)
virtual void Error(const char *msg,...)=0
bool FinishCommand(CommandRunner::Result *result, std::string *err)
Update status ninja logs following a command termination.
void RetrieveReadyEdges(EdgeSet *ready_queue)
Pool will add zero or more edges to the ready_queue.
RealCommandRunner(const BuildConfig &config)