windows: use _WIN32 define everywhere
[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 <stdio.h>
17 #include <string.h>
18 #include <sys/stat.h>
19 #include <sys/types.h>
20
21 #if defined(__APPLE__) || defined(__FreeBSD__)
22 #include <sys/sysctl.h>
23 #elif defined(linux)
24 #include <sys/sysinfo.h>
25 #endif
26
27 #ifdef _WIN32
28 #include "getopt.h"
29 #include <direct.h>
30 #include <windows.h>
31 #else
32 #include <getopt.h>
33 #endif
34
35 #include "browse.h"
36 #include "build.h"
37 #include "build_log.h"
38 #include "clean.h"
39 #include "edit_distance.h"
40 #include "graph.h"
41 #include "graphviz.h"
42 #include "metrics.h"
43 #include "parsers.h"
44 #include "state.h"
45 #include "util.h"
46
47 namespace {
48
49 /// Global information passed into subtools.
50 struct Globals {
51   Globals() : state(new State()) {}
52   ~Globals() {
53     delete state;
54   }
55
56   /// Deletes and recreates state so it is empty.
57   void ResetState() {
58     delete state;
59     state = new State();
60   }
61
62   /// Command line used to run Ninja.
63   const char* ninja_command;
64   /// Build configuration (e.g. parallelism).
65   BuildConfig config;
66   /// Loaded state (rules, nodes). This is a pointer so it can be reset.
67   State* state;
68 };
69
70 /// Print usage information.
71 void Usage(const BuildConfig& config) {
72   fprintf(stderr,
73 "usage: ninja [options] [targets...]\n"
74 "\n"
75 "if targets are unspecified, builds the 'default' target (see manual).\n"
76 "targets are paths, with additional special syntax:\n"
77 "  'target^' means 'the first output that uses target'.\n"
78 "  example: 'ninja foo.cc^' will likely build foo.o.\n"
79 "\n"
80 "options:\n"
81 "  -C DIR   change to DIR before doing anything else\n"
82 "  -f FILE  specify input build file [default=build.ninja]\n"
83 "\n"
84 "  -j N     run N jobs in parallel [default=%d]\n"
85 "  -k N     keep going until N jobs fail [default=1]\n"
86 "  -n       dry run (don't run commands but pretend they succeeded)\n"
87 "  -v       show all command lines while building\n"
88 "\n"
89 "  -d MODE  enable debugging (use -d list to list modes)\n"
90 "  -t TOOL  run a subtool\n"
91 "    use '-t list' to list subtools.\n"
92 "    terminates toplevel options; further flags are passed to the tool.\n",
93           config.parallelism);
94 }
95
96 /// Choose a default value for the -j (parallelism) flag.
97 int GuessParallelism() {
98   int processors = 0;
99
100 #if defined(linux)
101   processors = get_nprocs();
102 #elif defined(__APPLE__) || defined(__FreeBSD__)
103   size_t processors_size = sizeof(processors);
104   int name[] = {CTL_HW, HW_NCPU};
105   if (sysctl(name, sizeof(name) / sizeof(int),
106              &processors, &processors_size,
107              NULL, 0) < 0) {
108     processors = 1;
109   }
110 #elif defined(_WIN32)
111   SYSTEM_INFO info;
112   GetSystemInfo(&info);
113   processors = info.dwNumberOfProcessors;
114 #endif
115
116   switch (processors) {
117   case 0:
118   case 1:
119     return 2;
120   case 2:
121     return 3;
122   default:
123     return processors + 2;
124   }
125 }
126
127 /// An implementation of ManifestParser::FileReader that actually reads
128 /// the file.
129 struct RealFileReader : public ManifestParser::FileReader {
130   bool ReadFile(const string& path, string* content, string* err) {
131     return ::ReadFile(path, content, err) == 0;
132   }
133 };
134
135 /// Rebuild the build manifest, if necessary.
136 /// Returns true if the manifest was rebuilt.
137 bool RebuildManifest(State* state, const BuildConfig& config,
138                      const char* input_file, string* err) {
139   string path = input_file;
140   if (!CanonicalizePath(&path, err))
141     return false;
142   Node* node = state->LookupNode(path);
143   if (!node)
144     return false;
145
146   Builder manifest_builder(state, config);
147   if (!manifest_builder.AddTarget(node, err))
148     return false;
149
150   if (manifest_builder.AlreadyUpToDate())
151     return false;  // Not an error, but we didn't rebuild.
152   return manifest_builder.Build(err);
153 }
154
155 bool CollectTargetsFromArgs(State* state, int argc, char* argv[],
156                             vector<Node*>* targets, string* err) {
157   if (argc == 0) {
158     *targets = state->DefaultNodes(err);
159     if (!err->empty())
160       return false;
161   } else {
162     for (int i = 0; i < argc; ++i) {
163       string path = argv[i];
164       if (!CanonicalizePath(&path, err))
165         return false;
166
167       // Special syntax: "foo.cc^" means "the first output of foo.cc".
168       bool first_dependent = false;
169       if (!path.empty() && path[path.size() - 1] == '^') {
170         path.resize(path.size() - 1);
171         first_dependent = true;
172       }
173
174       Node* node = state->LookupNode(path);
175       if (node) {
176         if (first_dependent) {
177           if (node->out_edges().empty()) {
178             *err = "'" + path + "' has no out edge";
179             return false;
180           }
181           Edge* edge = node->out_edges()[0];
182           if (edge->outputs_.empty()) {
183             edge->Dump();
184             Fatal("edge has no outputs");
185           }
186           node = edge->outputs_[0];
187         }
188         targets->push_back(node);
189       } else {
190         *err = "unknown target '" + path + "'";
191
192         Node* suggestion = state->SpellcheckNode(path);
193         if (suggestion) {
194           *err += ", did you mean '" + suggestion->path() + "'?";
195         }
196         return false;
197       }
198     }
199   }
200   return true;
201 }
202
203 int ToolGraph(Globals* globals, int argc, char* argv[]) {
204   vector<Node*> nodes;
205   string err;
206   if (!CollectTargetsFromArgs(globals->state, argc, argv, &nodes, &err)) {
207     Error("%s", err.c_str());
208     return 1;
209   }
210
211   GraphViz graph;
212   graph.Start();
213   for (vector<Node*>::const_iterator n = nodes.begin(); n != nodes.end(); ++n)
214     graph.AddTarget(*n);
215   graph.Finish();
216
217   return 0;
218 }
219
220 int ToolQuery(Globals* globals, int argc, char* argv[]) {
221   if (argc == 0) {
222     Error("expected a target to query");
223     return 1;
224   }
225   for (int i = 0; i < argc; ++i) {
226     Node* node = globals->state->LookupNode(argv[i]);
227     if (node) {
228       printf("%s:\n", argv[i]);
229       if (node->in_edge()) {
230         printf("  input: %s\n", node->in_edge()->rule_->name().c_str());
231         for (vector<Node*>::iterator in = node->in_edge()->inputs_.begin();
232              in != node->in_edge()->inputs_.end(); ++in) {
233           printf("    %s\n", (*in)->path().c_str());
234         }
235       }
236       for (vector<Edge*>::const_iterator edge = node->out_edges().begin();
237            edge != node->out_edges().end(); ++edge) {
238         printf("  output: %s\n", (*edge)->rule_->name().c_str());
239         for (vector<Node*>::iterator out = (*edge)->outputs_.begin();
240              out != (*edge)->outputs_.end(); ++out) {
241           printf("    %s\n", (*out)->path().c_str());
242         }
243       }
244     } else {
245       Node* suggestion = globals->state->SpellcheckNode(argv[i]);
246       if (suggestion) {
247         printf("%s unknown, did you mean %s?\n",
248                argv[i], suggestion->path().c_str());
249       } else {
250         printf("%s unknown\n", argv[i]);
251       }
252       return 1;
253     }
254   }
255   return 0;
256 }
257
258 #if !defined(_WIN32) && !defined(NINJA_BOOTSTRAP)
259 int ToolBrowse(Globals* globals, int argc, char* argv[]) {
260   if (argc < 1) {
261     Error("expected a target to browse");
262     return 1;
263   }
264   RunBrowsePython(globals->state, globals->ninja_command, argv[0]);
265   // If we get here, the browse failed.
266   return 1;
267 }
268 #endif  // _WIN32
269
270 int ToolTargetsList(const vector<Node*>& nodes, int depth, int indent) {
271   for (vector<Node*>::const_iterator n = nodes.begin();
272        n != nodes.end();
273        ++n) {
274     for (int i = 0; i < indent; ++i)
275       printf("  ");
276     const char* target = (*n)->path().c_str();
277     if ((*n)->in_edge()) {
278       printf("%s: %s\n", target, (*n)->in_edge()->rule_->name().c_str());
279       if (depth > 1 || depth <= 0)
280         ToolTargetsList((*n)->in_edge()->inputs_, depth - 1, indent + 1);
281     } else {
282       printf("%s\n", target);
283     }
284   }
285   return 0;
286 }
287
288 int ToolTargetsSourceList(State* state) {
289   for (vector<Edge*>::iterator e = state->edges_.begin();
290        e != state->edges_.end(); ++e) {
291     for (vector<Node*>::iterator inps = (*e)->inputs_.begin();
292          inps != (*e)->inputs_.end(); ++inps) {
293       if (!(*inps)->in_edge())
294         printf("%s\n", (*inps)->path().c_str());
295     }
296   }
297   return 0;
298 }
299
300 int ToolTargetsList(State* state, const string& rule_name) {
301   set<string> rules;
302
303   // Gather the outputs.
304   for (vector<Edge*>::iterator e = state->edges_.begin();
305        e != state->edges_.end(); ++e) {
306     if ((*e)->rule_->name() == rule_name) {
307       for (vector<Node*>::iterator out_node = (*e)->outputs_.begin();
308            out_node != (*e)->outputs_.end(); ++out_node) {
309         rules.insert((*out_node)->path());
310       }
311     }
312   }
313
314   // Print them.
315   for (set<string>::const_iterator i = rules.begin();
316        i != rules.end(); ++i) {
317     printf("%s\n", (*i).c_str());
318   }
319
320   return 0;
321 }
322
323 int ToolTargetsList(State* state) {
324   for (vector<Edge*>::iterator e = state->edges_.begin();
325        e != state->edges_.end(); ++e) {
326     for (vector<Node*>::iterator out_node = (*e)->outputs_.begin();
327          out_node != (*e)->outputs_.end(); ++out_node) {
328       printf("%s: %s\n",
329              (*out_node)->path().c_str(),
330              (*e)->rule_->name().c_str());
331     }
332   }
333   return 0;
334 }
335
336 int ToolTargets(Globals* globals, int argc, char* argv[]) {
337   int depth = 1;
338   if (argc >= 1) {
339     string mode = argv[0];
340     if (mode == "rule") {
341       string rule;
342       if (argc > 1)
343         rule = argv[1];
344       if (rule.empty())
345         return ToolTargetsSourceList(globals->state);
346       else
347         return ToolTargetsList(globals->state, rule);
348     } else if (mode == "depth") {
349       if (argc > 1)
350         depth = atoi(argv[1]);
351     } else if (mode == "all") {
352       return ToolTargetsList(globals->state);
353     } else {
354       const char* suggestion =
355           SpellcheckString(mode, "rule", "depth", "all", NULL);
356       if (suggestion) {
357         Error("unknown target tool mode '%s', did you mean '%s'?",
358               mode.c_str(), suggestion);
359       } else {
360         Error("unknown target tool mode '%s'", mode.c_str());
361       }
362       return 1;
363     }
364   }
365
366   string err;
367   vector<Node*> root_nodes = globals->state->RootNodes(&err);
368   if (err.empty()) {
369     return ToolTargetsList(root_nodes, depth, 0);
370   } else {
371     Error("%s", err.c_str());
372     return 1;
373   }
374 }
375
376 int ToolRules(Globals* globals, int argc, char* /* argv */[]) {
377   for (map<string, const Rule*>::iterator i = globals->state->rules_.begin();
378        i != globals->state->rules_.end(); ++i) {
379     if (i->second->description().empty()) {
380       printf("%s\n", i->first.c_str());
381     } else {
382       printf("%s: %s\n",
383              i->first.c_str(),
384              // XXX I changed it such that we don't have an easy way
385              // to get the source text anymore, so this output is
386              // unsatisfactory.  How useful is this command, anyway?
387              i->second->description().Serialize().c_str());
388     }
389   }
390   return 0;
391 }
392
393 void PrintCommands(Edge* edge, set<Edge*>* seen) {
394   if (!edge)
395     return;
396   if (!seen->insert(edge).second)
397     return;
398
399   for (vector<Node*>::iterator in = edge->inputs_.begin();
400        in != edge->inputs_.end(); ++in)
401     PrintCommands((*in)->in_edge(), seen);
402
403   if (!edge->is_phony())
404     puts(edge->EvaluateCommand().c_str());
405 }
406
407 int ToolCommands(Globals* globals, int argc, char* argv[]) {
408   vector<Node*> nodes;
409   string err;
410   if (!CollectTargetsFromArgs(globals->state, argc, argv, &nodes, &err)) {
411     Error("%s", err.c_str());
412     return 1;
413   }
414
415   set<Edge*> seen;
416   for (vector<Node*>::iterator in = nodes.begin(); in != nodes.end(); ++in)
417     PrintCommands((*in)->in_edge(), &seen);
418
419   return 0;
420 }
421
422 int ToolClean(Globals* globals, int argc, char* argv[]) {
423   // The clean tool uses getopt, and expects argv[0] to contain the name of
424   // the tool, i.e. "clean".
425   argc++;
426   argv--;
427
428   bool generator = false;
429   bool clean_rules = false;
430
431   optind = 1;
432   int opt;
433   while ((opt = getopt(argc, argv, const_cast<char*>("hgr"))) != -1) {
434     switch (opt) {
435     case 'g':
436       generator = true;
437       break;
438     case 'r':
439       clean_rules = true;
440       break;
441     case 'h':
442     default:
443       printf("usage: ninja -t clean [options] [targets]\n"
444 "\n"
445 "options:\n"
446 "  -g     also clean files marked as ninja generator output\n"
447 "  -r     interpret targets as a list of rules to clean instead\n"
448              );
449     return 1;
450     }
451   }
452   argv += optind;
453   argc -= optind;
454
455   if (clean_rules && argc == 0) {
456     Error("expected a rule to clean");
457     return 1;
458   }
459
460   Cleaner cleaner(globals->state, globals->config);
461   if (argc >= 1) {
462     if (clean_rules)
463       return cleaner.CleanRules(argc, argv);
464     else
465       return cleaner.CleanTargets(argc, argv);
466   } else {
467     return cleaner.CleanAll(generator);
468   }
469 }
470
471 int RunTool(const string& tool, Globals* globals, int argc, char** argv) {
472   typedef int (*ToolFunc)(Globals*, int, char**);
473   struct Tool {
474     const char* name;
475     const char* desc;
476     ToolFunc func;
477   } tools[] = {
478 #if !defined(_WIN32) && !defined(NINJA_BOOTSTRAP)
479     { "browse", "browse dependency graph in a web browser",
480       ToolBrowse },
481 #endif
482     { "clean", "clean built files",
483       ToolClean },
484     { "commands", "list all commands required to rebuild given targets",
485       ToolCommands },
486     { "graph", "output graphviz dot file for targets",
487       ToolGraph },
488     { "query", "show inputs/outputs for a path",
489       ToolQuery },
490     { "rules",    "list all rules",
491       ToolRules },
492     { "targets",  "list targets by their rule or depth in the DAG",
493       ToolTargets },
494     { NULL, NULL, NULL }
495   };
496
497   if (tool == "list") {
498     printf("ninja subtools:\n");
499     for (int i = 0; tools[i].name; ++i) {
500       printf("%10s  %s\n", tools[i].name, tools[i].desc);
501     }
502     return 0;
503   }
504
505   for (int i = 0; tools[i].name; ++i) {
506     if (tool == tools[i].name)
507       return tools[i].func(globals, argc, argv);
508   }
509
510   vector<const char*> words;
511   for (int i = 0; tools[i].name; ++i)
512     words.push_back(tools[i].name);
513   const char* suggestion = SpellcheckStringV(tool, words);
514   if (suggestion) {
515     Error("unknown tool '%s', did you mean '%s'?", tool.c_str(), suggestion);
516   } else {
517     Error("unknown tool '%s'", tool.c_str());
518   }
519   return 1;
520 }
521
522 /// Enable a debugging mode.  Returns false if Ninja should exit instead
523 /// of continuing.
524 bool DebugEnable(const string& name, Globals* globals) {
525   if (name == "list") {
526     printf("debugging modes:\n"
527 "  stats  print operation counts/timing info\n");
528 //"multiple modes can be enabled via -d FOO -d BAR\n");
529     return false;
530   } else if (name == "stats") {
531     g_metrics = new Metrics;
532     return true;
533   } else {
534     printf("ninja: unknown debug setting '%s'\n", name.c_str());
535     return false;
536   }
537 }
538
539 int RunBuild(Globals* globals, int argc, char** argv) {
540   string err;
541   vector<Node*> targets;
542   if (!CollectTargetsFromArgs(globals->state, argc, argv, &targets, &err)) {
543     Error("%s", err.c_str());
544     return 1;
545   }
546
547   Builder builder(globals->state, globals->config);
548   for (size_t i = 0; i < targets.size(); ++i) {
549     if (!builder.AddTarget(targets[i], &err)) {
550       if (!err.empty()) {
551         Error("%s", err.c_str());
552         return 1;
553       } else {
554         // Added a target that is already up-to-date; not really
555         // an error.
556       }
557     }
558   }
559
560   if (builder.AlreadyUpToDate()) {
561     printf("ninja: no work to do.\n");
562     return 0;
563   }
564
565   if (!builder.Build(&err)) {
566     printf("ninja: build stopped: %s.\n", err.c_str());
567     return 1;
568   }
569
570   return 0;
571 }
572
573 }  // anonymous namespace
574
575 int main(int argc, char** argv) {
576   Globals globals;
577   globals.ninja_command = argv[0];
578   const char* input_file = "build.ninja";
579   const char* working_dir = NULL;
580   string tool;
581
582   setvbuf(stdout, NULL, _IOLBF, BUFSIZ);
583
584   globals.config.parallelism = GuessParallelism();
585
586   const option kLongOptions[] = {
587     { "help", no_argument, NULL, 'h' },
588     { NULL, 0, NULL, 0 }
589   };
590
591   int opt;
592   while (tool.empty() &&
593          (opt = getopt_long(argc, argv, "d:f:hj:k:nt:vC:", kLongOptions,
594                             NULL)) != -1) {
595     switch (opt) {
596       case 'd':
597         if (!DebugEnable(optarg, &globals))
598           return 1;
599         break;
600       case 'f':
601         input_file = optarg;
602         break;
603       case 'j':
604         globals.config.parallelism = atoi(optarg);
605         break;
606       case 'k': {
607         char* end;
608         int value = strtol(optarg, &end, 10);
609         if (*end != 0)
610           Fatal("-k parameter not numeric; did you mean -k0?");
611
612         // We want to go until N jobs fail, which means we should ignore
613         // the first N-1 that fail and then stop.
614         globals.config.swallow_failures = value - 1;
615         break;
616       }
617       case 'n':
618         globals.config.dry_run = true;
619         break;
620       case 'v':
621         globals.config.verbosity = BuildConfig::VERBOSE;
622         break;
623       case 't':
624         tool = optarg;
625         break;
626       case 'C':
627         working_dir = optarg;
628         break;
629       case 'h':
630       default:
631         Usage(globals.config);
632         return 1;
633     }
634   }
635   argv += optind;
636   argc -= optind;
637
638   if (working_dir) {
639     // The formatting of this string, complete with funny quotes, is
640     // so Emacs can properly identify that the cwd has changed for
641     // subsequent commands.
642     printf("ninja: Entering directory `%s'\n", working_dir);
643 #ifdef _WIN32
644     if (_chdir(working_dir) < 0) {
645 #else
646     if (chdir(working_dir) < 0) {
647 #endif
648       Fatal("chdir to '%s' - %s", working_dir, strerror(errno));
649     }
650   }
651
652   bool rebuilt_manifest = false;
653
654 reload:
655   RealFileReader file_reader;
656   ManifestParser parser(globals.state, &file_reader);
657   string err;
658   if (!parser.Load(input_file, &err)) {
659     Error("%s", err.c_str());
660     return 1;
661   }
662
663   if (!tool.empty())
664     return RunTool(tool, &globals, argc, argv);
665
666   BuildLog build_log;
667   build_log.SetConfig(&globals.config);
668   globals.state->build_log_ = &build_log;
669
670   const string build_dir = globals.state->bindings_.LookupVariable("builddir");
671   const char* kLogPath = ".ninja_log";
672   string log_path = kLogPath;
673   if (!build_dir.empty()) {
674     if (MakeDir(build_dir) < 0 && errno != EEXIST) {
675       Error("creating build directory %s: %s",
676             build_dir.c_str(), strerror(errno));
677       return 1;
678     }
679     log_path = build_dir + "/" + kLogPath;
680   }
681
682   if (!build_log.Load(log_path.c_str(), &err)) {
683     Error("loading build log %s: %s",
684           log_path.c_str(), err.c_str());
685     return 1;
686   }
687
688   if (!build_log.OpenForWrite(log_path.c_str(), &err)) {
689     Error("opening build log: %s", err.c_str());
690     return 1;
691   }
692
693   if (!rebuilt_manifest) { // Don't get caught in an infinite loop by a rebuild
694                            // target that is never up to date.
695     if (RebuildManifest(globals.state, globals.config, input_file, &err)) {
696       rebuilt_manifest = true;
697       globals.ResetState();
698       goto reload;
699     } else if (!err.empty()) {
700       Error("rebuilding '%s': %s", input_file, err.c_str());
701       return 1;
702     }
703   }
704
705   int result = RunBuild(&globals, argc, argv);
706   if (g_metrics) {
707     g_metrics->Report();
708
709     printf("\n");
710     int count = (int)globals.state->paths_.size();
711     int buckets =
712 #ifdef _WIN32
713         (int)globals.state->paths_.comp.bucket_size;
714 #else
715         (int)globals.state->paths_.bucket_count();
716 #endif
717     printf("path->node hash load %.2f (%d entries / %d buckets)\n",
718            count / (double) buckets, count, buckets);
719   }
720   return result;
721 }