version 1.0.0
[platform/upstream/ninja.git] / src / ninja.cc
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 <string.h>
19 #include <sys/stat.h>
20 #include <sys/types.h>
21
22 #ifdef _WIN32
23 #include "getopt.h"
24 #include <direct.h>
25 #include <windows.h>
26 #else
27 #include <getopt.h>
28 #include <unistd.h>
29 #endif
30
31 #include "browse.h"
32 #include "build.h"
33 #include "build_log.h"
34 #include "clean.h"
35 #include "disk_interface.h"
36 #include "edit_distance.h"
37 #include "explain.h"
38 #include "graph.h"
39 #include "graphviz.h"
40 #include "manifest_parser.h"
41 #include "metrics.h"
42 #include "state.h"
43 #include "util.h"
44
45 // Defined in msvc_helper_main-win32.cc.
46 int MSVCHelperMain(int argc, char** argv);
47
48 namespace {
49
50 /// The version number of the current Ninja release.  This will always
51 /// be "git" on trunk.
52 const char* kVersion = "1.0.0";
53
54 /// Global information passed into subtools.
55 struct Globals {
56   Globals() : state(new State()) {}
57   ~Globals() {
58     delete state;
59   }
60
61   /// Deletes and recreates state so it is empty.
62   void ResetState() {
63     delete state;
64     state = new State();
65   }
66
67   /// Command line used to run Ninja.
68   const char* ninja_command;
69   /// Build configuration set from flags (e.g. parallelism).
70   BuildConfig* config;
71   /// Loaded state (rules, nodes). This is a pointer so it can be reset.
72   State* state;
73 };
74
75 /// The type of functions that are the entry points to tools (subcommands).
76 typedef int (*ToolFunc)(Globals*, int, char**);
77
78 /// Subtools, accessible via "-t foo".
79 struct Tool {
80   /// Short name of the tool.
81   const char* name;
82
83   /// Description (shown in "-t list").
84   const char* desc;
85
86   /// When to run the tool.
87   enum {
88     /// Run after parsing the command-line flags (as early as possible).
89     RUN_AFTER_FLAGS,
90
91     /// Run after loading build.ninja.
92     RUN_AFTER_LOAD,
93   } when;
94
95   /// Implementation of the tool.
96   ToolFunc func;
97 };
98
99 /// Print usage information.
100 void Usage(const BuildConfig& config) {
101   fprintf(stderr,
102 "usage: ninja [options] [targets...]\n"
103 "\n"
104 "if targets are unspecified, builds the 'default' target (see manual).\n"
105 "\n"
106 "options:\n"
107 "  --version  print ninja version (\"%s\")\n"
108 "\n"
109 "  -C DIR   change to DIR before doing anything else\n"
110 "  -f FILE  specify input build file [default=build.ninja]\n"
111 "\n"
112 "  -j N     run N jobs in parallel [default=%d]\n"
113 "  -l N     do not start new jobs if the load average is greater than N\n"
114 #ifdef _WIN32
115 "           (not yet implemented on Windows)\n"
116 #endif
117 "  -k N     keep going until N jobs fail [default=1]\n"
118 "  -n       dry run (don't run commands but act like they succeeded)\n"
119 "  -v       show all command lines while building\n"
120 "\n"
121 "  -d MODE  enable debugging (use -d list to list modes)\n"
122 "  -t TOOL  run a subtool (use -t list to list subtools)\n"
123 "    terminates toplevel options; further flags are passed to the tool\n",
124           kVersion, config.parallelism);
125 }
126
127 /// Choose a default value for the -j (parallelism) flag.
128 int GuessParallelism() {
129   switch (int processors = GetProcessorCount()) {
130   case 0:
131   case 1:
132     return 2;
133   case 2:
134     return 3;
135   default:
136     return processors + 2;
137   }
138 }
139
140 /// An implementation of ManifestParser::FileReader that actually reads
141 /// the file.
142 struct RealFileReader : public ManifestParser::FileReader {
143   bool ReadFile(const string& path, string* content, string* err) {
144     return ::ReadFile(path, content, err) == 0;
145   }
146 };
147
148 /// Rebuild the build manifest, if necessary.
149 /// Returns true if the manifest was rebuilt.
150 bool RebuildManifest(Builder* builder, const char* input_file, string* err) {
151   string path = input_file;
152   if (!CanonicalizePath(&path, err))
153     return false;
154   Node* node = builder->state_->LookupNode(path);
155   if (!node)
156     return false;
157
158   if (!builder->AddTarget(node, err))
159     return false;
160
161   if (builder->AlreadyUpToDate())
162     return false;  // Not an error, but we didn't rebuild.
163   if (!builder->Build(err))
164     return false;
165
166   // The manifest was only rebuilt if it is now dirty (it may have been cleaned
167   // by a restat).
168   return node->dirty();
169 }
170
171 bool CollectTargetsFromArgs(State* state, int argc, char* argv[],
172                             vector<Node*>* targets, string* err) {
173   if (argc == 0) {
174     *targets = state->DefaultNodes(err);
175     return err->empty();
176   }
177
178   for (int i = 0; i < argc; ++i) {
179     string path = argv[i];
180     if (!CanonicalizePath(&path, err))
181       return false;
182
183     // Special syntax: "foo.cc^" means "the first output of foo.cc".
184     bool first_dependent = false;
185     if (!path.empty() && path[path.size() - 1] == '^') {
186       path.resize(path.size() - 1);
187       first_dependent = true;
188     }
189
190     Node* node = state->LookupNode(path);
191     if (node) {
192       if (first_dependent) {
193         if (node->out_edges().empty()) {
194           *err = "'" + path + "' has no out edge";
195           return false;
196         }
197         Edge* edge = node->out_edges()[0];
198         if (edge->outputs_.empty()) {
199           edge->Dump();
200           Fatal("edge has no outputs");
201         }
202         node = edge->outputs_[0];
203       }
204       targets->push_back(node);
205     } else {
206       *err = "unknown target '" + path + "'";
207
208       if (path == "clean") {
209         *err += ", did you mean 'ninja -t clean'?";
210       } else if (path == "help") {
211         *err += ", did you mean 'ninja -h'?";
212       } else {
213         Node* suggestion = state->SpellcheckNode(path);
214         if (suggestion) {
215           *err += ", did you mean '" + suggestion->path() + "'?";
216         }
217       }
218       return false;
219     }
220   }
221   return true;
222 }
223
224 int ToolGraph(Globals* globals, int argc, char* argv[]) {
225   vector<Node*> nodes;
226   string err;
227   if (!CollectTargetsFromArgs(globals->state, argc, argv, &nodes, &err)) {
228     Error("%s", err.c_str());
229     return 1;
230   }
231
232   GraphViz graph;
233   graph.Start();
234   for (vector<Node*>::const_iterator n = nodes.begin(); n != nodes.end(); ++n)
235     graph.AddTarget(*n);
236   graph.Finish();
237
238   return 0;
239 }
240
241 int ToolQuery(Globals* globals, int argc, char* argv[]) {
242   if (argc == 0) {
243     Error("expected a target to query");
244     return 1;
245   }
246   for (int i = 0; i < argc; ++i) {
247     Node* node = globals->state->LookupNode(argv[i]);
248     if (!node) {
249       Node* suggestion = globals->state->SpellcheckNode(argv[i]);
250       if (suggestion) {
251         printf("%s unknown, did you mean %s?\n",
252                argv[i], suggestion->path().c_str());
253       } else {
254         printf("%s unknown\n", argv[i]);
255       }
256       return 1;
257     }
258
259     printf("%s:\n", argv[i]);
260     if (Edge* edge = node->in_edge()) {
261       printf("  input: %s\n", edge->rule_->name().c_str());
262       for (int in = 0; in < (int)edge->inputs_.size(); in++) {
263         const char* label = "";
264         if (edge->is_implicit(in))
265           label = "| ";
266         else if (edge->is_order_only(in))
267           label = "|| ";
268         printf("    %s%s\n", label, edge->inputs_[in]->path().c_str());
269       }
270     }
271     printf("  outputs:\n");
272     for (vector<Edge*>::const_iterator edge = node->out_edges().begin();
273          edge != node->out_edges().end(); ++edge) {
274       for (vector<Node*>::iterator out = (*edge)->outputs_.begin();
275            out != (*edge)->outputs_.end(); ++out) {
276         printf("    %s\n", (*out)->path().c_str());
277       }
278     }
279   }
280   return 0;
281 }
282
283 #if !defined(_WIN32) && !defined(NINJA_BOOTSTRAP)
284 int ToolBrowse(Globals* globals, int argc, char* argv[]) {
285   if (argc < 1) {
286     Error("expected a target to browse");
287     return 1;
288   }
289   RunBrowsePython(globals->state, globals->ninja_command, argv[0]);
290   // If we get here, the browse failed.
291   return 1;
292 }
293 #endif  // _WIN32
294
295 #if defined(WIN32)
296 int ToolMSVC(Globals* globals, int argc, char* argv[]) {
297   // Reset getopt: push one argument onto the front of argv, reset optind.
298   argc++;
299   argv--;
300   optind = 0;
301   return MSVCHelperMain(argc, argv);
302 }
303 #endif
304
305 int ToolTargetsList(const vector<Node*>& nodes, int depth, int indent) {
306   for (vector<Node*>::const_iterator n = nodes.begin();
307        n != nodes.end();
308        ++n) {
309     for (int i = 0; i < indent; ++i)
310       printf("  ");
311     const char* target = (*n)->path().c_str();
312     if ((*n)->in_edge()) {
313       printf("%s: %s\n", target, (*n)->in_edge()->rule_->name().c_str());
314       if (depth > 1 || depth <= 0)
315         ToolTargetsList((*n)->in_edge()->inputs_, depth - 1, indent + 1);
316     } else {
317       printf("%s\n", target);
318     }
319   }
320   return 0;
321 }
322
323 int ToolTargetsSourceList(State* state) {
324   for (vector<Edge*>::iterator e = state->edges_.begin();
325        e != state->edges_.end(); ++e) {
326     for (vector<Node*>::iterator inps = (*e)->inputs_.begin();
327          inps != (*e)->inputs_.end(); ++inps) {
328       if (!(*inps)->in_edge())
329         printf("%s\n", (*inps)->path().c_str());
330     }
331   }
332   return 0;
333 }
334
335 int ToolTargetsList(State* state, const string& rule_name) {
336   set<string> rules;
337
338   // Gather the outputs.
339   for (vector<Edge*>::iterator e = state->edges_.begin();
340        e != state->edges_.end(); ++e) {
341     if ((*e)->rule_->name() == rule_name) {
342       for (vector<Node*>::iterator out_node = (*e)->outputs_.begin();
343            out_node != (*e)->outputs_.end(); ++out_node) {
344         rules.insert((*out_node)->path());
345       }
346     }
347   }
348
349   // Print them.
350   for (set<string>::const_iterator i = rules.begin();
351        i != rules.end(); ++i) {
352     printf("%s\n", (*i).c_str());
353   }
354
355   return 0;
356 }
357
358 int ToolTargetsList(State* state) {
359   for (vector<Edge*>::iterator e = state->edges_.begin();
360        e != state->edges_.end(); ++e) {
361     for (vector<Node*>::iterator out_node = (*e)->outputs_.begin();
362          out_node != (*e)->outputs_.end(); ++out_node) {
363       printf("%s: %s\n",
364              (*out_node)->path().c_str(),
365              (*e)->rule_->name().c_str());
366     }
367   }
368   return 0;
369 }
370
371 int ToolTargets(Globals* globals, int argc, char* argv[]) {
372   int depth = 1;
373   if (argc >= 1) {
374     string mode = argv[0];
375     if (mode == "rule") {
376       string rule;
377       if (argc > 1)
378         rule = argv[1];
379       if (rule.empty())
380         return ToolTargetsSourceList(globals->state);
381       else
382         return ToolTargetsList(globals->state, rule);
383     } else if (mode == "depth") {
384       if (argc > 1)
385         depth = atoi(argv[1]);
386     } else if (mode == "all") {
387       return ToolTargetsList(globals->state);
388     } else {
389       const char* suggestion =
390           SpellcheckString(mode, "rule", "depth", "all", NULL);
391       if (suggestion) {
392         Error("unknown target tool mode '%s', did you mean '%s'?",
393               mode.c_str(), suggestion);
394       } else {
395         Error("unknown target tool mode '%s'", mode.c_str());
396       }
397       return 1;
398     }
399   }
400
401   string err;
402   vector<Node*> root_nodes = globals->state->RootNodes(&err);
403   if (err.empty()) {
404     return ToolTargetsList(root_nodes, depth, 0);
405   } else {
406     Error("%s", err.c_str());
407     return 1;
408   }
409 }
410
411 int ToolRules(Globals* globals, int argc, char* /* argv */[]) {
412   for (map<string, const Rule*>::iterator i = globals->state->rules_.begin();
413        i != globals->state->rules_.end(); ++i) {
414     if (i->second->description().empty()) {
415       printf("%s\n", i->first.c_str());
416     } else {
417       printf("%s: %s\n",
418              i->first.c_str(),
419              // XXX I changed it such that we don't have an easy way
420              // to get the source text anymore, so this output is
421              // unsatisfactory.  How useful is this command, anyway?
422              i->second->description().Serialize().c_str());
423     }
424   }
425   return 0;
426 }
427
428 void PrintCommands(Edge* edge, set<Edge*>* seen) {
429   if (!edge)
430     return;
431   if (!seen->insert(edge).second)
432     return;
433
434   for (vector<Node*>::iterator in = edge->inputs_.begin();
435        in != edge->inputs_.end(); ++in)
436     PrintCommands((*in)->in_edge(), seen);
437
438   if (!edge->is_phony())
439     puts(edge->EvaluateCommand().c_str());
440 }
441
442 int ToolCommands(Globals* globals, int argc, char* argv[]) {
443   vector<Node*> nodes;
444   string err;
445   if (!CollectTargetsFromArgs(globals->state, argc, argv, &nodes, &err)) {
446     Error("%s", err.c_str());
447     return 1;
448   }
449
450   set<Edge*> seen;
451   for (vector<Node*>::iterator in = nodes.begin(); in != nodes.end(); ++in)
452     PrintCommands((*in)->in_edge(), &seen);
453
454   return 0;
455 }
456
457 int ToolClean(Globals* globals, int argc, char* argv[]) {
458   // The clean tool uses getopt, and expects argv[0] to contain the name of
459   // the tool, i.e. "clean".
460   argc++;
461   argv--;
462
463   bool generator = false;
464   bool clean_rules = false;
465
466   optind = 1;
467   int opt;
468   while ((opt = getopt(argc, argv, const_cast<char*>("hgr"))) != -1) {
469     switch (opt) {
470     case 'g':
471       generator = true;
472       break;
473     case 'r':
474       clean_rules = true;
475       break;
476     case 'h':
477     default:
478       printf("usage: ninja -t clean [options] [targets]\n"
479 "\n"
480 "options:\n"
481 "  -g     also clean files marked as ninja generator output\n"
482 "  -r     interpret targets as a list of rules to clean instead\n"
483              );
484     return 1;
485     }
486   }
487   argv += optind;
488   argc -= optind;
489
490   if (clean_rules && argc == 0) {
491     Error("expected a rule to clean");
492     return 1;
493   }
494
495   Cleaner cleaner(globals->state, *globals->config);
496   if (argc >= 1) {
497     if (clean_rules)
498       return cleaner.CleanRules(argc, argv);
499     else
500       return cleaner.CleanTargets(argc, argv);
501   } else {
502     return cleaner.CleanAll(generator);
503   }
504 }
505
506 int ToolUrtle(Globals* globals, int argc, char** argv) {
507   // RLE encoded.
508   const char* urtle =
509 " 13 ,3;2!2;\n8 ,;<11!;\n5 `'<10!(2`'2!\n11 ,6;, `\\. `\\9 .,c13$ec,.\n6 "
510 ",2;11!>; `. ,;!2> .e8$2\".2 \"?7$e.\n <:<8!'` 2.3,.2` ,3!' ;,(?7\";2!2'<"
511 "; `?6$PF ,;,\n2 `'4!8;<!3'`2 3! ;,`'2`2'3!;4!`2.`!;2 3,2 .<!2'`).\n5 3`5"
512 "'2`9 `!2 `4!><3;5! J2$b,`!>;2!:2!`,d?b`!>\n26 `'-;,(<9!> $F3 )3.:!.2 d\""
513 "2 ) !>\n30 7`2'<3!- \"=-='5 .2 `2-=\",!>\n25 .ze9$er2 .,cd16$bc.'\n22 .e"
514 "14$,26$.\n21 z45$c .\n20 J50$c\n20 14$P\"`?34$b\n20 14$ dbc `2\"?22$?7$c"
515 "\n20 ?18$c.6 4\"8?4\" c8$P\n9 .2,.8 \"20$c.3 ._14 J9$\n .2,2c9$bec,.2 `?"
516 "21$c.3`4%,3%,3 c8$P\"\n22$c2 2\"?21$bc2,.2` .2,c7$P2\",cb\n23$b bc,.2\"2"
517 "?14$2F2\"5?2\",J5$P\" ,zd3$\n24$ ?$3?%3 `2\"2?12$bcucd3$P3\"2 2=7$\n23$P"
518 "\" ,3;<5!>2;,. `4\"6?2\"2 ,9;, `\"?2$\n";
519   int count = 0;
520   for (const char* p = urtle; *p; p++) {
521     if ('0' <= *p && *p <= '9') {
522       count = count*10 + *p - '0';
523     } else {
524       for (int i = 0; i < std::max(count, 1); ++i)
525         printf("%c", *p);
526       count = 0;
527     }
528   }
529   return 0;
530 }
531
532 /// Find the function to execute for \a tool_name and return it via \a func.
533 /// If there is no tool to run (e.g.: unknown tool), returns an exit code.
534 int ChooseTool(const string& tool_name, const Tool** tool_out) {
535   static const Tool kTools[] = {
536 #if !defined(_WIN32) && !defined(NINJA_BOOTSTRAP)
537     { "browse", "browse dependency graph in a web browser",
538       Tool::RUN_AFTER_LOAD, ToolBrowse },
539 #endif
540 #if defined(WIN32)
541     { "msvc", "build helper for MSVC cl.exe (EXPERIMENTAL)",
542       Tool::RUN_AFTER_FLAGS, ToolMSVC },
543 #endif
544     { "clean", "clean built files",
545       Tool::RUN_AFTER_LOAD, ToolClean },
546     { "commands", "list all commands required to rebuild given targets",
547       Tool::RUN_AFTER_LOAD, ToolCommands },
548     { "graph", "output graphviz dot file for targets",
549       Tool::RUN_AFTER_LOAD, ToolGraph },
550     { "query", "show inputs/outputs for a path",
551       Tool::RUN_AFTER_LOAD, ToolQuery },
552     { "rules",    "list all rules",
553       Tool::RUN_AFTER_LOAD, ToolRules },
554     { "targets",  "list targets by their rule or depth in the DAG",
555       Tool::RUN_AFTER_LOAD, ToolTargets },
556     { "urtle", NULL,
557       Tool::RUN_AFTER_FLAGS, ToolUrtle },
558     { NULL, NULL, Tool::RUN_AFTER_FLAGS, NULL }
559   };
560
561   if (tool_name == "list") {
562     printf("ninja subtools:\n");
563     for (const Tool* tool = &kTools[0]; tool->name; ++tool) {
564       if (tool->desc)
565         printf("%10s  %s\n", tool->name, tool->desc);
566     }
567     return 0;
568   }
569
570   for (const Tool* tool = &kTools[0]; tool->name; ++tool) {
571     if (tool->name == tool_name) {
572       *tool_out = tool;
573       return 0;
574     }
575   }
576
577   vector<const char*> words;
578   for (const Tool* tool = &kTools[0]; tool->name; ++tool)
579     words.push_back(tool->name);
580   const char* suggestion = SpellcheckStringV(tool_name, words);
581   if (suggestion) {
582     Error("unknown tool '%s', did you mean '%s'?",
583           tool_name.c_str(), suggestion);
584   } else {
585     Error("unknown tool '%s'", tool_name.c_str());
586   }
587   return 1;
588 }
589
590 /// Enable a debugging mode.  Returns false if Ninja should exit instead
591 /// of continuing.
592 bool DebugEnable(const string& name, Globals* globals) {
593   if (name == "list") {
594     printf("debugging modes:\n"
595 "  stats    print operation counts/timing info\n"
596 "  explain  explain what caused a command to execute\n"
597 "multiple modes can be enabled via -d FOO -d BAR\n");
598     return false;
599   } else if (name == "stats") {
600     g_metrics = new Metrics;
601     return true;
602   } else if (name == "explain") {
603     g_explaining = true;
604     return true;
605   } else {
606     printf("ninja: unknown debug setting '%s'\n", name.c_str());
607     return false;
608   }
609 }
610
611 bool OpenLog(BuildLog* build_log, Globals* globals,
612              DiskInterface* disk_interface) {
613   const string build_dir =
614       globals->state->bindings_.LookupVariable("builddir");
615   const char* kLogPath = ".ninja_log";
616   string log_path = kLogPath;
617   if (!build_dir.empty()) {
618     log_path = build_dir + "/" + kLogPath;
619     if (!disk_interface->MakeDirs(log_path) && errno != EEXIST) {
620       Error("creating build directory %s: %s",
621             build_dir.c_str(), strerror(errno));
622       return false;
623     }
624   }
625
626   string err;
627   if (!build_log->Load(log_path, &err)) {
628     Error("loading build log %s: %s", log_path.c_str(), err.c_str());
629     return false;
630   }
631   if (!err.empty()) {
632     // Hack: Load() can return a warning via err by returning true.
633     Warning("%s", err.c_str());
634     err.clear();
635   }
636
637   if (!globals->config->dry_run) {
638     if (!build_log->OpenForWrite(log_path, &err)) {
639       Error("opening build log: %s", err.c_str());
640       return false;
641     }
642   }
643
644   return true;
645 }
646
647 /// Dump the output requested by '-d stats'.
648 void DumpMetrics(Globals* globals) {
649   g_metrics->Report();
650
651   printf("\n");
652   int count = (int)globals->state->paths_.size();
653   int buckets = (int)globals->state->paths_.bucket_count();
654   printf("path->node hash load %.2f (%d entries / %d buckets)\n",
655          count / (double) buckets, count, buckets);
656 }
657
658 int RunBuild(Builder* builder, int argc, char** argv) {
659   string err;
660   vector<Node*> targets;
661   if (!CollectTargetsFromArgs(builder->state_, argc, argv, &targets, &err)) {
662     Error("%s", err.c_str());
663     return 1;
664   }
665
666   for (size_t i = 0; i < targets.size(); ++i) {
667     if (!builder->AddTarget(targets[i], &err)) {
668       if (!err.empty()) {
669         Error("%s", err.c_str());
670         return 1;
671       } else {
672         // Added a target that is already up-to-date; not really
673         // an error.
674       }
675     }
676   }
677
678   if (builder->AlreadyUpToDate()) {
679     printf("ninja: no work to do.\n");
680     return 0;
681   }
682
683   if (!builder->Build(&err)) {
684     printf("ninja: build stopped: %s.\n", err.c_str());
685     return 1;
686   }
687
688   return 0;
689 }
690
691 #ifdef _MSC_VER
692
693 } // anonymous namespace
694
695 // Defined in minidump-win32.cc.
696 void CreateWin32MiniDump(_EXCEPTION_POINTERS* pep);
697
698 namespace {
699
700 /// This handler processes fatal crashes that you can't catch
701 /// Test example: C++ exception in a stack-unwind-block
702 /// Real-world example: ninja launched a compiler to process a tricky
703 /// C++ input file. The compiler got itself into a state where it
704 /// generated 3 GB of output and caused ninja to crash.
705 void TerminateHandler() {
706   CreateWin32MiniDump(NULL);
707   Fatal("terminate handler called");
708 }
709
710 /// On Windows, we want to prevent error dialogs in case of exceptions.
711 /// This function handles the exception, and writes a minidump.
712 int ExceptionFilter(unsigned int code, struct _EXCEPTION_POINTERS *ep) {
713   Error("exception: 0x%X", code);  // e.g. EXCEPTION_ACCESS_VIOLATION
714   fflush(stderr);
715   CreateWin32MiniDump(ep);
716   return EXCEPTION_EXECUTE_HANDLER;
717 }
718
719 #endif  // _MSC_VER
720
721 int NinjaMain(int argc, char** argv) {
722   BuildConfig config;
723   Globals globals;
724   globals.ninja_command = argv[0];
725   globals.config = &config;
726   const char* input_file = "build.ninja";
727   const char* working_dir = NULL;
728   string tool_name;
729
730   setvbuf(stdout, NULL, _IOLBF, BUFSIZ);
731
732   config.parallelism = GuessParallelism();
733
734   enum { OPT_VERSION = 1 };
735   const option kLongOptions[] = {
736     { "help", no_argument, NULL, 'h' },
737     { "version", no_argument, NULL, OPT_VERSION },
738     { NULL, 0, NULL, 0 }
739   };
740
741   int opt;
742   while (tool_name.empty() &&
743          (opt = getopt_long(argc, argv, "d:f:hj:k:l:nt:vC:V", kLongOptions,
744                             NULL)) != -1) {
745     switch (opt) {
746       case 'd':
747         if (!DebugEnable(optarg, &globals))
748           return 1;
749         break;
750       case 'f':
751         input_file = optarg;
752         break;
753       case 'j':
754         config.parallelism = atoi(optarg);
755         break;
756       case 'l': {
757         char* end;
758         double value = strtod(optarg, &end);
759         if (end == optarg)
760           Fatal("-l parameter not numeric: did you mean -l 0.0?");
761         config.max_load_average = value;
762         break;
763       }
764       case 'k': {
765         char* end;
766         int value = strtol(optarg, &end, 10);
767         if (*end != 0)
768           Fatal("-k parameter not numeric; did you mean -k 0?");
769
770         // We want to go until N jobs fail, which means we should allow
771         // N failures and then stop.  For N <= 0, INT_MAX is close enough
772         // to infinite for most sane builds.
773         config.failures_allowed = value > 0 ? value : INT_MAX;
774         break;
775       }
776       case 'n':
777         config.dry_run = true;
778         break;
779       case 'v':
780         config.verbosity = BuildConfig::VERBOSE;
781         break;
782       case 't':
783         tool_name = optarg;
784         break;
785       case 'C':
786         working_dir = optarg;
787         break;
788       case OPT_VERSION:
789         printf("%s\n", kVersion);
790         return 0;
791       case 'h':
792       default:
793         Usage(config);
794         return 1;
795     }
796   }
797   argv += optind;
798   argc -= optind;
799
800   // If specified, select a tool as early as possible, so commands like
801   // -t list can run before we attempt to load build.ninja etc.
802   const Tool* tool = NULL;
803   if (!tool_name.empty()) {
804     int exit_code = ChooseTool(tool_name, &tool);
805     if (!tool)
806       return exit_code;
807   }
808
809   if (tool && tool->when == Tool::RUN_AFTER_FLAGS)
810     return tool->func(&globals, argc, argv);
811
812   if (working_dir) {
813     // The formatting of this string, complete with funny quotes, is
814     // so Emacs can properly identify that the cwd has changed for
815     // subsequent commands.
816     // Don't print this if a tool is being used, so that tool output
817     // can be piped into a file without this string showing up.
818     if (!tool)
819       printf("ninja: Entering directory `%s'\n", working_dir);
820     if (chdir(working_dir) < 0) {
821       Fatal("chdir to '%s' - %s", working_dir, strerror(errno));
822     }
823   }
824
825   bool rebuilt_manifest = false;
826
827 reload:
828   RealDiskInterface disk_interface;
829   RealFileReader file_reader;
830   ManifestParser parser(globals.state, &file_reader);
831   string err;
832   if (!parser.Load(input_file, &err)) {
833     Error("%s", err.c_str());
834     return 1;
835   }
836
837   if (tool && tool->when == Tool::RUN_AFTER_LOAD)
838     return tool->func(&globals, argc, argv);
839
840   BuildLog build_log;
841   if (!OpenLog(&build_log, &globals, &disk_interface))
842     return 1;
843
844   if (!rebuilt_manifest) { // Don't get caught in an infinite loop by a rebuild
845                            // target that is never up to date.
846     Builder manifest_builder(globals.state, config, &build_log,
847                              &disk_interface);
848     if (RebuildManifest(&manifest_builder, input_file, &err)) {
849       rebuilt_manifest = true;
850       globals.ResetState();
851       goto reload;
852     } else if (!err.empty()) {
853       Error("rebuilding '%s': %s", input_file, err.c_str());
854       return 1;
855     }
856   }
857
858   Builder builder(globals.state, config, &build_log, &disk_interface);
859   int result = RunBuild(&builder, argc, argv);
860   if (g_metrics)
861     DumpMetrics(&globals);
862   return result;
863 }
864
865 }  // anonymous namespace
866
867 int main(int argc, char** argv) {
868 #if !defined(NINJA_BOOTSTRAP) && defined(_MSC_VER)
869   // Set a handler to catch crashes not caught by the __try..__except
870   // block (e.g. an exception in a stack-unwind-block).
871   set_terminate(TerminateHandler);
872   __try {
873     // Running inside __try ... __except suppresses any Windows error
874     // dialogs for errors such as bad_alloc.
875     return NinjaMain(argc, argv);
876   }
877   __except(ExceptionFilter(GetExceptionCode(), GetExceptionInformation())) {
878     // Common error situations return exitCode=1. 2 was chosen to
879     // indicate a more serious problem.
880     return 2;
881   }
882 #else
883   return NinjaMain(argc, argv);
884 #endif
885 }