23 #if defined(__SVR4) && defined(__sun)
24 #include <sys/termios.h>
41 virtual ~DryRunCommandRunner() {}
44 virtual bool CanRunMore();
45 virtual bool StartCommand(
Edge* edge);
46 virtual bool WaitForCommand(Result* result);
49 queue<Edge*> finished_;
52 bool DryRunCommandRunner::CanRunMore() {
56 bool DryRunCommandRunner::StartCommand(
Edge* edge) {
61 bool DryRunCommandRunner::WaitForCommand(Result* result) {
62 if (finished_.empty())
66 result->edge = finished_.front();
76 started_edges_(0), finished_edges_(0), total_edges_(0),
77 progress_status_format_(NULL),
78 overall_rate_(), current_rate_(config.parallelism) {
103 const string& output,
110 *start_time = i->second;
124 if (!output.empty()) {
141 final_output = output;
151 const char* progress_status_format)
const {
155 for (
const char* s = progress_status_format; *s !=
'\0'; ++s) {
210 snprintf(buf,
sizeof(buf),
"%3i%%", percent);
216 snprintf(buf,
sizeof(buf),
"%.3f", elapsed);
222 Fatal(
"unknown placeholder '%%%c' in $NINJA_STATUS", *s);
239 string to_print = edge->
GetBinding(
"description");
240 if (to_print.empty() || force_full_command)
266 referenced =
", needed by '" + stack->back()->path() +
"',";
267 *err =
"'" + node->
path() +
"'" + referenced +
" missing "
268 "and no known rule to make it";
281 pair<map<Edge*, bool>::iterator,
bool> want_ins =
282 want_.insert(make_pair(edge,
false));
283 bool& want = want_ins.first->second;
287 if (node->
dirty() && !want) {
296 if (!want_ins.second)
299 stack->push_back(node);
300 for (vector<Node*>::iterator i = edge->
inputs_.begin();
301 i != edge->
inputs_.end(); ++i) {
305 assert(stack->back() == node);
312 vector<Node*>::reverse_iterator ri =
313 find(stack->rbegin(), stack->rend(), node);
314 if (ri == stack->rend())
319 stack->push_back(node);
321 vector<Node*>::iterator start = find(stack->begin(), stack->end(), node);
322 *err =
"dependency cycle: ";
323 for (vector<Node*>::iterator i = start; i != stack->end(); ++i) {
326 err->append((*i)->path());
334 set<Edge*>::iterator i =
ready_.begin();
363 map<Edge*, bool>::iterator i =
want_.find(edge);
364 assert(i !=
want_.end());
374 for (vector<Node*>::iterator i = edge->
outputs_.begin();
382 for (vector<Edge*>::const_iterator i = node->
out_edges().begin();
384 map<Edge*, bool>::iterator want_i =
want_.find(*i);
385 if (want_i ==
want_.end())
389 if ((*i)->AllInputsReady()) {
390 if (want_i->second) {
404 for (vector<Edge*>::const_iterator ei = node->
out_edges().begin();
407 map<Edge*, bool>::iterator want_i =
want_.find(*ei);
408 if (want_i ==
want_.end() || !want_i->second)
413 vector<Node*>::iterator
414 begin = (*ei)->inputs_.begin(),
415 end = (*ei)->inputs_.end() - (*ei)->order_only_deps_;
416 if (find_if(begin, end, mem_fun(&
Node::dirty)) == end) {
418 Node* most_recent_input = NULL;
419 for (vector<Node*>::iterator ni = begin; ni != end; ++ni) {
420 if (!most_recent_input || (*ni)->
mtime() > most_recent_input->
mtime())
421 most_recent_input = *ni;
423 string command = (*ei)->EvaluateCommand(
true);
426 bool all_outputs_clean =
true;
427 for (vector<Node*>::iterator ni = (*ei)->outputs_.begin();
428 ni != (*ei)->outputs_.end(); ++ni) {
435 all_outputs_clean =
false;
442 if (all_outputs_clean) {
443 want_i->second =
false;
445 if (!(*ei)->is_phony())
453 printf(
"pending: %d\n", (
int)
want_.size());
454 for (map<Edge*, bool>::iterator i =
want_.begin(); i !=
want_.end(); ++i) {
459 printf(
"ready: %d\n", (
int)
ready_.size());
469 virtual void Abort();
480 edges.push_back(i->second);
516 result->
edge = i->second;
526 : state_(state), config_(config), disk_interface_(disk_interface),
527 scan_(state, build_log, deps_log, disk_interface) {
540 for (vector<Edge*>::iterator i = active_edges.begin();
541 i != active_edges.end(); ++i) {
542 string depfile = (*i)->GetBinding(
"depfile");
543 for (vector<Node*>::iterator ni = (*i)->outputs_.begin();
544 ni != (*i)->outputs_.end(); ++ni) {
552 if (!depfile.empty() ||
557 if (!depfile.empty())
566 *err =
"unknown target: '" + name +
"'";
579 if (in_edge->outputs_ready())
597 int pending_commands = 0;
634 if (pending_commands) {
639 *err =
"interrupted by user";
647 if (failures_allowed)
657 if (failures_allowed == 0) {
659 *err =
"subcommands failed";
661 *err =
"subcommand failed";
663 *err =
"cannot make progress due to previous errors";
665 *err =
"stuck [this is a bug]";
683 for (vector<Node*>::iterator i = edge->
outputs_.begin();
692 if (!rspfile.empty()) {
693 string content = edge->
GetBinding(
"rspfile_content");
717 vector<Node*> deps_nodes;
719 if (!deps_type.empty()) {
721 if (!
ExtractDeps(result, deps_type, &deps_nodes, &extract_err) &&
723 if (!result->
output.empty())
724 result->
output.append(
"\n");
725 result->
output.append(extract_err);
730 int start_time, end_time;
732 &start_time, &end_time);
741 bool node_cleaned =
false;
743 for (vector<Node*>::iterator i = edge->
outputs_.begin();
746 if ((*i)->mtime() == new_mtime) {
758 for (vector<Node*>::iterator i = edge->
inputs_.begin();
761 if (input_mtime > restat_mtime)
762 restat_mtime = input_mtime;
766 if (restat_mtime != 0 && !depfile.empty()) {
768 if (depfile_mtime > restat_mtime)
769 restat_mtime = depfile_mtime;
782 if (!rspfile.empty())
791 assert(edge->
outputs_.size() == 1 &&
"should have been rejected by parser");
800 const string& deps_type,
801 vector<Node*>* deps_nodes,
804 if (deps_type ==
"msvc") {
807 for (set<string>::iterator i = parser.
includes_.begin();
813 if (deps_type ==
"gcc") {
815 if (depfile.empty()) {
816 *err = string(
"edge with deps=gcc but no depfile makes no sense");
827 if (!deps.
Parse(&content, err))
831 deps_nodes->reserve(deps.
ins_.size());
832 for (vector<StringPiece>::iterator i = deps.
ins_.begin();
833 i != deps.
ins_.end(); ++i) {
840 *err = string(
"deleting depfile: ") + strerror(errno) + string(
"\n");
844 Fatal(
"unknown deps type '%s'", deps_type.c_str());
SubprocessSet runs a ppoll/pselect() loop around a set of Subprocesses.
virtual string ReadFile(const string &path, string *err)=0
Read a file to a string. Fill in |err| on error.
CommandRunner is an interface that wraps running the build subcommands.
map< Subprocess *, Edge * > subproc_to_edge_
void BuildEdgeFinished(Edge *edge, bool success, const string &output, int *start_time, int *end_time)
BuildStatus(const BuildConfig &config)
virtual ~RealCommandRunner()
Subprocess * NextFinished()
double max_load_average
The maximum load average we must not exceed.
bool more_to_do() const
Returns true if there's more work to be done.
Parser for the dependency information emitted by gcc's -M flags.
SlidingRateInfo current_rate_
void EdgeScheduled(const Edge &edge)
informs this Pool that the given edge is committed to be run.
Node * GetNode(StringPiece path)
void UpdateRate(int edges)
bool RecomputeOutputDirty(Edge *edge, Node *most_recent_input, TimeStamp deps_mtime, const string &command, Node *output)
Recompute whether a given single output should be marked dirty.
bool RecomputeDirty(Edge *edge, string *err)
Examine inputs, outputs, and command lines to judge whether an edge needs to be re-run, and update outputs_ready_ and each outputs' |dirty_| state accordingly.
bool AddSubTarget(Node *node, vector< Node * > *stack, string *err)
The result of waiting for a command.
void set_dirty(bool dirty)
bool AddTarget(Node *node, string *err)
Add a target to our plan (including all its dependencies).
bool MakeDirs(const string &path)
Create all the parent directories for path; like mkdir -p basename path.
Information about a node in the dependency graph: the file, whether it's dirty, mtime, etc.
virtual bool StartCommand(Edge *edge)
void ResumeDelayedJobs(Edge *edge)
Allows jobs blocking on |edge| to potentially resume.
void ScheduleWork(Edge *edge)
Submits a ready edge as a candidate for execution.
bool Parse(string *content, string *err)
Parse an input file.
bool ShouldDelayEdge() const
true if the Pool might delay this edge
bool StatIfNecessary(DiskInterface *disk_interface)
Return true if we needed to stat.
Interface for accessing the disk.
const BuildConfig & config_
bool is_smart_terminal() const
int64_t GetTimeMillis()
Get the current time as relative to some epoch.
bool GetBindingBool(const string &key)
void PrintOnNewLine(const string &to_print)
Prints a string on a new line, not overprinting previous output.
const BuildConfig & config_
void CleanNode(DependencyScan *scan, Node *node)
Clean the given node during the build.
bool outputs_ready() const
An edge in the dependency graph; links between Nodes using Rules.
void UpdateRate(int update_hint)
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.
string EvaluateCommand(bool incl_rsp_file=false)
Expand all variables in a command and return it as a string.
Subprocess * Add(const string &command)
bool AlreadyUpToDate() const
Returns true if the build targets are already up to date.
vector< Subprocess * > running_
const BuildConfig & config_
void BuildEdgeStarted(Edge *edge)
DiskInterface * disk_interface_
bool CanonicalizePath(string *path, string *err)
Canonicalize a path like "foo/../bar.h" into just "bar.h".
ExitStatus Finish()
Returns ExitSuccess on successful process exit, ExitInterrupted if the process was interrupted...
int command_edge_count() const
Number of edges with commands to run.
string Parse(const string &output)
Parse the full output of cl, returning the output (if any) that should printed.
void RecordCommand(Edge *edge, int start_time, int end_time, TimeStamp restat_mtime=0)
void EdgeFinished(Edge *edge)
Mark an edge as done building.
virtual bool WriteFile(const string &path, const string &contents)=0
Create a file, with the specified name and contents Returns true on success, false on failure...
As build commands run they can output extra dependency information (e.g.
signed long long int64_t
A 64-bit integer type.
const string & GetOutput() const
Builder(State *state, const BuildConfig &config, BuildLog *build_log, DepsLog *deps_log, DiskInterface *disk_interface)
BuildLog * build_log() const
Subprocess wraps a single async subprocess.
map< Edge *, bool > want_
Keep track of which edges we want to build in this plan.
virtual vector< Edge * > GetActiveEdges()
int64_t start_time_millis_
Time the build started.
int wanted_edges_
Total remaining number of wanted edges.
void set_smart_terminal(bool smart)
void FinishCommand(CommandRunner::Result *result)
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.
Node * LookupNode(StringPiece path)
vector< StringPiece > ins_
A pool for delayed edges.
#define METRIC_RECORD(name)
The primary interface to metrics.
auto_ptr< CommandRunner > command_runner_
const string & path() const
void RetrieveReadyEdges(set< Edge * > *ready_queue)
Pool will add zero or more edges to the ready_queue.
void PlanHasTotalEdges(int total)
void NodeFinished(Node *node)
bool CheckDependencyCycle(Node *node, vector< Node * > *stack, string *err)
string StripAnsiEscapeCodes(const string &in)
Removes all Ansi escape codes (http://www.termsys.demon.co.uk/vtansi.htm).
void Fatal(const char *msg,...)
Log a fatal message and exit.
Tracks the status of a build: completion fraction, printing updates.
bool ExtractDeps(CommandRunner::Result *result, const string &deps_type, vector< Node * > *deps_nodes, string *err)
const char * progress_status_format_
The custom progress status format to use.
string GetBinding(const string &key)
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...
void PrintStatus(Edge *edge)
void EdgeFinished(const Edge &edge)
informs this Pool that the given edge is no longer runnable, and should relinquish its resources back...
virtual int RemoveFile(const string &path)=0
Remove the file named path.
virtual bool CanRunMore()
Options (e.g. verbosity, parallelism) passed to a build.
Global state (file status, loaded rules) for a single run.
bool StartEdge(Edge *edge, string *err)
bool AllInputsReady() const
Return true if all inputs' in-edges are ready.
void Dump()
Dumps the current state of the plan.
void Print(string to_print, LineType type)
Overprints the current line.
bool RecordDeps(Node *node, TimeStamp mtime, const vector< Node * > &nodes)
RunningEdgeMap running_edges_
bool Build(string *err)
Run the build.
string FormatProgressStatus(const char *progress_status_format) const
Format the progress status string by replacing the placeholders.
LinePrinter printer_
Prints progress output.
Node * AddTarget(const string &name, string *err)
const vector< Edge * > & out_edges() const
virtual TimeStamp Stat(const string &path)=0
stat() a file, returning the mtime, or 0 if missing and -1 on other errors.
int command_edges_
Total number of edges that have commands (not phony).
void snprinfRate(double rate, char(&buf)[S], const char *format) const
DepsLog * deps_log() const
RealCommandRunner(const BuildConfig &config)
vector< Node * > outputs_