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