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