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 
21 #ifdef _WIN32
22 #include "getopt.h"
23 #include <direct.h>
24 #include <windows.h>
25 #else
26 #include <getopt.h>
27 #include <unistd.h>
28 #endif
29 
30 #include "browse.h"
31 #include "build.h"
32 #include "build_log.h"
33 #include "deps_log.h"
34 #include "clean.h"
35 #include "debug_flags.h"
36 #include "disk_interface.h"
37 #include "graph.h"
38 #include "graphviz.h"
39 #include "manifest_parser.h"
40 #include "metrics.h"
41 #include "state.h"
42 #include "util.h"
43 #include "version.h"
44 
45 #ifdef _MSC_VER
46 // Defined in msvc_helper_main-win32.cc.
47 int MSVCHelperMain(int argc, char** argv);
48 
49 // Defined in minidump-win32.cc.
50 void CreateWin32MiniDump(_EXCEPTION_POINTERS* pep);
51 #endif
52 
53 namespace {
54 
55 struct Tool;
56 
57 /// Command-line options.
58 struct Options {
59  /// Build file to load.
60  const char* input_file;
61 
62  /// Directory to change into before running.
63  const char* working_dir;
64 
65  /// Tool to run rather than building.
66  const Tool* tool;
67 };
68 
69 /// The Ninja main() loads up a series of data structures; various tools need
70 /// to poke into these, so store them as fields on an object.
71 struct NinjaMain : public BuildLogUser {
72  NinjaMain(const char* ninja_command, const BuildConfig& config) :
73  ninja_command_(ninja_command), config_(config) {}
74 
75  /// Command line used to run Ninja.
76  const char* ninja_command_;
77 
78  /// Build configuration set from flags (e.g. parallelism).
79  const BuildConfig& config_;
80 
81  /// Loaded state (rules, nodes).
82  State state_;
83 
84  /// Functions for accesssing the disk.
85  RealDiskInterface disk_interface_;
86 
87  /// The build directory, used for storing the build log etc.
88  string build_dir_;
89 
90  BuildLog build_log_;
91  DepsLog deps_log_;
92 
93  /// The type of functions that are the entry points to tools (subcommands).
94  typedef int (NinjaMain::*ToolFunc)(int, char**);
95 
96  /// Get the Node for a given command-line path, handling features like
97  /// spell correction.
98  Node* CollectTarget(const char* cpath, string* err);
99 
100  /// CollectTarget for all command-line arguments, filling in \a targets.
101  bool CollectTargetsFromArgs(int argc, char* argv[],
102  vector<Node*>* targets, string* err);
103 
104  // The various subcommands, run via "-t XXX".
105  int ToolGraph(int argc, char* argv[]);
106  int ToolQuery(int argc, char* argv[]);
107  int ToolDeps(int argc, char* argv[]);
108  int ToolBrowse(int argc, char* argv[]);
109  int ToolMSVC(int argc, char* argv[]);
110  int ToolTargets(int argc, char* argv[]);
111  int ToolCommands(int argc, char* argv[]);
112  int ToolClean(int argc, char* argv[]);
113  int ToolCompilationDatabase(int argc, char* argv[]);
114  int ToolRecompact(int argc, char* argv[]);
115  int ToolUrtle(int argc, char** argv);
116 
117  /// Open the build log.
118  /// @return false on error.
119  bool OpenBuildLog(bool recompact_only = false);
120 
121  /// Open the deps log: load it, then open for writing.
122  /// @return false on error.
123  bool OpenDepsLog(bool recompact_only = false);
124 
125  /// Ensure the build directory exists, creating it if necessary.
126  /// @return false on error.
127  bool EnsureBuildDirExists();
128 
129  /// Rebuild the manifest, if necessary.
130  /// Fills in \a err on error.
131  /// @return true if the manifest was rebuilt.
132  bool RebuildManifest(const char* input_file, string* err);
133 
134  /// Build the targets listed on the command line.
135  /// @return an exit code.
136  int RunBuild(int argc, char** argv);
137 
138  /// Dump the output requested by '-d stats'.
139  void DumpMetrics();
140 
141  virtual bool IsPathDead(StringPiece s) const {
142  Node* n = state_.LookupNode(s);
143  // Just checking n isn't enough: If an old output is both in the build log
144  // and in the deps log, it will have a Node object in state_. (It will also
145  // have an in edge if one of its inputs is another output that's in the deps
146  // log, but having a deps edge product an output thats input to another deps
147  // edge is rare, and the first recompaction will delete all old outputs from
148  // the deps log, and then a second recompaction will clear the build log,
149  // which seems good enough for this corner case.)
150  // Do keep entries around for files which still exist on disk, for
151  // generators that want to use this information.
152  return (!n || !n->in_edge()) && disk_interface_.Stat(s.AsString()) == 0;
153  }
154 };
155 
156 /// Subtools, accessible via "-t foo".
157 struct Tool {
158  /// Short name of the tool.
159  const char* name;
160 
161  /// Description (shown in "-t list").
162  const char* desc;
163 
164  /// When to run the tool.
165  enum {
166  /// Run after parsing the command-line flags and potentially changing
167  /// the current working directory (as early as possible).
168  RUN_AFTER_FLAGS,
169 
170  /// Run after loading build.ninja.
171  RUN_AFTER_LOAD,
172 
173  /// Run after loading the build/deps logs.
174  RUN_AFTER_LOGS,
175  } when;
176 
177  /// Implementation of the tool.
178  NinjaMain::ToolFunc func;
179 };
180 
181 /// Print usage information.
182 void Usage(const BuildConfig& config) {
183  fprintf(stderr,
184 "usage: ninja [options] [targets...]\n"
185 "\n"
186 "if targets are unspecified, builds the 'default' target (see manual).\n"
187 "\n"
188 "options:\n"
189 " --version print ninja version (\"%s\")\n"
190 "\n"
191 " -C DIR change to DIR before doing anything else\n"
192 " -f FILE specify input build file [default=build.ninja]\n"
193 "\n"
194 " -j N run N jobs in parallel [default=%d, derived from CPUs available]\n"
195 " -l N do not start new jobs if the load average is greater than N\n"
196 " -k N keep going until N jobs fail [default=1]\n"
197 " -n dry run (don't run commands but act like they succeeded)\n"
198 " -v show all command lines while building\n"
199 "\n"
200 " -d MODE enable debugging (use -d list to list modes)\n"
201 " -t TOOL run a subtool (use -t list to list subtools)\n"
202 " terminates toplevel options; further flags are passed to the tool\n",
203  kNinjaVersion, config.parallelism);
204 }
205 
206 /// Choose a default value for the -j (parallelism) flag.
207 int GuessParallelism() {
208  switch (int processors = GetProcessorCount()) {
209  case 0:
210  case 1:
211  return 2;
212  case 2:
213  return 3;
214  default:
215  return processors + 2;
216  }
217 }
218 
219 /// An implementation of ManifestParser::FileReader that actually reads
220 /// the file.
221 struct RealFileReader : public ManifestParser::FileReader {
222  virtual bool ReadFile(const string& path, string* content, string* err) {
223  return ::ReadFile(path, content, err) == 0;
224  }
225 };
226 
227 /// Rebuild the build manifest, if necessary.
228 /// Returns true if the manifest was rebuilt.
229 bool NinjaMain::RebuildManifest(const char* input_file, string* err) {
230  string path = input_file;
231  unsigned int slash_bits; // Unused because this path is only used for lookup.
232  if (!CanonicalizePath(&path, &slash_bits, err))
233  return false;
234  Node* node = state_.LookupNode(path);
235  if (!node)
236  return false;
237 
238  Builder builder(&state_, config_, &build_log_, &deps_log_, &disk_interface_);
239  if (!builder.AddTarget(node, err))
240  return false;
241 
242  if (builder.AlreadyUpToDate())
243  return false; // Not an error, but we didn't rebuild.
244  if (!builder.Build(err))
245  return false;
246 
247  // The manifest was only rebuilt if it is now dirty (it may have been cleaned
248  // by a restat).
249  return node->dirty();
250 }
251 
252 Node* NinjaMain::CollectTarget(const char* cpath, string* err) {
253  string path = cpath;
254  unsigned int slash_bits; // Unused because this path is only used for lookup.
255  if (!CanonicalizePath(&path, &slash_bits, err))
256  return NULL;
257 
258  // Special syntax: "foo.cc^" means "the first output of foo.cc".
259  bool first_dependent = false;
260  if (!path.empty() && path[path.size() - 1] == '^') {
261  path.resize(path.size() - 1);
262  first_dependent = true;
263  }
264 
265  Node* node = state_.LookupNode(path);
266  if (node) {
267  if (first_dependent) {
268  if (node->out_edges().empty()) {
269  *err = "'" + path + "' has no out edge";
270  return NULL;
271  }
272  Edge* edge = node->out_edges()[0];
273  if (edge->outputs_.empty()) {
274  edge->Dump();
275  Fatal("edge has no outputs");
276  }
277  node = edge->outputs_[0];
278  }
279  return node;
280  } else {
281  *err = "unknown target '" + path + "'";
282 
283  if (path == "clean") {
284  *err += ", did you mean 'ninja -t clean'?";
285  } else if (path == "help") {
286  *err += ", did you mean 'ninja -h'?";
287  } else {
288  Node* suggestion = state_.SpellcheckNode(path);
289  if (suggestion) {
290  *err += ", did you mean '" + suggestion->path() + "'?";
291  }
292  }
293  return NULL;
294  }
295 }
296 
297 bool NinjaMain::CollectTargetsFromArgs(int argc, char* argv[],
298  vector<Node*>* targets, string* err) {
299  if (argc == 0) {
300  *targets = state_.DefaultNodes(err);
301  return err->empty();
302  }
303 
304  for (int i = 0; i < argc; ++i) {
305  Node* node = CollectTarget(argv[i], err);
306  if (node == NULL)
307  return false;
308  targets->push_back(node);
309  }
310  return true;
311 }
312 
313 int NinjaMain::ToolGraph(int argc, char* argv[]) {
314  vector<Node*> nodes;
315  string err;
316  if (!CollectTargetsFromArgs(argc, argv, &nodes, &err)) {
317  Error("%s", err.c_str());
318  return 1;
319  }
320 
321  GraphViz graph;
322  graph.Start();
323  for (vector<Node*>::const_iterator n = nodes.begin(); n != nodes.end(); ++n)
324  graph.AddTarget(*n);
325  graph.Finish();
326 
327  return 0;
328 }
329 
330 int NinjaMain::ToolQuery(int argc, char* argv[]) {
331  if (argc == 0) {
332  Error("expected a target to query");
333  return 1;
334  }
335 
336  for (int i = 0; i < argc; ++i) {
337  string err;
338  Node* node = CollectTarget(argv[i], &err);
339  if (!node) {
340  Error("%s", err.c_str());
341  return 1;
342  }
343 
344  printf("%s:\n", node->path().c_str());
345  if (Edge* edge = node->in_edge()) {
346  printf(" input: %s\n", edge->rule_->name().c_str());
347  for (int in = 0; in < (int)edge->inputs_.size(); in++) {
348  const char* label = "";
349  if (edge->is_implicit(in))
350  label = "| ";
351  else if (edge->is_order_only(in))
352  label = "|| ";
353  printf(" %s%s\n", label, edge->inputs_[in]->path().c_str());
354  }
355  }
356  printf(" outputs:\n");
357  for (vector<Edge*>::const_iterator edge = node->out_edges().begin();
358  edge != node->out_edges().end(); ++edge) {
359  for (vector<Node*>::iterator out = (*edge)->outputs_.begin();
360  out != (*edge)->outputs_.end(); ++out) {
361  printf(" %s\n", (*out)->path().c_str());
362  }
363  }
364  }
365  return 0;
366 }
367 
368 #if defined(NINJA_HAVE_BROWSE)
369 int NinjaMain::ToolBrowse(int argc, char* argv[]) {
370  if (argc < 1) {
371  Error("expected a target to browse");
372  return 1;
373  }
374  RunBrowsePython(&state_, ninja_command_, argv[0]);
375  // If we get here, the browse failed.
376  return 1;
377 }
378 #endif // _WIN32
379 
380 #if defined(_MSC_VER)
381 int NinjaMain::ToolMSVC(int argc, char* argv[]) {
382  // Reset getopt: push one argument onto the front of argv, reset optind.
383  argc++;
384  argv--;
385  optind = 0;
386  return MSVCHelperMain(argc, argv);
387 }
388 #endif
389 
390 int ToolTargetsList(const vector<Node*>& nodes, int depth, int indent) {
391  for (vector<Node*>::const_iterator n = nodes.begin();
392  n != nodes.end();
393  ++n) {
394  for (int i = 0; i < indent; ++i)
395  printf(" ");
396  const char* target = (*n)->path().c_str();
397  if ((*n)->in_edge()) {
398  printf("%s: %s\n", target, (*n)->in_edge()->rule_->name().c_str());
399  if (depth > 1 || depth <= 0)
400  ToolTargetsList((*n)->in_edge()->inputs_, depth - 1, indent + 1);
401  } else {
402  printf("%s\n", target);
403  }
404  }
405  return 0;
406 }
407 
408 int ToolTargetsSourceList(State* state) {
409  for (vector<Edge*>::iterator e = state->edges_.begin();
410  e != state->edges_.end(); ++e) {
411  for (vector<Node*>::iterator inps = (*e)->inputs_.begin();
412  inps != (*e)->inputs_.end(); ++inps) {
413  if (!(*inps)->in_edge())
414  printf("%s\n", (*inps)->path().c_str());
415  }
416  }
417  return 0;
418 }
419 
420 int ToolTargetsList(State* state, const string& rule_name) {
421  set<string> rules;
422 
423  // Gather the outputs.
424  for (vector<Edge*>::iterator e = state->edges_.begin();
425  e != state->edges_.end(); ++e) {
426  if ((*e)->rule_->name() == rule_name) {
427  for (vector<Node*>::iterator out_node = (*e)->outputs_.begin();
428  out_node != (*e)->outputs_.end(); ++out_node) {
429  rules.insert((*out_node)->path());
430  }
431  }
432  }
433 
434  // Print them.
435  for (set<string>::const_iterator i = rules.begin();
436  i != rules.end(); ++i) {
437  printf("%s\n", (*i).c_str());
438  }
439 
440  return 0;
441 }
442 
443 int ToolTargetsList(State* state) {
444  for (vector<Edge*>::iterator e = state->edges_.begin();
445  e != state->edges_.end(); ++e) {
446  for (vector<Node*>::iterator out_node = (*e)->outputs_.begin();
447  out_node != (*e)->outputs_.end(); ++out_node) {
448  printf("%s: %s\n",
449  (*out_node)->path().c_str(),
450  (*e)->rule_->name().c_str());
451  }
452  }
453  return 0;
454 }
455 
456 int NinjaMain::ToolDeps(int argc, char** argv) {
457  vector<Node*> nodes;
458  if (argc == 0) {
459  for (vector<Node*>::const_iterator ni = deps_log_.nodes().begin();
460  ni != deps_log_.nodes().end(); ++ni) {
461  if (deps_log_.IsDepsEntryLiveFor(*ni))
462  nodes.push_back(*ni);
463  }
464  } else {
465  string err;
466  if (!CollectTargetsFromArgs(argc, argv, &nodes, &err)) {
467  Error("%s", err.c_str());
468  return 1;
469  }
470  }
471 
472  RealDiskInterface disk_interface;
473  for (vector<Node*>::iterator it = nodes.begin(), end = nodes.end();
474  it != end; ++it) {
475  DepsLog::Deps* deps = deps_log_.GetDeps(*it);
476  if (!deps) {
477  printf("%s: deps not found\n", (*it)->path().c_str());
478  continue;
479  }
480 
481  TimeStamp mtime = disk_interface.Stat((*it)->path());
482  printf("%s: #deps %d, deps mtime %d (%s)\n",
483  (*it)->path().c_str(), deps->node_count, deps->mtime,
484  (!mtime || mtime > deps->mtime ? "STALE":"VALID"));
485  for (int i = 0; i < deps->node_count; ++i)
486  printf(" %s\n", deps->nodes[i]->path().c_str());
487  printf("\n");
488  }
489 
490  return 0;
491 }
492 
493 int NinjaMain::ToolTargets(int argc, char* argv[]) {
494  int depth = 1;
495  if (argc >= 1) {
496  string mode = argv[0];
497  if (mode == "rule") {
498  string rule;
499  if (argc > 1)
500  rule = argv[1];
501  if (rule.empty())
502  return ToolTargetsSourceList(&state_);
503  else
504  return ToolTargetsList(&state_, rule);
505  } else if (mode == "depth") {
506  if (argc > 1)
507  depth = atoi(argv[1]);
508  } else if (mode == "all") {
509  return ToolTargetsList(&state_);
510  } else {
511  const char* suggestion =
512  SpellcheckString(mode.c_str(), "rule", "depth", "all", NULL);
513  if (suggestion) {
514  Error("unknown target tool mode '%s', did you mean '%s'?",
515  mode.c_str(), suggestion);
516  } else {
517  Error("unknown target tool mode '%s'", mode.c_str());
518  }
519  return 1;
520  }
521  }
522 
523  string err;
524  vector<Node*> root_nodes = state_.RootNodes(&err);
525  if (err.empty()) {
526  return ToolTargetsList(root_nodes, depth, 0);
527  } else {
528  Error("%s", err.c_str());
529  return 1;
530  }
531 }
532 
533 void PrintCommands(Edge* edge, set<Edge*>* seen) {
534  if (!edge)
535  return;
536  if (!seen->insert(edge).second)
537  return;
538 
539  for (vector<Node*>::iterator in = edge->inputs_.begin();
540  in != edge->inputs_.end(); ++in)
541  PrintCommands((*in)->in_edge(), seen);
542 
543  if (!edge->is_phony())
544  puts(edge->EvaluateCommand().c_str());
545 }
546 
547 int NinjaMain::ToolCommands(int argc, char* argv[]) {
548  vector<Node*> nodes;
549  string err;
550  if (!CollectTargetsFromArgs(argc, argv, &nodes, &err)) {
551  Error("%s", err.c_str());
552  return 1;
553  }
554 
555  set<Edge*> seen;
556  for (vector<Node*>::iterator in = nodes.begin(); in != nodes.end(); ++in)
557  PrintCommands((*in)->in_edge(), &seen);
558 
559  return 0;
560 }
561 
562 int NinjaMain::ToolClean(int argc, char* argv[]) {
563  // The clean tool uses getopt, and expects argv[0] to contain the name of
564  // the tool, i.e. "clean".
565  argc++;
566  argv--;
567 
568  bool generator = false;
569  bool clean_rules = false;
570 
571  optind = 1;
572  int opt;
573  while ((opt = getopt(argc, argv, const_cast<char*>("hgr"))) != -1) {
574  switch (opt) {
575  case 'g':
576  generator = true;
577  break;
578  case 'r':
579  clean_rules = true;
580  break;
581  case 'h':
582  default:
583  printf("usage: ninja -t clean [options] [targets]\n"
584 "\n"
585 "options:\n"
586 " -g also clean files marked as ninja generator output\n"
587 " -r interpret targets as a list of rules to clean instead\n"
588  );
589  return 1;
590  }
591  }
592  argv += optind;
593  argc -= optind;
594 
595  if (clean_rules && argc == 0) {
596  Error("expected a rule to clean");
597  return 1;
598  }
599 
600  Cleaner cleaner(&state_, config_);
601  if (argc >= 1) {
602  if (clean_rules)
603  return cleaner.CleanRules(argc, argv);
604  else
605  return cleaner.CleanTargets(argc, argv);
606  } else {
607  return cleaner.CleanAll(generator);
608  }
609 }
610 
611 void EncodeJSONString(const char *str) {
612  while (*str) {
613  if (*str == '"' || *str == '\\')
614  putchar('\\');
615  putchar(*str);
616  str++;
617  }
618 }
619 
620 int NinjaMain::ToolCompilationDatabase(int argc, char* argv[]) {
621  bool first = true;
622  vector<char> cwd;
623 
624  do {
625  cwd.resize(cwd.size() + 1024);
626  errno = 0;
627  } while (!getcwd(&cwd[0], cwd.size()) && errno == ERANGE);
628  if (errno != 0 && errno != ERANGE) {
629  Error("cannot determine working directory: %s", strerror(errno));
630  return 1;
631  }
632 
633  putchar('[');
634  for (vector<Edge*>::iterator e = state_.edges_.begin();
635  e != state_.edges_.end(); ++e) {
636  if ((*e)->inputs_.empty())
637  continue;
638  for (int i = 0; i != argc; ++i) {
639  if ((*e)->rule_->name() == argv[i]) {
640  if (!first)
641  putchar(',');
642 
643  printf("\n {\n \"directory\": \"");
644  EncodeJSONString(&cwd[0]);
645  printf("\",\n \"command\": \"");
646  EncodeJSONString((*e)->EvaluateCommand().c_str());
647  printf("\",\n \"file\": \"");
648  EncodeJSONString((*e)->inputs_[0]->path().c_str());
649  printf("\"\n }");
650 
651  first = false;
652  }
653  }
654  }
655 
656  puts("\n]");
657  return 0;
658 }
659 
660 int NinjaMain::ToolRecompact(int argc, char* argv[]) {
661  if (!EnsureBuildDirExists())
662  return 1;
663 
664  if (!OpenBuildLog(/*recompact_only=*/true) ||
665  !OpenDepsLog(/*recompact_only=*/true))
666  return 1;
667 
668  return 0;
669 }
670 
671 int NinjaMain::ToolUrtle(int argc, char** argv) {
672  // RLE encoded.
673  const char* urtle =
674 " 13 ,3;2!2;\n8 ,;<11!;\n5 `'<10!(2`'2!\n11 ,6;, `\\. `\\9 .,c13$ec,.\n6 "
675 ",2;11!>; `. ,;!2> .e8$2\".2 \"?7$e.\n <:<8!'` 2.3,.2` ,3!' ;,(?7\";2!2'<"
676 "; `?6$PF ,;,\n2 `'4!8;<!3'`2 3! ;,`'2`2'3!;4!`2.`!;2 3,2 .<!2'`).\n5 3`5"
677 "'2`9 `!2 `4!><3;5! J2$b,`!>;2!:2!`,d?b`!>\n26 `'-;,(<9!> $F3 )3.:!.2 d\""
678 "2 ) !>\n30 7`2'<3!- \"=-='5 .2 `2-=\",!>\n25 .ze9$er2 .,cd16$bc.'\n22 .e"
679 "14$,26$.\n21 z45$c .\n20 J50$c\n20 14$P\"`?34$b\n20 14$ dbc `2\"?22$?7$c"
680 "\n20 ?18$c.6 4\"8?4\" c8$P\n9 .2,.8 \"20$c.3 ._14 J9$\n .2,2c9$bec,.2 `?"
681 "21$c.3`4%,3%,3 c8$P\"\n22$c2 2\"?21$bc2,.2` .2,c7$P2\",cb\n23$b bc,.2\"2"
682 "?14$2F2\"5?2\",J5$P\" ,zd3$\n24$ ?$3?%3 `2\"2?12$bcucd3$P3\"2 2=7$\n23$P"
683 "\" ,3;<5!>2;,. `4\"6?2\"2 ,9;, `\"?2$\n";
684  int count = 0;
685  for (const char* p = urtle; *p; p++) {
686  if ('0' <= *p && *p <= '9') {
687  count = count*10 + *p - '0';
688  } else {
689  for (int i = 0; i < std::max(count, 1); ++i)
690  printf("%c", *p);
691  count = 0;
692  }
693  }
694  return 0;
695 }
696 
697 /// Find the function to execute for \a tool_name and return it via \a func.
698 /// Returns a Tool, or NULL if Ninja should exit.
699 const Tool* ChooseTool(const string& tool_name) {
700  static const Tool kTools[] = {
701 #if defined(NINJA_HAVE_BROWSE)
702  { "browse", "browse dependency graph in a web browser",
703  Tool::RUN_AFTER_LOAD, &NinjaMain::ToolBrowse },
704 #endif
705 #if defined(_MSC_VER)
706  { "msvc", "build helper for MSVC cl.exe (EXPERIMENTAL)",
707  Tool::RUN_AFTER_FLAGS, &NinjaMain::ToolMSVC },
708 #endif
709  { "clean", "clean built files",
710  Tool::RUN_AFTER_LOAD, &NinjaMain::ToolClean },
711  { "commands", "list all commands required to rebuild given targets",
712  Tool::RUN_AFTER_LOAD, &NinjaMain::ToolCommands },
713  { "deps", "show dependencies stored in the deps log",
714  Tool::RUN_AFTER_LOGS, &NinjaMain::ToolDeps },
715  { "graph", "output graphviz dot file for targets",
716  Tool::RUN_AFTER_LOAD, &NinjaMain::ToolGraph },
717  { "query", "show inputs/outputs for a path",
718  Tool::RUN_AFTER_LOGS, &NinjaMain::ToolQuery },
719  { "targets", "list targets by their rule or depth in the DAG",
720  Tool::RUN_AFTER_LOAD, &NinjaMain::ToolTargets },
721  { "compdb", "dump JSON compilation database to stdout",
722  Tool::RUN_AFTER_LOAD, &NinjaMain::ToolCompilationDatabase },
723  { "recompact", "recompacts ninja-internal data structures",
724  Tool::RUN_AFTER_LOAD, &NinjaMain::ToolRecompact },
725  { "urtle", NULL,
726  Tool::RUN_AFTER_FLAGS, &NinjaMain::ToolUrtle },
727  { NULL, NULL, Tool::RUN_AFTER_FLAGS, NULL }
728  };
729 
730  if (tool_name == "list") {
731  printf("ninja subtools:\n");
732  for (const Tool* tool = &kTools[0]; tool->name; ++tool) {
733  if (tool->desc)
734  printf("%10s %s\n", tool->name, tool->desc);
735  }
736  return NULL;
737  }
738 
739  for (const Tool* tool = &kTools[0]; tool->name; ++tool) {
740  if (tool->name == tool_name)
741  return tool;
742  }
743 
744  vector<const char*> words;
745  for (const Tool* tool = &kTools[0]; tool->name; ++tool)
746  words.push_back(tool->name);
747  const char* suggestion = SpellcheckStringV(tool_name, words);
748  if (suggestion) {
749  Fatal("unknown tool '%s', did you mean '%s'?",
750  tool_name.c_str(), suggestion);
751  } else {
752  Fatal("unknown tool '%s'", tool_name.c_str());
753  }
754  return NULL; // Not reached.
755 }
756 
757 /// Enable a debugging mode. Returns false if Ninja should exit instead
758 /// of continuing.
759 bool DebugEnable(const string& name) {
760  if (name == "list") {
761  printf("debugging modes:\n"
762 " stats print operation counts/timing info\n"
763 " explain explain what caused a command to execute\n"
764 " keeprsp don't delete @response files on success\n"
765 #ifdef _WIN32
766 " nostatcache don't batch stat() calls per directory and cache them\n"
767 #endif
768 "multiple modes can be enabled via -d FOO -d BAR\n");
769  return false;
770  } else if (name == "stats") {
771  g_metrics = new Metrics;
772  return true;
773  } else if (name == "explain") {
774  g_explaining = true;
775  return true;
776  } else if (name == "keeprsp") {
777  g_keep_rsp = true;
778  return true;
779  } else if (name == "nostatcache") {
780  g_experimental_statcache = false;
781  return true;
782  } else {
783  const char* suggestion =
784  SpellcheckString(name.c_str(), "stats", "explain", "keeprsp",
785  "nostatcache", NULL);
786  if (suggestion) {
787  Error("unknown debug setting '%s', did you mean '%s'?",
788  name.c_str(), suggestion);
789  } else {
790  Error("unknown debug setting '%s'", name.c_str());
791  }
792  return false;
793  }
794 }
795 
796 bool NinjaMain::OpenBuildLog(bool recompact_only) {
797  string log_path = ".ninja_log";
798  if (!build_dir_.empty())
799  log_path = build_dir_ + "/" + log_path;
800 
801  string err;
802  if (!build_log_.Load(log_path, &err)) {
803  Error("loading build log %s: %s", log_path.c_str(), err.c_str());
804  return false;
805  }
806  if (!err.empty()) {
807  // Hack: Load() can return a warning via err by returning true.
808  Warning("%s", err.c_str());
809  err.clear();
810  }
811 
812  if (recompact_only) {
813  bool success = build_log_.Recompact(log_path, *this, &err);
814  if (!success)
815  Error("failed recompaction: %s", err.c_str());
816  return success;
817  }
818 
819  if (!config_.dry_run) {
820  if (!build_log_.OpenForWrite(log_path, *this, &err)) {
821  Error("opening build log: %s", err.c_str());
822  return false;
823  }
824  }
825 
826  return true;
827 }
828 
829 /// Open the deps log: load it, then open for writing.
830 /// @return false on error.
831 bool NinjaMain::OpenDepsLog(bool recompact_only) {
832  string path = ".ninja_deps";
833  if (!build_dir_.empty())
834  path = build_dir_ + "/" + path;
835 
836  string err;
837  if (!deps_log_.Load(path, &state_, &err)) {
838  Error("loading deps log %s: %s", path.c_str(), err.c_str());
839  return false;
840  }
841  if (!err.empty()) {
842  // Hack: Load() can return a warning via err by returning true.
843  Warning("%s", err.c_str());
844  err.clear();
845  }
846 
847  if (recompact_only) {
848  bool success = deps_log_.Recompact(path, &err);
849  if (!success)
850  Error("failed recompaction: %s", err.c_str());
851  return success;
852  }
853 
854  if (!config_.dry_run) {
855  if (!deps_log_.OpenForWrite(path, &err)) {
856  Error("opening deps log: %s", err.c_str());
857  return false;
858  }
859  }
860 
861  return true;
862 }
863 
864 void NinjaMain::DumpMetrics() {
865  g_metrics->Report();
866 
867  printf("\n");
868  int count = (int)state_.paths_.size();
869  int buckets = (int)state_.paths_.bucket_count();
870  printf("path->node hash load %.2f (%d entries / %d buckets)\n",
871  count / (double) buckets, count, buckets);
872 }
873 
874 bool NinjaMain::EnsureBuildDirExists() {
875  build_dir_ = state_.bindings_.LookupVariable("builddir");
876  if (!build_dir_.empty() && !config_.dry_run) {
877  if (!disk_interface_.MakeDirs(build_dir_ + "/.") && errno != EEXIST) {
878  Error("creating build directory %s: %s",
879  build_dir_.c_str(), strerror(errno));
880  return false;
881  }
882  }
883  return true;
884 }
885 
886 int NinjaMain::RunBuild(int argc, char** argv) {
887  string err;
888  vector<Node*> targets;
889  if (!CollectTargetsFromArgs(argc, argv, &targets, &err)) {
890  Error("%s", err.c_str());
891  return 1;
892  }
893 
894  disk_interface_.AllowStatCache(g_experimental_statcache);
895 
896  Builder builder(&state_, config_, &build_log_, &deps_log_, &disk_interface_);
897  for (size_t i = 0; i < targets.size(); ++i) {
898  if (!builder.AddTarget(targets[i], &err)) {
899  if (!err.empty()) {
900  Error("%s", err.c_str());
901  return 1;
902  } else {
903  // Added a target that is already up-to-date; not really
904  // an error.
905  }
906  }
907  }
908 
909  // Make sure restat rules do not see stale timestamps.
910  disk_interface_.AllowStatCache(false);
911 
912  if (builder.AlreadyUpToDate()) {
913  printf("ninja: no work to do.\n");
914  return 0;
915  }
916 
917  if (!builder.Build(&err)) {
918  printf("ninja: build stopped: %s.\n", err.c_str());
919  if (err.find("interrupted by user") != string::npos) {
920  return 2;
921  }
922  return 1;
923  }
924 
925  return 0;
926 }
927 
928 #ifdef _MSC_VER
929 
930 /// This handler processes fatal crashes that you can't catch
931 /// Test example: C++ exception in a stack-unwind-block
932 /// Real-world example: ninja launched a compiler to process a tricky
933 /// C++ input file. The compiler got itself into a state where it
934 /// generated 3 GB of output and caused ninja to crash.
935 void TerminateHandler() {
936  CreateWin32MiniDump(NULL);
937  Fatal("terminate handler called");
938 }
939 
940 /// On Windows, we want to prevent error dialogs in case of exceptions.
941 /// This function handles the exception, and writes a minidump.
942 int ExceptionFilter(unsigned int code, struct _EXCEPTION_POINTERS *ep) {
943  Error("exception: 0x%X", code); // e.g. EXCEPTION_ACCESS_VIOLATION
944  fflush(stderr);
945  CreateWin32MiniDump(ep);
946  return EXCEPTION_EXECUTE_HANDLER;
947 }
948 
949 #endif // _MSC_VER
950 
951 /// Parse argv for command-line options.
952 /// Returns an exit code, or -1 if Ninja should continue.
953 int ReadFlags(int* argc, char*** argv,
954  Options* options, BuildConfig* config) {
955  config->parallelism = GuessParallelism();
956 
957  enum { OPT_VERSION = 1 };
958  const option kLongOptions[] = {
959  { "help", no_argument, NULL, 'h' },
960  { "version", no_argument, NULL, OPT_VERSION },
961  { NULL, 0, NULL, 0 }
962  };
963 
964  int opt;
965  while (!options->tool &&
966  (opt = getopt_long(*argc, *argv, "d:f:j:k:l:nt:vC:h", kLongOptions,
967  NULL)) != -1) {
968  switch (opt) {
969  case 'd':
970  if (!DebugEnable(optarg))
971  return 1;
972  break;
973  case 'f':
974  options->input_file = optarg;
975  break;
976  case 'j': {
977  char* end;
978  int value = strtol(optarg, &end, 10);
979  if (*end != 0 || value <= 0)
980  Fatal("invalid -j parameter");
981  config->parallelism = value;
982  break;
983  }
984  case 'k': {
985  char* end;
986  int value = strtol(optarg, &end, 10);
987  if (*end != 0)
988  Fatal("-k parameter not numeric; did you mean -k 0?");
989 
990  // We want to go until N jobs fail, which means we should allow
991  // N failures and then stop. For N <= 0, INT_MAX is close enough
992  // to infinite for most sane builds.
993  config->failures_allowed = value > 0 ? value : INT_MAX;
994  break;
995  }
996  case 'l': {
997  char* end;
998  double value = strtod(optarg, &end);
999  if (end == optarg)
1000  Fatal("-l parameter not numeric: did you mean -l 0.0?");
1001  config->max_load_average = value;
1002  break;
1003  }
1004  case 'n':
1005  config->dry_run = true;
1006  break;
1007  case 't':
1008  options->tool = ChooseTool(optarg);
1009  if (!options->tool)
1010  return 0;
1011  break;
1012  case 'v':
1013  config->verbosity = BuildConfig::VERBOSE;
1014  break;
1015  case 'C':
1016  options->working_dir = optarg;
1017  break;
1018  case OPT_VERSION:
1019  printf("%s\n", kNinjaVersion);
1020  return 0;
1021  case 'h':
1022  default:
1023  Usage(*config);
1024  return 1;
1025  }
1026  }
1027  *argv += optind;
1028  *argc -= optind;
1029 
1030  return -1;
1031 }
1032 
1033 int real_main(int argc, char** argv) {
1034  BuildConfig config;
1035  Options options = {};
1036  options.input_file = "build.ninja";
1037 
1038  setvbuf(stdout, NULL, _IOLBF, BUFSIZ);
1039  const char* ninja_command = argv[0];
1040 
1041  int exit_code = ReadFlags(&argc, &argv, &options, &config);
1042  if (exit_code >= 0)
1043  return exit_code;
1044 
1045  if (options.working_dir) {
1046  // The formatting of this string, complete with funny quotes, is
1047  // so Emacs can properly identify that the cwd has changed for
1048  // subsequent commands.
1049  // Don't print this if a tool is being used, so that tool output
1050  // can be piped into a file without this string showing up.
1051  if (!options.tool)
1052  printf("ninja: Entering directory `%s'\n", options.working_dir);
1053  if (chdir(options.working_dir) < 0) {
1054  Fatal("chdir to '%s' - %s", options.working_dir, strerror(errno));
1055  }
1056  }
1057 
1058  if (options.tool && options.tool->when == Tool::RUN_AFTER_FLAGS) {
1059  // None of the RUN_AFTER_FLAGS actually use a NinjaMain, but it's needed
1060  // by other tools.
1061  NinjaMain ninja(ninja_command, config);
1062  return (ninja.*options.tool->func)(argc, argv);
1063  }
1064 
1065  // The build can take up to 2 passes: one to rebuild the manifest, then
1066  // another to build the desired target.
1067  for (int cycle = 0; cycle < 2; ++cycle) {
1068  NinjaMain ninja(ninja_command, config);
1069 
1070  RealFileReader file_reader;
1071  ManifestParser parser(&ninja.state_, &file_reader);
1072  string err;
1073  if (!parser.Load(options.input_file, &err)) {
1074  Error("%s", err.c_str());
1075  return 1;
1076  }
1077 
1078  if (options.tool && options.tool->when == Tool::RUN_AFTER_LOAD)
1079  return (ninja.*options.tool->func)(argc, argv);
1080 
1081  if (!ninja.EnsureBuildDirExists())
1082  return 1;
1083 
1084  if (!ninja.OpenBuildLog() || !ninja.OpenDepsLog())
1085  return 1;
1086 
1087  if (options.tool && options.tool->when == Tool::RUN_AFTER_LOGS)
1088  return (ninja.*options.tool->func)(argc, argv);
1089 
1090  // The first time through, attempt to rebuild the manifest before
1091  // building anything else.
1092  if (cycle == 0) {
1093  if (ninja.RebuildManifest(options.input_file, &err)) {
1094  // Start the build over with the new manifest.
1095  continue;
1096  } else if (!err.empty()) {
1097  Error("rebuilding '%s': %s", options.input_file, err.c_str());
1098  return 1;
1099  }
1100  }
1101 
1102  int result = ninja.RunBuild(argc, argv);
1103  if (g_metrics)
1104  ninja.DumpMetrics();
1105  return result;
1106  }
1107 
1108  return 1; // Shouldn't be reached.
1109 }
1110 
1111 } // anonymous namespace
1112 
1113 int main(int argc, char** argv) {
1114 #if defined(_MSC_VER)
1115  // Set a handler to catch crashes not caught by the __try..__except
1116  // block (e.g. an exception in a stack-unwind-block).
1117  set_terminate(TerminateHandler);
1118  __try {
1119  // Running inside __try ... __except suppresses any Windows error
1120  // dialogs for errors such as bad_alloc.
1121  return real_main(argc, argv);
1122  }
1123  __except(ExceptionFilter(GetExceptionCode(), GetExceptionInformation())) {
1124  // Common error situations return exitCode=1. 2 was chosen to
1125  // indicate a more serious problem.
1126  return 2;
1127  }
1128 #else
1129  return real_main(argc, argv);
1130 #endif
1131 }
#define no_argument
Definition: getopt.h:7
bool is_phony() const
Definition: graph.cc:323
void Report()
Print a summary report to stdout.
Definition: metrics.cc:101
virtual bool ReadFile(const string &path, string *content, string *err)=0
Verbosity verbosity
Definition: build.h:133
const char * SpellcheckString(const char *text,...)
Like SpellcheckStringV, but takes a NULL-terminated list.
Definition: util.cc:431
vector< Edge * > edges_
All the edges of the graph.
Definition: state.h:129
double max_load_average
The maximum load average we must not exceed.
Definition: build.h:139
int MSVCHelperMain(int argc, char **argv)
StringPiece represents a slice of a string whose memory is managed externally.
Definition: string_piece.h:27
Information about a node in the dependency graph: the file, whether it's dirty, mtime, etc.
Definition: graph.h:35
Edge * in_edge() const
Definition: graph.h:84
Node ** nodes
Definition: deps_log.h:83
string AsString() const
Convert the slice into a full-fledged std::string, copying the data into a new string.
Definition: string_piece.h:45
bool CanonicalizePath(string *path, unsigned int *slash_bits, string *err)
Canonicalize a path like "foo/../bar.h" into just "bar.h".
Definition: util.cc:88
void Dump(const char *prefix="") const
Definition: graph.cc:302
Metrics * g_metrics
Definition: metrics.cc:31
int TimeStamp
Definition: timestamp.h:22
An edge in the dependency graph; links between Nodes using Rules.
Definition: graph.h:146
const char * kNinjaVersion
The version number of the current Ninja release.
Definition: version.cc:21
Store a log of every command ran for every build.
Definition: build_log.h:42
bool g_explaining
Definition: debug_flags.cc:15
string EvaluateCommand(bool incl_rsp_file=false)
Expand all variables in a command and return it as a string.
Definition: graph.cc:273
bool is_order_only(size_t index)
Definition: graph.h:196
virtual bool IsPathDead(StringPiece s) const =0
Return if a given output no longer part of the build manifest.
void RunBrowsePython(State *state, const char *ninja_command, const char *initial_target)
Run in "browse" mode, which execs a Python webserver.
Definition: browse.cc:23
bool Stat(DiskInterface *disk_interface)
Return true if the file exists (mtime_ got a value).
Definition: graph.cc:30
virtual TimeStamp Stat(const string &path) const
stat() a file, returning the mtime, or 0 if missing and -1 on other errors.
vector< Node * > inputs_
Definition: graph.h:171
As build commands run they can output extra dependency information (e.g.
Definition: deps_log.h:66
Parses .ninja files.
Implementation of DiskInterface that actually hits the disk.
int parallelism
Definition: build.h:135
int failures_allowed
Definition: build.h:136
bool is_implicit(size_t index)
Definition: graph.h:192
int getopt_long(int argc, char **argv, const char *shortopts, const GETOPT_LONG_OPTION_T *longopts, int *longind)
bool dirty() const
Definition: graph.h:80
int node_count
Definition: deps_log.h:82
void Finish()
Definition: graphviz.cc:75
void Start()
Definition: graphviz.cc:68
int getopt(int argc, char **argv, char *optstring)
char * optarg
int ReadFile(const string &path, string *contents, string *err)
Read a file to a string (in text mode: with CRLF conversion on Windows).
Definition: util.cc:340
int main(int argc, char **argv)
Definition: ninja.cc:1113
const string & path() const
Definition: graph.h:74
bool g_experimental_statcache
Definition: debug_flags.cc:19
int optind
Builder wraps the build process: starting commands, updating status.
Definition: build.h:143
void Fatal(const char *msg,...)
Log a fatal message and exit.
Definition: util.cc:52
const char * SpellcheckStringV(const string &text, const vector< const char * > &words)
Given a misspelled string and a list of correct spellings, returns the closest match or NULL if there...
Definition: util.cc:412
The singleton that stores metrics and prints the report.
Definition: metrics.h:51
const Rule * rule_
Definition: graph.h:169
Runs the process of creating GraphViz .dot file output.
Definition: graphviz.h:25
int GetProcessorCount()
Definition: util.cc:497
Options (e.g. verbosity, parallelism) passed to a build.
Definition: build.h:124
Global state (file status, loaded rules) for a single run.
Definition: state.h:83
const string & name() const
Definition: graph.h:128
bool g_keep_rsp
Definition: debug_flags.cc:17
void Warning(const char *msg,...)
Log a warning message.
Definition: util.cc:70
Definition: clean.h:30
void AddTarget(Node *node)
Definition: graphviz.cc:21
bool dry_run
Definition: build.h:134
const vector< Edge * > & out_edges() const
Definition: graph.h:90
void Error(const char *msg,...)
Log an error message.
Definition: util.cc:79
Can answer questions about the manifest for the BuildLog.
Definition: build_log.h:29
vector< Node * > outputs_
Definition: graph.h:172