Ninja
ninja.cc
Go to the documentation of this file.
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 #include <errno.h>
16 #include <limits.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <cstdlib>
21 
22 #ifdef _WIN32
23 #include "getopt.h"
24 #include <direct.h>
25 #include <windows.h>
26 #elif defined(_AIX)
27 #include "getopt.h"
28 #include <unistd.h>
29 #else
30 #include <getopt.h>
31 #include <unistd.h>
32 #endif
33 
34 #include "browse.h"
35 #include "build.h"
36 #include "build_log.h"
37 #include "deps_log.h"
38 #include "clean.h"
39 #include "debug_flags.h"
40 #include "disk_interface.h"
41 #include "graph.h"
42 #include "graphviz.h"
43 #include "manifest_parser.h"
44 #include "metrics.h"
45 #include "state.h"
46 #include "util.h"
47 #include "version.h"
48 
49 using namespace std;
50 
51 #ifdef _MSC_VER
52 // Defined in msvc_helper_main-win32.cc.
53 int MSVCHelperMain(int argc, char** argv);
54 
55 // Defined in minidump-win32.cc.
56 void CreateWin32MiniDump(_EXCEPTION_POINTERS* pep);
57 #endif
58 
59 namespace {
60 
61 struct Tool;
62 
63 /// Command-line options.
64 struct Options {
65  /// Build file to load.
66  const char* input_file;
67 
68  /// Directory to change into before running.
69  const char* working_dir;
70 
71  /// Tool to run rather than building.
72  const Tool* tool;
73 
74  /// Whether duplicate rules for one target should warn or print an error.
75  bool dupe_edges_should_err;
76 
77  /// Whether phony cycles should warn or print an error.
78  bool phony_cycle_should_err;
79 };
80 
81 /// The Ninja main() loads up a series of data structures; various tools need
82 /// to poke into these, so store them as fields on an object.
83 struct NinjaMain : public BuildLogUser {
84  NinjaMain(const char* ninja_command, const BuildConfig& config) :
85  ninja_command_(ninja_command), config_(config) {}
86 
87  /// Command line used to run Ninja.
88  const char* ninja_command_;
89 
90  /// Build configuration set from flags (e.g. parallelism).
91  const BuildConfig& config_;
92 
93  /// Loaded state (rules, nodes).
94  State state_;
95 
96  /// Functions for accessing the disk.
97  RealDiskInterface disk_interface_;
98 
99  /// The build directory, used for storing the build log etc.
100  string build_dir_;
101 
102  BuildLog build_log_;
103  DepsLog deps_log_;
104 
105  /// The type of functions that are the entry points to tools (subcommands).
106  typedef int (NinjaMain::*ToolFunc)(const Options*, int, char**);
107 
108  /// Get the Node for a given command-line path, handling features like
109  /// spell correction.
110  Node* CollectTarget(const char* cpath, string* err);
111 
112  /// CollectTarget for all command-line arguments, filling in \a targets.
113  bool CollectTargetsFromArgs(int argc, char* argv[],
114  vector<Node*>* targets, string* err);
115 
116  // The various subcommands, run via "-t XXX".
117  int ToolGraph(const Options* options, int argc, char* argv[]);
118  int ToolQuery(const Options* options, int argc, char* argv[]);
119  int ToolDeps(const Options* options, int argc, char* argv[]);
120  int ToolBrowse(const Options* options, int argc, char* argv[]);
121  int ToolMSVC(const Options* options, int argc, char* argv[]);
122  int ToolTargets(const Options* options, int argc, char* argv[]);
123  int ToolCommands(const Options* options, int argc, char* argv[]);
124  int ToolClean(const Options* options, int argc, char* argv[]);
125  int ToolCleanDead(const Options* options, int argc, char* argv[]);
126  int ToolCompilationDatabase(const Options* options, int argc, char* argv[]);
127  int ToolRecompact(const Options* options, int argc, char* argv[]);
128  int ToolRestat(const Options* options, int argc, char* argv[]);
129  int ToolUrtle(const Options* options, int argc, char** argv);
130  int ToolRules(const Options* options, int argc, char* argv[]);
131 
132  /// Open the build log.
133  /// @return LOAD_ERROR on error.
134  bool OpenBuildLog(bool recompact_only = false);
135 
136  /// Open the deps log: load it, then open for writing.
137  /// @return LOAD_ERROR on error.
138  bool OpenDepsLog(bool recompact_only = false);
139 
140  /// Ensure the build directory exists, creating it if necessary.
141  /// @return false on error.
142  bool EnsureBuildDirExists();
143 
144  /// Rebuild the manifest, if necessary.
145  /// Fills in \a err on error.
146  /// @return true if the manifest was rebuilt.
147  bool RebuildManifest(const char* input_file, string* err);
148 
149  /// Build the targets listed on the command line.
150  /// @return an exit code.
151  int RunBuild(int argc, char** argv);
152 
153  /// Dump the output requested by '-d stats'.
154  void DumpMetrics();
155 
156  virtual bool IsPathDead(StringPiece s) const {
157  Node* n = state_.LookupNode(s);
158  if (n && n->in_edge())
159  return false;
160  // Just checking n isn't enough: If an old output is both in the build log
161  // and in the deps log, it will have a Node object in state_. (It will also
162  // have an in edge if one of its inputs is another output that's in the deps
163  // log, but having a deps edge product an output that's input to another deps
164  // edge is rare, and the first recompaction will delete all old outputs from
165  // the deps log, and then a second recompaction will clear the build log,
166  // which seems good enough for this corner case.)
167  // Do keep entries around for files which still exist on disk, for
168  // generators that want to use this information.
169  string err;
170  TimeStamp mtime = disk_interface_.Stat(s.AsString(), &err);
171  if (mtime == -1)
172  Error("%s", err.c_str()); // Log and ignore Stat() errors.
173  return mtime == 0;
174  }
175 };
176 
177 /// Subtools, accessible via "-t foo".
178 struct Tool {
179  /// Short name of the tool.
180  const char* name;
181 
182  /// Description (shown in "-t list").
183  const char* desc;
184 
185  /// When to run the tool.
186  enum {
187  /// Run after parsing the command-line flags and potentially changing
188  /// the current working directory (as early as possible).
189  RUN_AFTER_FLAGS,
190 
191  /// Run after loading build.ninja.
192  RUN_AFTER_LOAD,
193 
194  /// Run after loading the build/deps logs.
195  RUN_AFTER_LOGS,
196  } when;
197 
198  /// Implementation of the tool.
199  NinjaMain::ToolFunc func;
200 };
201 
202 /// Print usage information.
203 void Usage(const BuildConfig& config) {
204  fprintf(stderr,
205 "usage: ninja [options] [targets...]\n"
206 "\n"
207 "if targets are unspecified, builds the 'default' target (see manual).\n"
208 "\n"
209 "options:\n"
210 " --version print ninja version (\"%s\")\n"
211 " -v, --verbose show all command lines while building\n"
212 "\n"
213 " -C DIR change to DIR before doing anything else\n"
214 " -f FILE specify input build file [default=build.ninja]\n"
215 "\n"
216 " -j N run N jobs in parallel (0 means infinity) [default=%d on this system]\n"
217 " -k N keep going until N jobs fail (0 means infinity) [default=1]\n"
218 " -l N do not start new jobs if the load average is greater than N\n"
219 " -n dry run (don't run commands but act like they succeeded)\n"
220 "\n"
221 " -d MODE enable debugging (use '-d list' to list modes)\n"
222 " -t TOOL run a subtool (use '-t list' to list subtools)\n"
223 " terminates toplevel options; further flags are passed to the tool\n"
224 " -w FLAG adjust warnings (use '-w list' to list warnings)\n",
225  kNinjaVersion, config.parallelism);
226 }
227 
228 /// Choose a default value for the -j (parallelism) flag.
229 int GuessParallelism() {
230  switch (int processors = GetProcessorCount()) {
231  case 0:
232  case 1:
233  return 2;
234  case 2:
235  return 3;
236  default:
237  return processors + 2;
238  }
239 }
240 
241 /// Rebuild the build manifest, if necessary.
242 /// Returns true if the manifest was rebuilt.
243 bool NinjaMain::RebuildManifest(const char* input_file, string* err) {
244  string path = input_file;
245  uint64_t slash_bits; // Unused because this path is only used for lookup.
246  if (!CanonicalizePath(&path, &slash_bits, err))
247  return false;
248  Node* node = state_.LookupNode(path);
249  if (!node)
250  return false;
251 
252  Builder builder(&state_, config_, &build_log_, &deps_log_, &disk_interface_);
253  if (!builder.AddTarget(node, err))
254  return false;
255 
256  if (builder.AlreadyUpToDate())
257  return false; // Not an error, but we didn't rebuild.
258 
259  if (!builder.Build(err))
260  return false;
261 
262  // The manifest was only rebuilt if it is now dirty (it may have been cleaned
263  // by a restat).
264  if (!node->dirty()) {
265  // Reset the state to prevent problems like
266  // https://github.com/ninja-build/ninja/issues/874
267  state_.Reset();
268  return false;
269  }
270 
271  return true;
272 }
273 
274 Node* NinjaMain::CollectTarget(const char* cpath, string* err) {
275  string path = cpath;
276  uint64_t slash_bits;
277  if (!CanonicalizePath(&path, &slash_bits, err))
278  return NULL;
279 
280  // Special syntax: "foo.cc^" means "the first output of foo.cc".
281  bool first_dependent = false;
282  if (!path.empty() && path[path.size() - 1] == '^') {
283  path.resize(path.size() - 1);
284  first_dependent = true;
285  }
286 
287  Node* node = state_.LookupNode(path);
288  if (node) {
289  if (first_dependent) {
290  if (node->out_edges().empty()) {
291  *err = "'" + path + "' has no out edge";
292  return NULL;
293  }
294  Edge* edge = node->out_edges()[0];
295  if (edge->outputs_.empty()) {
296  edge->Dump();
297  Fatal("edge has no outputs");
298  }
299  node = edge->outputs_[0];
300  }
301  return node;
302  } else {
303  *err =
304  "unknown target '" + Node::PathDecanonicalized(path, slash_bits) + "'";
305  if (path == "clean") {
306  *err += ", did you mean 'ninja -t clean'?";
307  } else if (path == "help") {
308  *err += ", did you mean 'ninja -h'?";
309  } else {
310  Node* suggestion = state_.SpellcheckNode(path);
311  if (suggestion) {
312  *err += ", did you mean '" + suggestion->path() + "'?";
313  }
314  }
315  return NULL;
316  }
317 }
318 
319 bool NinjaMain::CollectTargetsFromArgs(int argc, char* argv[],
320  vector<Node*>* targets, string* err) {
321  if (argc == 0) {
322  *targets = state_.DefaultNodes(err);
323  return err->empty();
324  }
325 
326  for (int i = 0; i < argc; ++i) {
327  Node* node = CollectTarget(argv[i], err);
328  if (node == NULL)
329  return false;
330  targets->push_back(node);
331  }
332  return true;
333 }
334 
335 int NinjaMain::ToolGraph(const Options* options, int argc, char* argv[]) {
336  vector<Node*> nodes;
337  string err;
338  if (!CollectTargetsFromArgs(argc, argv, &nodes, &err)) {
339  Error("%s", err.c_str());
340  return 1;
341  }
342 
343  GraphViz graph(&state_, &disk_interface_);
344  graph.Start();
345  for (vector<Node*>::const_iterator n = nodes.begin(); n != nodes.end(); ++n)
346  graph.AddTarget(*n);
347  graph.Finish();
348 
349  return 0;
350 }
351 
352 int NinjaMain::ToolQuery(const Options* options, int argc, char* argv[]) {
353  if (argc == 0) {
354  Error("expected a target to query");
355  return 1;
356  }
357 
358  DyndepLoader dyndep_loader(&state_, &disk_interface_);
359 
360  for (int i = 0; i < argc; ++i) {
361  string err;
362  Node* node = CollectTarget(argv[i], &err);
363  if (!node) {
364  Error("%s", err.c_str());
365  return 1;
366  }
367 
368  printf("%s:\n", node->path().c_str());
369  if (Edge* edge = node->in_edge()) {
370  if (edge->dyndep_ && edge->dyndep_->dyndep_pending()) {
371  if (!dyndep_loader.LoadDyndeps(edge->dyndep_, &err)) {
372  Warning("%s\n", err.c_str());
373  }
374  }
375  printf(" input: %s\n", edge->rule_->name().c_str());
376  for (int in = 0; in < (int)edge->inputs_.size(); in++) {
377  const char* label = "";
378  if (edge->is_implicit(in))
379  label = "| ";
380  else if (edge->is_order_only(in))
381  label = "|| ";
382  printf(" %s%s\n", label, edge->inputs_[in]->path().c_str());
383  }
384  }
385  printf(" outputs:\n");
386  for (vector<Edge*>::const_iterator edge = node->out_edges().begin();
387  edge != node->out_edges().end(); ++edge) {
388  for (vector<Node*>::iterator out = (*edge)->outputs_.begin();
389  out != (*edge)->outputs_.end(); ++out) {
390  printf(" %s\n", (*out)->path().c_str());
391  }
392  }
393  }
394  return 0;
395 }
396 
397 #if defined(NINJA_HAVE_BROWSE)
398 int NinjaMain::ToolBrowse(const Options* options, int argc, char* argv[]) {
399  RunBrowsePython(&state_, ninja_command_, options->input_file, argc, argv);
400  // If we get here, the browse failed.
401  return 1;
402 }
403 #else
404 int NinjaMain::ToolBrowse(const Options*, int, char**) {
405  Fatal("browse tool not supported on this platform");
406  return 1;
407 }
408 #endif
409 
410 #if defined(_MSC_VER)
411 int NinjaMain::ToolMSVC(const Options* options, int argc, char* argv[]) {
412  // Reset getopt: push one argument onto the front of argv, reset optind.
413  argc++;
414  argv--;
415  optind = 0;
416  return MSVCHelperMain(argc, argv);
417 }
418 #endif
419 
420 int ToolTargetsList(const vector<Node*>& nodes, int depth, int indent) {
421  for (vector<Node*>::const_iterator n = nodes.begin();
422  n != nodes.end();
423  ++n) {
424  for (int i = 0; i < indent; ++i)
425  printf(" ");
426  const char* target = (*n)->path().c_str();
427  if ((*n)->in_edge()) {
428  printf("%s: %s\n", target, (*n)->in_edge()->rule_->name().c_str());
429  if (depth > 1 || depth <= 0)
430  ToolTargetsList((*n)->in_edge()->inputs_, depth - 1, indent + 1);
431  } else {
432  printf("%s\n", target);
433  }
434  }
435  return 0;
436 }
437 
438 int ToolTargetsSourceList(State* state) {
439  for (vector<Edge*>::iterator e = state->edges_.begin();
440  e != state->edges_.end(); ++e) {
441  for (vector<Node*>::iterator inps = (*e)->inputs_.begin();
442  inps != (*e)->inputs_.end(); ++inps) {
443  if (!(*inps)->in_edge())
444  printf("%s\n", (*inps)->path().c_str());
445  }
446  }
447  return 0;
448 }
449 
450 int ToolTargetsList(State* state, const string& rule_name) {
451  set<string> rules;
452 
453  // Gather the outputs.
454  for (vector<Edge*>::iterator e = state->edges_.begin();
455  e != state->edges_.end(); ++e) {
456  if ((*e)->rule_->name() == rule_name) {
457  for (vector<Node*>::iterator out_node = (*e)->outputs_.begin();
458  out_node != (*e)->outputs_.end(); ++out_node) {
459  rules.insert((*out_node)->path());
460  }
461  }
462  }
463 
464  // Print them.
465  for (set<string>::const_iterator i = rules.begin();
466  i != rules.end(); ++i) {
467  printf("%s\n", (*i).c_str());
468  }
469 
470  return 0;
471 }
472 
473 int ToolTargetsList(State* state) {
474  for (vector<Edge*>::iterator e = state->edges_.begin();
475  e != state->edges_.end(); ++e) {
476  for (vector<Node*>::iterator out_node = (*e)->outputs_.begin();
477  out_node != (*e)->outputs_.end(); ++out_node) {
478  printf("%s: %s\n",
479  (*out_node)->path().c_str(),
480  (*e)->rule_->name().c_str());
481  }
482  }
483  return 0;
484 }
485 
486 int NinjaMain::ToolDeps(const Options* options, int argc, char** argv) {
487  vector<Node*> nodes;
488  if (argc == 0) {
489  for (vector<Node*>::const_iterator ni = deps_log_.nodes().begin();
490  ni != deps_log_.nodes().end(); ++ni) {
491  if (deps_log_.IsDepsEntryLiveFor(*ni))
492  nodes.push_back(*ni);
493  }
494  } else {
495  string err;
496  if (!CollectTargetsFromArgs(argc, argv, &nodes, &err)) {
497  Error("%s", err.c_str());
498  return 1;
499  }
500  }
501 
502  RealDiskInterface disk_interface;
503  for (vector<Node*>::iterator it = nodes.begin(), end = nodes.end();
504  it != end; ++it) {
505  DepsLog::Deps* deps = deps_log_.GetDeps(*it);
506  if (!deps) {
507  printf("%s: deps not found\n", (*it)->path().c_str());
508  continue;
509  }
510 
511  string err;
512  TimeStamp mtime = disk_interface.Stat((*it)->path(), &err);
513  if (mtime == -1)
514  Error("%s", err.c_str()); // Log and ignore Stat() errors;
515  printf("%s: #deps %d, deps mtime %" PRId64 " (%s)\n",
516  (*it)->path().c_str(), deps->node_count, deps->mtime,
517  (!mtime || mtime > deps->mtime ? "STALE":"VALID"));
518  for (int i = 0; i < deps->node_count; ++i)
519  printf(" %s\n", deps->nodes[i]->path().c_str());
520  printf("\n");
521  }
522 
523  return 0;
524 }
525 
526 int NinjaMain::ToolTargets(const Options* options, int argc, char* argv[]) {
527  int depth = 1;
528  if (argc >= 1) {
529  string mode = argv[0];
530  if (mode == "rule") {
531  string rule;
532  if (argc > 1)
533  rule = argv[1];
534  if (rule.empty())
535  return ToolTargetsSourceList(&state_);
536  else
537  return ToolTargetsList(&state_, rule);
538  } else if (mode == "depth") {
539  if (argc > 1)
540  depth = atoi(argv[1]);
541  } else if (mode == "all") {
542  return ToolTargetsList(&state_);
543  } else {
544  const char* suggestion =
545  SpellcheckString(mode.c_str(), "rule", "depth", "all", NULL);
546  if (suggestion) {
547  Error("unknown target tool mode '%s', did you mean '%s'?",
548  mode.c_str(), suggestion);
549  } else {
550  Error("unknown target tool mode '%s'", mode.c_str());
551  }
552  return 1;
553  }
554  }
555 
556  string err;
557  vector<Node*> root_nodes = state_.RootNodes(&err);
558  if (err.empty()) {
559  return ToolTargetsList(root_nodes, depth, 0);
560  } else {
561  Error("%s", err.c_str());
562  return 1;
563  }
564 }
565 
566 int NinjaMain::ToolRules(const Options* options, int argc, char* argv[]) {
567  // Parse options.
568 
569  // The rules tool uses getopt, and expects argv[0] to contain the name of
570  // the tool, i.e. "rules".
571  argc++;
572  argv--;
573 
574  bool print_description = false;
575 
576  optind = 1;
577  int opt;
578  while ((opt = getopt(argc, argv, const_cast<char*>("hd"))) != -1) {
579  switch (opt) {
580  case 'd':
581  print_description = true;
582  break;
583  case 'h':
584  default:
585  printf("usage: ninja -t rules [options]\n"
586  "\n"
587  "options:\n"
588  " -d also print the description of the rule\n"
589  " -h print this message\n"
590  );
591  return 1;
592  }
593  }
594  argv += optind;
595  argc -= optind;
596 
597  // Print rules
598 
599  typedef map<string, const Rule*> Rules;
600  const Rules& rules = state_.bindings_.GetRules();
601  for (Rules::const_iterator i = rules.begin(); i != rules.end(); ++i) {
602  printf("%s", i->first.c_str());
603  if (print_description) {
604  const Rule* rule = i->second;
605  const EvalString* description = rule->GetBinding("description");
606  if (description != NULL) {
607  printf(": %s", description->Unparse().c_str());
608  }
609  }
610  printf("\n");
611  }
612  return 0;
613 }
614 
615 enum PrintCommandMode { PCM_Single, PCM_All };
616 void PrintCommands(Edge* edge, set<Edge*>* seen, PrintCommandMode mode) {
617  if (!edge)
618  return;
619  if (!seen->insert(edge).second)
620  return;
621 
622  if (mode == PCM_All) {
623  for (vector<Node*>::iterator in = edge->inputs_.begin();
624  in != edge->inputs_.end(); ++in)
625  PrintCommands((*in)->in_edge(), seen, mode);
626  }
627 
628  if (!edge->is_phony())
629  puts(edge->EvaluateCommand().c_str());
630 }
631 
632 int NinjaMain::ToolCommands(const Options* options, int argc, char* argv[]) {
633  // The clean tool uses getopt, and expects argv[0] to contain the name of
634  // the tool, i.e. "commands".
635  ++argc;
636  --argv;
637 
638  PrintCommandMode mode = PCM_All;
639 
640  optind = 1;
641  int opt;
642  while ((opt = getopt(argc, argv, const_cast<char*>("hs"))) != -1) {
643  switch (opt) {
644  case 's':
645  mode = PCM_Single;
646  break;
647  case 'h':
648  default:
649  printf("usage: ninja -t commands [options] [targets]\n"
650 "\n"
651 "options:\n"
652 " -s only print the final command to build [target], not the whole chain\n"
653  );
654  return 1;
655  }
656  }
657  argv += optind;
658  argc -= optind;
659 
660  vector<Node*> nodes;
661  string err;
662  if (!CollectTargetsFromArgs(argc, argv, &nodes, &err)) {
663  Error("%s", err.c_str());
664  return 1;
665  }
666 
667  set<Edge*> seen;
668  for (vector<Node*>::iterator in = nodes.begin(); in != nodes.end(); ++in)
669  PrintCommands((*in)->in_edge(), &seen, mode);
670 
671  return 0;
672 }
673 
674 int NinjaMain::ToolClean(const Options* options, int argc, char* argv[]) {
675  // The clean tool uses getopt, and expects argv[0] to contain the name of
676  // the tool, i.e. "clean".
677  argc++;
678  argv--;
679 
680  bool generator = false;
681  bool clean_rules = false;
682 
683  optind = 1;
684  int opt;
685  while ((opt = getopt(argc, argv, const_cast<char*>("hgr"))) != -1) {
686  switch (opt) {
687  case 'g':
688  generator = true;
689  break;
690  case 'r':
691  clean_rules = true;
692  break;
693  case 'h':
694  default:
695  printf("usage: ninja -t clean [options] [targets]\n"
696 "\n"
697 "options:\n"
698 " -g also clean files marked as ninja generator output\n"
699 " -r interpret targets as a list of rules to clean instead\n"
700  );
701  return 1;
702  }
703  }
704  argv += optind;
705  argc -= optind;
706 
707  if (clean_rules && argc == 0) {
708  Error("expected a rule to clean");
709  return 1;
710  }
711 
712  Cleaner cleaner(&state_, config_, &disk_interface_);
713  if (argc >= 1) {
714  if (clean_rules)
715  return cleaner.CleanRules(argc, argv);
716  else
717  return cleaner.CleanTargets(argc, argv);
718  } else {
719  return cleaner.CleanAll(generator);
720  }
721 }
722 
723 int NinjaMain::ToolCleanDead(const Options* options, int argc, char* argv[]) {
724  Cleaner cleaner(&state_, config_, &disk_interface_);
725  return cleaner.CleanDead(build_log_.entries());
726 }
727 
728 void EncodeJSONString(const char *str) {
729  while (*str) {
730  if (*str == '"' || *str == '\\')
731  putchar('\\');
732  putchar(*str);
733  str++;
734  }
735 }
736 
738  ECM_NORMAL,
739  ECM_EXPAND_RSPFILE
740 };
741 std::string EvaluateCommandWithRspfile(const Edge* edge,
742  const EvaluateCommandMode mode) {
743  string command = edge->EvaluateCommand();
744  if (mode == ECM_NORMAL)
745  return command;
746 
747  string rspfile = edge->GetUnescapedRspfile();
748  if (rspfile.empty())
749  return command;
750 
751  size_t index = command.find(rspfile);
752  if (index == 0 || index == string::npos || command[index - 1] != '@')
753  return command;
754 
755  string rspfile_content = edge->GetBinding("rspfile_content");
756  size_t newline_index = 0;
757  while ((newline_index = rspfile_content.find('\n', newline_index)) !=
758  string::npos) {
759  rspfile_content.replace(newline_index, 1, 1, ' ');
760  ++newline_index;
761  }
762  command.replace(index - 1, rspfile.length() + 1, rspfile_content);
763  return command;
764 }
765 
766 void printCompdb(const char* const directory, const Edge* const edge,
767  const EvaluateCommandMode eval_mode) {
768  printf("\n {\n \"directory\": \"");
769  EncodeJSONString(directory);
770  printf("\",\n \"command\": \"");
771  EncodeJSONString(EvaluateCommandWithRspfile(edge, eval_mode).c_str());
772  printf("\",\n \"file\": \"");
773  EncodeJSONString(edge->inputs_[0]->path().c_str());
774  printf("\",\n \"output\": \"");
775  EncodeJSONString(edge->outputs_[0]->path().c_str());
776  printf("\"\n }");
777 }
778 
779 int NinjaMain::ToolCompilationDatabase(const Options* options, int argc,
780  char* argv[]) {
781  // The compdb tool uses getopt, and expects argv[0] to contain the name of
782  // the tool, i.e. "compdb".
783  argc++;
784  argv--;
785 
786  EvaluateCommandMode eval_mode = ECM_NORMAL;
787 
788  optind = 1;
789  int opt;
790  while ((opt = getopt(argc, argv, const_cast<char*>("hx"))) != -1) {
791  switch(opt) {
792  case 'x':
793  eval_mode = ECM_EXPAND_RSPFILE;
794  break;
795 
796  case 'h':
797  default:
798  printf(
799  "usage: ninja -t compdb [options] [rules]\n"
800  "\n"
801  "options:\n"
802  " -x expand @rspfile style response file invocations\n"
803  );
804  return 1;
805  }
806  }
807  argv += optind;
808  argc -= optind;
809 
810  bool first = true;
811  vector<char> cwd;
812  char* success = NULL;
813 
814  do {
815  cwd.resize(cwd.size() + 1024);
816  errno = 0;
817  success = getcwd(&cwd[0], cwd.size());
818  } while (!success && errno == ERANGE);
819  if (!success) {
820  Error("cannot determine working directory: %s", strerror(errno));
821  return 1;
822  }
823 
824  putchar('[');
825  for (vector<Edge*>::iterator e = state_.edges_.begin();
826  e != state_.edges_.end(); ++e) {
827  if ((*e)->inputs_.empty())
828  continue;
829  if (argc == 0) {
830  if (!first) {
831  putchar(',');
832  }
833  printCompdb(&cwd[0], *e, eval_mode);
834  first = false;
835  } else {
836  for (int i = 0; i != argc; ++i) {
837  if ((*e)->rule_->name() == argv[i]) {
838  if (!first) {
839  putchar(',');
840  }
841  printCompdb(&cwd[0], *e, eval_mode);
842  first = false;
843  }
844  }
845  }
846  }
847 
848  puts("\n]");
849  return 0;
850 }
851 
852 int NinjaMain::ToolRecompact(const Options* options, int argc, char* argv[]) {
853  if (!EnsureBuildDirExists())
854  return 1;
855 
856  if (OpenBuildLog(/*recompact_only=*/true) == LOAD_ERROR ||
857  OpenDepsLog(/*recompact_only=*/true) == LOAD_ERROR)
858  return 1;
859 
860  return 0;
861 }
862 
863 int NinjaMain::ToolRestat(const Options* options, int argc, char* argv[]) {
864  // The restat tool uses getopt, and expects argv[0] to contain the name of the
865  // tool, i.e. "restat"
866  argc++;
867  argv--;
868 
869  optind = 1;
870  int opt;
871  while ((opt = getopt(argc, argv, const_cast<char*>("h"))) != -1) {
872  switch (opt) {
873  case 'h':
874  default:
875  printf("usage: ninja -t restat [outputs]\n");
876  return 1;
877  }
878  }
879  argv += optind;
880  argc -= optind;
881 
882  if (!EnsureBuildDirExists())
883  return 1;
884 
885  string log_path = ".ninja_log";
886  if (!build_dir_.empty())
887  log_path = build_dir_ + "/" + log_path;
888 
889  string err;
890  const LoadStatus status = build_log_.Load(log_path, &err);
891  if (status == LOAD_ERROR) {
892  Error("loading build log %s: %s", log_path.c_str(), err.c_str());
893  return EXIT_FAILURE;
894  }
895  if (status == LOAD_NOT_FOUND) {
896  // Nothing to restat, ignore this
897  return EXIT_SUCCESS;
898  }
899  if (!err.empty()) {
900  // Hack: Load() can return a warning via err by returning LOAD_SUCCESS.
901  Warning("%s", err.c_str());
902  err.clear();
903  }
904 
905  bool success = build_log_.Restat(log_path, disk_interface_, argc, argv, &err);
906  if (!success) {
907  Error("failed recompaction: %s", err.c_str());
908  return EXIT_FAILURE;
909  }
910 
911  if (!config_.dry_run) {
912  if (!build_log_.OpenForWrite(log_path, *this, &err)) {
913  Error("opening build log: %s", err.c_str());
914  return EXIT_FAILURE;
915  }
916  }
917 
918  return EXIT_SUCCESS;
919 }
920 
921 int NinjaMain::ToolUrtle(const Options* options, int argc, char** argv) {
922  // RLE encoded.
923  const char* urtle =
924 " 13 ,3;2!2;\n8 ,;<11!;\n5 `'<10!(2`'2!\n11 ,6;, `\\. `\\9 .,c13$ec,.\n6 "
925 ",2;11!>; `. ,;!2> .e8$2\".2 \"?7$e.\n <:<8!'` 2.3,.2` ,3!' ;,(?7\";2!2'<"
926 "; `?6$PF ,;,\n2 `'4!8;<!3'`2 3! ;,`'2`2'3!;4!`2.`!;2 3,2 .<!2'`).\n5 3`5"
927 "'2`9 `!2 `4!><3;5! J2$b,`!>;2!:2!`,d?b`!>\n26 `'-;,(<9!> $F3 )3.:!.2 d\""
928 "2 ) !>\n30 7`2'<3!- \"=-='5 .2 `2-=\",!>\n25 .ze9$er2 .,cd16$bc.'\n22 .e"
929 "14$,26$.\n21 z45$c .\n20 J50$c\n20 14$P\"`?34$b\n20 14$ dbc `2\"?22$?7$c"
930 "\n20 ?18$c.6 4\"8?4\" c8$P\n9 .2,.8 \"20$c.3 ._14 J9$\n .2,2c9$bec,.2 `?"
931 "21$c.3`4%,3%,3 c8$P\"\n22$c2 2\"?21$bc2,.2` .2,c7$P2\",cb\n23$b bc,.2\"2"
932 "?14$2F2\"5?2\",J5$P\" ,zd3$\n24$ ?$3?%3 `2\"2?12$bcucd3$P3\"2 2=7$\n23$P"
933 "\" ,3;<5!>2;,. `4\"6?2\"2 ,9;, `\"?2$\n";
934  int count = 0;
935  for (const char* p = urtle; *p; p++) {
936  if ('0' <= *p && *p <= '9') {
937  count = count*10 + *p - '0';
938  } else {
939  for (int i = 0; i < max(count, 1); ++i)
940  printf("%c", *p);
941  count = 0;
942  }
943  }
944  return 0;
945 }
946 
947 /// Find the function to execute for \a tool_name and return it via \a func.
948 /// Returns a Tool, or NULL if Ninja should exit.
949 const Tool* ChooseTool(const string& tool_name) {
950  static const Tool kTools[] = {
951  { "browse", "browse dependency graph in a web browser",
952  Tool::RUN_AFTER_LOAD, &NinjaMain::ToolBrowse },
953 #if defined(_MSC_VER)
954  { "msvc", "build helper for MSVC cl.exe (EXPERIMENTAL)",
955  Tool::RUN_AFTER_FLAGS, &NinjaMain::ToolMSVC },
956 #endif
957  { "clean", "clean built files",
958  Tool::RUN_AFTER_LOAD, &NinjaMain::ToolClean },
959  { "commands", "list all commands required to rebuild given targets",
960  Tool::RUN_AFTER_LOAD, &NinjaMain::ToolCommands },
961  { "deps", "show dependencies stored in the deps log",
962  Tool::RUN_AFTER_LOGS, &NinjaMain::ToolDeps },
963  { "graph", "output graphviz dot file for targets",
964  Tool::RUN_AFTER_LOAD, &NinjaMain::ToolGraph },
965  { "query", "show inputs/outputs for a path",
966  Tool::RUN_AFTER_LOGS, &NinjaMain::ToolQuery },
967  { "targets", "list targets by their rule or depth in the DAG",
968  Tool::RUN_AFTER_LOAD, &NinjaMain::ToolTargets },
969  { "compdb", "dump JSON compilation database to stdout",
970  Tool::RUN_AFTER_LOAD, &NinjaMain::ToolCompilationDatabase },
971  { "recompact", "recompacts ninja-internal data structures",
972  Tool::RUN_AFTER_LOAD, &NinjaMain::ToolRecompact },
973  { "restat", "restats all outputs in the build log",
974  Tool::RUN_AFTER_FLAGS, &NinjaMain::ToolRestat },
975  { "rules", "list all rules",
976  Tool::RUN_AFTER_LOAD, &NinjaMain::ToolRules },
977  { "cleandead", "clean built files that are no longer produced by the manifest",
978  Tool::RUN_AFTER_LOGS, &NinjaMain::ToolCleanDead },
979  { "urtle", NULL,
980  Tool::RUN_AFTER_FLAGS, &NinjaMain::ToolUrtle },
981  { NULL, NULL, Tool::RUN_AFTER_FLAGS, NULL }
982  };
983 
984  if (tool_name == "list") {
985  printf("ninja subtools:\n");
986  for (const Tool* tool = &kTools[0]; tool->name; ++tool) {
987  if (tool->desc)
988  printf("%10s %s\n", tool->name, tool->desc);
989  }
990  return NULL;
991  }
992 
993  for (const Tool* tool = &kTools[0]; tool->name; ++tool) {
994  if (tool->name == tool_name)
995  return tool;
996  }
997 
998  vector<const char*> words;
999  for (const Tool* tool = &kTools[0]; tool->name; ++tool)
1000  words.push_back(tool->name);
1001  const char* suggestion = SpellcheckStringV(tool_name, words);
1002  if (suggestion) {
1003  Fatal("unknown tool '%s', did you mean '%s'?",
1004  tool_name.c_str(), suggestion);
1005  } else {
1006  Fatal("unknown tool '%s'", tool_name.c_str());
1007  }
1008  return NULL; // Not reached.
1009 }
1010 
1011 /// Enable a debugging mode. Returns false if Ninja should exit instead
1012 /// of continuing.
1013 bool DebugEnable(const string& name) {
1014  if (name == "list") {
1015  printf("debugging modes:\n"
1016 " stats print operation counts/timing info\n"
1017 " explain explain what caused a command to execute\n"
1018 " keepdepfile don't delete depfiles after they're read by ninja\n"
1019 " keeprsp don't delete @response files on success\n"
1020 #ifdef _WIN32
1021 " nostatcache don't batch stat() calls per directory and cache them\n"
1022 #endif
1023 "multiple modes can be enabled via -d FOO -d BAR\n");
1024  return false;
1025  } else if (name == "stats") {
1026  g_metrics = new Metrics;
1027  return true;
1028  } else if (name == "explain") {
1029  g_explaining = true;
1030  return true;
1031  } else if (name == "keepdepfile") {
1032  g_keep_depfile = true;
1033  return true;
1034  } else if (name == "keeprsp") {
1035  g_keep_rsp = true;
1036  return true;
1037  } else if (name == "nostatcache") {
1038  g_experimental_statcache = false;
1039  return true;
1040  } else {
1041  const char* suggestion =
1042  SpellcheckString(name.c_str(),
1043  "stats", "explain", "keepdepfile", "keeprsp",
1044  "nostatcache", NULL);
1045  if (suggestion) {
1046  Error("unknown debug setting '%s', did you mean '%s'?",
1047  name.c_str(), suggestion);
1048  } else {
1049  Error("unknown debug setting '%s'", name.c_str());
1050  }
1051  return false;
1052  }
1053 }
1054 
1055 /// Set a warning flag. Returns false if Ninja should exit instead of
1056 /// continuing.
1057 bool WarningEnable(const string& name, Options* options) {
1058  if (name == "list") {
1059  printf("warning flags:\n"
1060 " dupbuild={err,warn} multiple build lines for one target\n"
1061 " phonycycle={err,warn} phony build statement references itself\n"
1062  );
1063  return false;
1064  } else if (name == "dupbuild=err") {
1065  options->dupe_edges_should_err = true;
1066  return true;
1067  } else if (name == "dupbuild=warn") {
1068  options->dupe_edges_should_err = false;
1069  return true;
1070  } else if (name == "phonycycle=err") {
1071  options->phony_cycle_should_err = true;
1072  return true;
1073  } else if (name == "phonycycle=warn") {
1074  options->phony_cycle_should_err = false;
1075  return true;
1076  } else if (name == "depfilemulti=err" ||
1077  name == "depfilemulti=warn") {
1078  Warning("deprecated warning 'depfilemulti'");
1079  return true;
1080  } else {
1081  const char* suggestion =
1082  SpellcheckString(name.c_str(), "dupbuild=err", "dupbuild=warn",
1083  "phonycycle=err", "phonycycle=warn", NULL);
1084  if (suggestion) {
1085  Error("unknown warning flag '%s', did you mean '%s'?",
1086  name.c_str(), suggestion);
1087  } else {
1088  Error("unknown warning flag '%s'", name.c_str());
1089  }
1090  return false;
1091  }
1092 }
1093 
1094 bool NinjaMain::OpenBuildLog(bool recompact_only) {
1095  string log_path = ".ninja_log";
1096  if (!build_dir_.empty())
1097  log_path = build_dir_ + "/" + log_path;
1098 
1099  string err;
1100  const LoadStatus status = build_log_.Load(log_path, &err);
1101  if (status == LOAD_ERROR) {
1102  Error("loading build log %s: %s", log_path.c_str(), err.c_str());
1103  return false;
1104  }
1105  if (!err.empty()) {
1106  // Hack: Load() can return a warning via err by returning LOAD_SUCCESS.
1107  Warning("%s", err.c_str());
1108  err.clear();
1109  }
1110 
1111  if (recompact_only) {
1112  if (status == LOAD_NOT_FOUND) {
1113  return true;
1114  }
1115  bool success = build_log_.Recompact(log_path, *this, &err);
1116  if (!success)
1117  Error("failed recompaction: %s", err.c_str());
1118  return success;
1119  }
1120 
1121  if (!config_.dry_run) {
1122  if (!build_log_.OpenForWrite(log_path, *this, &err)) {
1123  Error("opening build log: %s", err.c_str());
1124  return false;
1125  }
1126  }
1127 
1128  return true;
1129 }
1130 
1131 /// Open the deps log: load it, then open for writing.
1132 /// @return false on error.
1133 bool NinjaMain::OpenDepsLog(bool recompact_only) {
1134  string path = ".ninja_deps";
1135  if (!build_dir_.empty())
1136  path = build_dir_ + "/" + path;
1137 
1138  string err;
1139  const LoadStatus status = deps_log_.Load(path, &state_, &err);
1140  if (status == LOAD_ERROR) {
1141  Error("loading deps log %s: %s", path.c_str(), err.c_str());
1142  return false;
1143  }
1144  if (!err.empty()) {
1145  // Hack: Load() can return a warning via err by returning LOAD_SUCCESS.
1146  Warning("%s", err.c_str());
1147  err.clear();
1148  }
1149 
1150  if (recompact_only) {
1151  if (status == LOAD_NOT_FOUND) {
1152  return true;
1153  }
1154  bool success = deps_log_.Recompact(path, &err);
1155  if (!success)
1156  Error("failed recompaction: %s", err.c_str());
1157  return success;
1158  }
1159 
1160  if (!config_.dry_run) {
1161  if (!deps_log_.OpenForWrite(path, &err)) {
1162  Error("opening deps log: %s", err.c_str());
1163  return false;
1164  }
1165  }
1166 
1167  return true;
1168 }
1169 
1170 void NinjaMain::DumpMetrics() {
1171  g_metrics->Report();
1172 
1173  printf("\n");
1174  int count = (int)state_.paths_.size();
1175  int buckets = (int)state_.paths_.bucket_count();
1176  printf("path->node hash load %.2f (%d entries / %d buckets)\n",
1177  count / (double) buckets, count, buckets);
1178 }
1179 
1180 bool NinjaMain::EnsureBuildDirExists() {
1181  build_dir_ = state_.bindings_.LookupVariable("builddir");
1182  if (!build_dir_.empty() && !config_.dry_run) {
1183  if (!disk_interface_.MakeDirs(build_dir_ + "/.") && errno != EEXIST) {
1184  Error("creating build directory %s: %s",
1185  build_dir_.c_str(), strerror(errno));
1186  return false;
1187  }
1188  }
1189  return true;
1190 }
1191 
1192 int NinjaMain::RunBuild(int argc, char** argv) {
1193  string err;
1194  vector<Node*> targets;
1195  if (!CollectTargetsFromArgs(argc, argv, &targets, &err)) {
1196  Error("%s", err.c_str());
1197  return 1;
1198  }
1199 
1200  disk_interface_.AllowStatCache(g_experimental_statcache);
1201 
1202  Builder builder(&state_, config_, &build_log_, &deps_log_, &disk_interface_);
1203  for (size_t i = 0; i < targets.size(); ++i) {
1204  if (!builder.AddTarget(targets[i], &err)) {
1205  if (!err.empty()) {
1206  Error("%s", err.c_str());
1207  return 1;
1208  } else {
1209  // Added a target that is already up-to-date; not really
1210  // an error.
1211  }
1212  }
1213  }
1214 
1215  // Make sure restat rules do not see stale timestamps.
1216  disk_interface_.AllowStatCache(false);
1217 
1218  if (builder.AlreadyUpToDate()) {
1219  printf("ninja: no work to do.\n");
1220  return 0;
1221  }
1222 
1223  if (!builder.Build(&err)) {
1224  printf("ninja: build stopped: %s.\n", err.c_str());
1225  if (err.find("interrupted by user") != string::npos) {
1226  return 2;
1227  }
1228  return 1;
1229  }
1230 
1231  return 0;
1232 }
1233 
1234 #ifdef _MSC_VER
1235 
1236 /// This handler processes fatal crashes that you can't catch
1237 /// Test example: C++ exception in a stack-unwind-block
1238 /// Real-world example: ninja launched a compiler to process a tricky
1239 /// C++ input file. The compiler got itself into a state where it
1240 /// generated 3 GB of output and caused ninja to crash.
1241 void TerminateHandler() {
1242  CreateWin32MiniDump(NULL);
1243  Fatal("terminate handler called");
1244 }
1245 
1246 /// On Windows, we want to prevent error dialogs in case of exceptions.
1247 /// This function handles the exception, and writes a minidump.
1248 int ExceptionFilter(unsigned int code, struct _EXCEPTION_POINTERS *ep) {
1249  Error("exception: 0x%X", code); // e.g. EXCEPTION_ACCESS_VIOLATION
1250  fflush(stderr);
1251  CreateWin32MiniDump(ep);
1252  return EXCEPTION_EXECUTE_HANDLER;
1253 }
1254 
1255 #endif // _MSC_VER
1256 
1257 /// Parse argv for command-line options.
1258 /// Returns an exit code, or -1 if Ninja should continue.
1259 int ReadFlags(int* argc, char*** argv,
1260  Options* options, BuildConfig* config) {
1261  config->parallelism = GuessParallelism();
1262 
1263  enum { OPT_VERSION = 1 };
1264  const option kLongOptions[] = {
1265  { "help", no_argument, NULL, 'h' },
1266  { "version", no_argument, NULL, OPT_VERSION },
1267  { "verbose", no_argument, NULL, 'v' },
1268  { NULL, 0, NULL, 0 }
1269  };
1270 
1271  int opt;
1272  while (!options->tool &&
1273  (opt = getopt_long(*argc, *argv, "d:f:j:k:l:nt:vw:C:h", kLongOptions,
1274  NULL)) != -1) {
1275  switch (opt) {
1276  case 'd':
1277  if (!DebugEnable(optarg))
1278  return 1;
1279  break;
1280  case 'f':
1281  options->input_file = optarg;
1282  break;
1283  case 'j': {
1284  char* end;
1285  int value = strtol(optarg, &end, 10);
1286  if (*end != 0 || value < 0)
1287  Fatal("invalid -j parameter");
1288 
1289  // We want to run N jobs in parallel. For N = 0, INT_MAX
1290  // is close enough to infinite for most sane builds.
1291  config->parallelism = value > 0 ? value : INT_MAX;
1292  break;
1293  }
1294  case 'k': {
1295  char* end;
1296  int value = strtol(optarg, &end, 10);
1297  if (*end != 0)
1298  Fatal("-k parameter not numeric; did you mean -k 0?");
1299 
1300  // We want to go until N jobs fail, which means we should allow
1301  // N failures and then stop. For N <= 0, INT_MAX is close enough
1302  // to infinite for most sane builds.
1303  config->failures_allowed = value > 0 ? value : INT_MAX;
1304  break;
1305  }
1306  case 'l': {
1307  char* end;
1308  double value = strtod(optarg, &end);
1309  if (end == optarg)
1310  Fatal("-l parameter not numeric: did you mean -l 0.0?");
1311  config->max_load_average = value;
1312  break;
1313  }
1314  case 'n':
1315  config->dry_run = true;
1316  break;
1317  case 't':
1318  options->tool = ChooseTool(optarg);
1319  if (!options->tool)
1320  return 0;
1321  break;
1322  case 'v':
1323  config->verbosity = BuildConfig::VERBOSE;
1324  break;
1325  case 'w':
1326  if (!WarningEnable(optarg, options))
1327  return 1;
1328  break;
1329  case 'C':
1330  options->working_dir = optarg;
1331  break;
1332  case OPT_VERSION:
1333  printf("%s\n", kNinjaVersion);
1334  return 0;
1335  case 'h':
1336  default:
1337  Usage(*config);
1338  return 1;
1339  }
1340  }
1341  *argv += optind;
1342  *argc -= optind;
1343 
1344  return -1;
1345 }
1346 
1347 NORETURN void real_main(int argc, char** argv) {
1348  // Use exit() instead of return in this function to avoid potentially
1349  // expensive cleanup when destructing NinjaMain.
1350  BuildConfig config;
1351  Options options = {};
1352  options.input_file = "build.ninja";
1353  options.dupe_edges_should_err = true;
1354 
1355  setvbuf(stdout, NULL, _IOLBF, BUFSIZ);
1356  const char* ninja_command = argv[0];
1357 
1358  int exit_code = ReadFlags(&argc, &argv, &options, &config);
1359  if (exit_code >= 0)
1360  exit(exit_code);
1361 
1362  if (options.working_dir) {
1363  // The formatting of this string, complete with funny quotes, is
1364  // so Emacs can properly identify that the cwd has changed for
1365  // subsequent commands.
1366  // Don't print this if a tool is being used, so that tool output
1367  // can be piped into a file without this string showing up.
1368  if (!options.tool)
1369  printf("ninja: Entering directory `%s'\n", options.working_dir);
1370  if (chdir(options.working_dir) < 0) {
1371  Fatal("chdir to '%s' - %s", options.working_dir, strerror(errno));
1372  }
1373  }
1374 
1375  if (options.tool && options.tool->when == Tool::RUN_AFTER_FLAGS) {
1376  // None of the RUN_AFTER_FLAGS actually use a NinjaMain, but it's needed
1377  // by other tools.
1378  NinjaMain ninja(ninja_command, config);
1379  exit((ninja.*options.tool->func)(&options, argc, argv));
1380  }
1381 
1382  // Limit number of rebuilds, to prevent infinite loops.
1383  const int kCycleLimit = 100;
1384  for (int cycle = 1; cycle <= kCycleLimit; ++cycle) {
1385  NinjaMain ninja(ninja_command, config);
1386 
1387  ManifestParserOptions parser_opts;
1388  if (options.dupe_edges_should_err) {
1390  }
1391  if (options.phony_cycle_should_err) {
1393  }
1394  ManifestParser parser(&ninja.state_, &ninja.disk_interface_, parser_opts);
1395  string err;
1396  if (!parser.Load(options.input_file, &err)) {
1397  Error("%s", err.c_str());
1398  exit(1);
1399  }
1400 
1401  if (options.tool && options.tool->when == Tool::RUN_AFTER_LOAD)
1402  exit((ninja.*options.tool->func)(&options, argc, argv));
1403 
1404  if (!ninja.EnsureBuildDirExists())
1405  exit(1);
1406 
1407  if (!ninja.OpenBuildLog() || !ninja.OpenDepsLog())
1408  exit(1);
1409 
1410  if (options.tool && options.tool->when == Tool::RUN_AFTER_LOGS)
1411  exit((ninja.*options.tool->func)(&options, argc, argv));
1412 
1413  // Attempt to rebuild the manifest before building anything else
1414  if (ninja.RebuildManifest(options.input_file, &err)) {
1415  // In dry_run mode the regeneration will succeed without changing the
1416  // manifest forever. Better to return immediately.
1417  if (config.dry_run)
1418  exit(0);
1419  // Start the build over with the new manifest.
1420  continue;
1421  } else if (!err.empty()) {
1422  Error("rebuilding '%s': %s", options.input_file, err.c_str());
1423  exit(1);
1424  }
1425 
1426  int result = ninja.RunBuild(argc, argv);
1427  if (g_metrics)
1428  ninja.DumpMetrics();
1429  exit(result);
1430  }
1431 
1432  Error("manifest '%s' still dirty after %d tries\n",
1433  options.input_file, kCycleLimit);
1434  exit(1);
1435 }
1436 
1437 } // anonymous namespace
1438 
1439 int main(int argc, char** argv) {
1440 #if defined(_MSC_VER)
1441  // Set a handler to catch crashes not caught by the __try..__except
1442  // block (e.g. an exception in a stack-unwind-block).
1443  std::set_terminate(TerminateHandler);
1444  __try {
1445  // Running inside __try ... __except suppresses any Windows error
1446  // dialogs for errors such as bad_alloc.
1447  real_main(argc, argv);
1448  }
1449  __except(ExceptionFilter(GetExceptionCode(), GetExceptionInformation())) {
1450  // Common error situations return exitCode=1. 2 was chosen to
1451  // indicate a more serious problem.
1452  return 2;
1453  }
1454 #else
1455  real_main(argc, argv);
1456 #endif
1457 }
bool OpenForWrite(const std::string &path, const BuildLogUser &user, std::string *err)
Prepares writing to the log file without actually opening it - that will happen when/if it&#39;s needed...
Definition: build_log.cc:131
#define no_argument
Definition: getopt.h:7
bool Recompact(const std::string &path, const BuildLogUser &user, std::string *err)
Rewrite the known log entries, throwing away old data.
Definition: build_log.cc:390
void Reset()
Reset state.
Definition: state.cc:185
bool dyndep_pending() const
Definition: graph.h:91
void Report()
Print a summary report to stdout.
Definition: metrics.cc:103
const char * SpellcheckStringV(const string &text, const vector< const char *> &words)
Definition: util.cc:395
const Entries & entries() const
Definition: build_log.h:94
std::string AsString() const
Convert the slice into a full-fledged std::string, copying the data into a new string.
Definition: string_piece.h:46
Verbosity verbosity
Definition: build.h:169
Node * SpellcheckNode(const std::string &path)
Definition: state.cc:121
LoadStatus Load(const std::string &path, std::string *err)
Load the on-disk log.
Definition: build_log.cc:261
const char * SpellcheckString(const char *text,...)
Like SpellcheckStringV, but takes a NULL-terminated list.
Definition: util.cc:414
LoadStatus
Definition: load_status.h:18
const std::map< std::string, const Rule * > & GetRules() const
Definition: eval_env.cc:81
void Dump(const char *prefix="") const
Definition: graph.cc:435
const EvalString * GetBinding(const std::string &key) const
Definition: eval_env.cc:59
const std::vector< Node * > & nodes() const
Used for tests.
Definition: deps_log.h:102
double max_load_average
The maximum load average we must not exceed.
Definition: build.h:175
int MSVCHelperMain(int argc, char **argv)
Edge * in_edge() const
Definition: graph.h:94
bool Restat(StringPiece path, const DiskInterface &disk_interface, int output_count, char **outputs, std::string *err)
Restat all outputs in the log.
Definition: build_log.cc:439
bool CanonicalizePath(string *path, uint64_t *slash_bits, string *err)
Definition: util.cc:95
PhonyCycleAction phony_cycle_action_
StringPiece represents a slice of a string whose memory is managed externally.
Definition: string_piece.h:25
const std::string & name() const
Definition: eval_env.h:62
Paths paths_
Definition: state.h:118
Information about a node in the dependency graph: the file, whether it&#39;s dirty, mtime, etc.
Definition: graph.h:37
virtual TimeStamp Stat(const std::string &path, std::string *err) const
stat() a file, returning the mtime, or 0 if missing and -1 on other errors.
Node ** nodes
Definition: deps_log.h:85
bool g_keep_depfile
Definition: debug_flags.cc:17
std::vector< Node * > outputs_
Definition: graph.h:175
Metrics * g_metrics
Definition: metrics.cc:33
#define PRId64
Definition: win32port.h:33
An edge in the dependency graph; links between Nodes using Rules.
Definition: graph.h:139
const char * kNinjaVersion
The version number of the current Ninja release.
Definition: version.cc:23
Node * LookupNode(StringPiece path) const
Definition: state.cc:113
Store a log of every command ran for every build.
Definition: build_log.h:43
std::string PathDecanonicalized() const
Get |path()| but use slash_bits to convert back to original slash styles.
Definition: graph.h:78
bool g_explaining
Definition: debug_flags.cc:15
std::vector< Node * > RootNodes(std::string *error) const
Definition: state.cc:163
bool is_order_only(size_t index)
Definition: graph.h:202
LoadStatus Load(const std::string &path, State *state, std::string *err)
Definition: deps_log.cc:152
const std::string & path() const
Definition: graph.h:76
bool Recompact(const std::string &path, std::string *err)
Rewrite the known log entries, throwing away old data.
Definition: deps_log.cc:298
#define NORETURN
Definition: util.h:30
As build commands run they can output extra dependency information (e.g.
Definition: deps_log.h:68
Parses .ninja files.
Implementation of DiskInterface that actually hits the disk.
int parallelism
Definition: build.h:171
int failures_allowed
Definition: build.h:172
bool is_implicit(size_t index)
Definition: graph.h:198
void RunBrowsePython(State *state, const char *ninja_command, const char *input_file, int argc, char *argv[])
Run in "browse" mode, which execs a Python webserver.
Definition: browse.cc:27
int getopt_long(int argc, char **argv, const char *shortopts, const GETOPT_LONG_OPTION_T *longopts, int *longind)
An invokable build command and associated metadata (description, etc.).
Definition: eval_env.h:59
Deps * GetDeps(Node *node)
Definition: deps_log.cc:290
int node_count
Definition: deps_log.h:84
bool dirty() const
Definition: graph.h:87
std::string GetUnescapedRspfile() const
Like GetBinding("rspfile"), but without shell escaping.
Definition: graph.cc:430
int getopt(int argc, char **argv, char *optstring)
int64_t TimeStamp
Definition: timestamp.h:31
DyndepLoader loads dynamically discovered dependencies, as referenced via the "dyndep" attribute in b...
Definition: dyndep.h:44
char * optarg
int main(int argc, char **argv)
Definition: ninja.cc:1439
BindingEnv bindings_
Definition: state.h:126
EvaluateCommandMode
Definition: ninja.cc:737
bool OpenForWrite(const std::string &path, std::string *err)
Definition: deps_log.cc:48
std::vector< Node * > inputs_
Definition: graph.h:174
bool g_experimental_statcache
Definition: debug_flags.cc:21
int optind
Builder wraps the build process: starting commands, updating status.
Definition: build.h:180
std::string GetBinding(const std::string &key) const
Returns the shell-escaped value of |key|.
Definition: graph.cc:411
void Fatal(const char *msg,...)
Log a fatal message and exit.
Definition: util.cc:59
std::vector< Node * > DefaultNodes(std::string *error) const
Definition: state.cc:181
PrintCommandMode
Definition: ninja.cc:615
The singleton that stores metrics and prints the report.
Definition: metrics.h:50
const Rule * rule_
Definition: graph.h:172
bool MakeDirs(const std::string &path)
Create all the parent directories for path; like mkdir -p basename path.
Runs the process of creating GraphViz .dot file output.
Definition: graphviz.h:28
std::string EvaluateCommand(bool incl_rsp_file=false) const
Expand all variables in a command and return it as a string.
Definition: graph.cc:401
void AllowStatCache(bool allow)
Whether stat information can be cached. Only has an effect on Windows.
const std::vector< Edge * > & out_edges() const
Definition: graph.h:100
std::string Unparse() const
Definition: eval_env.cc:137
int GetProcessorCount()
Definition: util.cc:484
Options (e.g. verbosity, parallelism) passed to a build.
Definition: build.h:160
Global state (file status) for a single run.
Definition: state.h:84
bool g_keep_rsp
Definition: debug_flags.cc:19
unsigned long long uint64_t
Definition: win32port.h:29
std::vector< Edge * > edges_
All the edges of the graph.
Definition: state.h:124
TimeStamp mtime
Definition: deps_log.h:83
bool is_phony() const
Definition: graph.cc:456
virtual std::string LookupVariable(const std::string &var)
Definition: eval_env.cc:21
A tokenized string that contains variable references.
Definition: eval_env.h:34
void Warning(const char *msg,...)
Log a warning message.
Definition: util.cc:77
DupeEdgeAction dupe_edge_action_
Definition: clean.h:30
bool dry_run
Definition: build.h:170
void Error(const char *msg,...)
Log an error message.
Definition: util.cc:86
Node * dyndep_
Definition: graph.h:176
bool IsDepsEntryLiveFor(Node *node)
Returns if the deps entry for a node is still reachable from the manifest.
Definition: deps_log.cc:351
Can answer questions about the manifest for the BuildLog.
Definition: build_log.h:30