1 // Copyright 2011 Google Inc. All Rights Reserved.
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
7 // http://www.apache.org/licenses/LICENSE-2.0
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.
20 #include <sys/types.h>
33 #include "build_log.h"
35 #include "disk_interface.h"
36 #include "edit_distance.h"
40 #include "manifest_parser.h"
45 // Defined in msvc_helper_main-win32.cc.
46 int MSVCHelperMain(int argc, char** argv);
50 /// The version number of the current Ninja release. This will always
51 /// be "git" on trunk.
52 const char* kVersion = "1.0.0";
54 /// Global information passed into subtools.
56 Globals() : state(new State()) {}
61 /// Deletes and recreates state so it is empty.
67 /// Command line used to run Ninja.
68 const char* ninja_command;
69 /// Build configuration set from flags (e.g. parallelism).
71 /// Loaded state (rules, nodes). This is a pointer so it can be reset.
75 /// The type of functions that are the entry points to tools (subcommands).
76 typedef int (*ToolFunc)(Globals*, int, char**);
78 /// Subtools, accessible via "-t foo".
80 /// Short name of the tool.
83 /// Description (shown in "-t list").
86 /// When to run the tool.
88 /// Run after parsing the command-line flags (as early as possible).
91 /// Run after loading build.ninja.
95 /// Implementation of the tool.
99 /// Print usage information.
100 void Usage(const BuildConfig& config) {
102 "usage: ninja [options] [targets...]\n"
104 "if targets are unspecified, builds the 'default' target (see manual).\n"
107 " --version print ninja version (\"%s\")\n"
109 " -C DIR change to DIR before doing anything else\n"
110 " -f FILE specify input build file [default=build.ninja]\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"
115 " (not yet implemented on Windows)\n"
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"
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);
127 /// Choose a default value for the -j (parallelism) flag.
128 int GuessParallelism() {
129 switch (int processors = GetProcessorCount()) {
136 return processors + 2;
140 /// An implementation of ManifestParser::FileReader that actually reads
142 struct RealFileReader : public ManifestParser::FileReader {
143 bool ReadFile(const string& path, string* content, string* err) {
144 return ::ReadFile(path, content, err) == 0;
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))
154 Node* node = builder->state_->LookupNode(path);
158 if (!builder->AddTarget(node, err))
161 if (builder->AlreadyUpToDate())
162 return false; // Not an error, but we didn't rebuild.
163 if (!builder->Build(err))
166 // The manifest was only rebuilt if it is now dirty (it may have been cleaned
168 return node->dirty();
171 bool CollectTargetsFromArgs(State* state, int argc, char* argv[],
172 vector<Node*>* targets, string* err) {
174 *targets = state->DefaultNodes(err);
178 for (int i = 0; i < argc; ++i) {
179 string path = argv[i];
180 if (!CanonicalizePath(&path, err))
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;
190 Node* node = state->LookupNode(path);
192 if (first_dependent) {
193 if (node->out_edges().empty()) {
194 *err = "'" + path + "' has no out edge";
197 Edge* edge = node->out_edges()[0];
198 if (edge->outputs_.empty()) {
200 Fatal("edge has no outputs");
202 node = edge->outputs_[0];
204 targets->push_back(node);
206 *err = "unknown target '" + path + "'";
208 if (path == "clean") {
209 *err += ", did you mean 'ninja -t clean'?";
210 } else if (path == "help") {
211 *err += ", did you mean 'ninja -h'?";
213 Node* suggestion = state->SpellcheckNode(path);
215 *err += ", did you mean '" + suggestion->path() + "'?";
224 int ToolGraph(Globals* globals, int argc, char* argv[]) {
227 if (!CollectTargetsFromArgs(globals->state, argc, argv, &nodes, &err)) {
228 Error("%s", err.c_str());
234 for (vector<Node*>::const_iterator n = nodes.begin(); n != nodes.end(); ++n)
241 int ToolQuery(Globals* globals, int argc, char* argv[]) {
243 Error("expected a target to query");
246 for (int i = 0; i < argc; ++i) {
247 Node* node = globals->state->LookupNode(argv[i]);
249 Node* suggestion = globals->state->SpellcheckNode(argv[i]);
251 printf("%s unknown, did you mean %s?\n",
252 argv[i], suggestion->path().c_str());
254 printf("%s unknown\n", argv[i]);
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))
266 else if (edge->is_order_only(in))
268 printf(" %s%s\n", label, edge->inputs_[in]->path().c_str());
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());
283 #if !defined(_WIN32) && !defined(NINJA_BOOTSTRAP)
284 int ToolBrowse(Globals* globals, int argc, char* argv[]) {
286 Error("expected a target to browse");
289 RunBrowsePython(globals->state, globals->ninja_command, argv[0]);
290 // If we get here, the browse failed.
296 int ToolMSVC(Globals* globals, int argc, char* argv[]) {
297 // Reset getopt: push one argument onto the front of argv, reset optind.
301 return MSVCHelperMain(argc, argv);
305 int ToolTargetsList(const vector<Node*>& nodes, int depth, int indent) {
306 for (vector<Node*>::const_iterator n = nodes.begin();
309 for (int i = 0; i < indent; ++i)
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);
317 printf("%s\n", target);
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());
335 int ToolTargetsList(State* state, const string& rule_name) {
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());
350 for (set<string>::const_iterator i = rules.begin();
351 i != rules.end(); ++i) {
352 printf("%s\n", (*i).c_str());
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) {
364 (*out_node)->path().c_str(),
365 (*e)->rule_->name().c_str());
371 int ToolTargets(Globals* globals, int argc, char* argv[]) {
374 string mode = argv[0];
375 if (mode == "rule") {
380 return ToolTargetsSourceList(globals->state);
382 return ToolTargetsList(globals->state, rule);
383 } else if (mode == "depth") {
385 depth = atoi(argv[1]);
386 } else if (mode == "all") {
387 return ToolTargetsList(globals->state);
389 const char* suggestion =
390 SpellcheckString(mode, "rule", "depth", "all", NULL);
392 Error("unknown target tool mode '%s', did you mean '%s'?",
393 mode.c_str(), suggestion);
395 Error("unknown target tool mode '%s'", mode.c_str());
402 vector<Node*> root_nodes = globals->state->RootNodes(&err);
404 return ToolTargetsList(root_nodes, depth, 0);
406 Error("%s", err.c_str());
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());
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());
428 void PrintCommands(Edge* edge, set<Edge*>* seen) {
431 if (!seen->insert(edge).second)
434 for (vector<Node*>::iterator in = edge->inputs_.begin();
435 in != edge->inputs_.end(); ++in)
436 PrintCommands((*in)->in_edge(), seen);
438 if (!edge->is_phony())
439 puts(edge->EvaluateCommand().c_str());
442 int ToolCommands(Globals* globals, int argc, char* argv[]) {
445 if (!CollectTargetsFromArgs(globals->state, argc, argv, &nodes, &err)) {
446 Error("%s", err.c_str());
451 for (vector<Node*>::iterator in = nodes.begin(); in != nodes.end(); ++in)
452 PrintCommands((*in)->in_edge(), &seen);
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".
463 bool generator = false;
464 bool clean_rules = false;
468 while ((opt = getopt(argc, argv, const_cast<char*>("hgr"))) != -1) {
478 printf("usage: ninja -t clean [options] [targets]\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"
490 if (clean_rules && argc == 0) {
491 Error("expected a rule to clean");
495 Cleaner cleaner(globals->state, *globals->config);
498 return cleaner.CleanRules(argc, argv);
500 return cleaner.CleanTargets(argc, argv);
502 return cleaner.CleanAll(generator);
506 int ToolUrtle(Globals* globals, int argc, char** argv) {
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";
520 for (const char* p = urtle; *p; p++) {
521 if ('0' <= *p && *p <= '9') {
522 count = count*10 + *p - '0';
524 for (int i = 0; i < std::max(count, 1); ++i)
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 },
541 { "msvc", "build helper for MSVC cl.exe (EXPERIMENTAL)",
542 Tool::RUN_AFTER_FLAGS, ToolMSVC },
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 },
557 Tool::RUN_AFTER_FLAGS, ToolUrtle },
558 { NULL, NULL, Tool::RUN_AFTER_FLAGS, NULL }
561 if (tool_name == "list") {
562 printf("ninja subtools:\n");
563 for (const Tool* tool = &kTools[0]; tool->name; ++tool) {
565 printf("%10s %s\n", tool->name, tool->desc);
570 for (const Tool* tool = &kTools[0]; tool->name; ++tool) {
571 if (tool->name == tool_name) {
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);
582 Error("unknown tool '%s', did you mean '%s'?",
583 tool_name.c_str(), suggestion);
585 Error("unknown tool '%s'", tool_name.c_str());
590 /// Enable a debugging mode. Returns false if Ninja should exit instead
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");
599 } else if (name == "stats") {
600 g_metrics = new Metrics;
602 } else if (name == "explain") {
606 printf("ninja: unknown debug setting '%s'\n", name.c_str());
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));
627 if (!build_log->Load(log_path, &err)) {
628 Error("loading build log %s: %s", log_path.c_str(), err.c_str());
632 // Hack: Load() can return a warning via err by returning true.
633 Warning("%s", err.c_str());
637 if (!globals->config->dry_run) {
638 if (!build_log->OpenForWrite(log_path, &err)) {
639 Error("opening build log: %s", err.c_str());
647 /// Dump the output requested by '-d stats'.
648 void DumpMetrics(Globals* globals) {
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);
658 int RunBuild(Builder* builder, int argc, char** argv) {
660 vector<Node*> targets;
661 if (!CollectTargetsFromArgs(builder->state_, argc, argv, &targets, &err)) {
662 Error("%s", err.c_str());
666 for (size_t i = 0; i < targets.size(); ++i) {
667 if (!builder->AddTarget(targets[i], &err)) {
669 Error("%s", err.c_str());
672 // Added a target that is already up-to-date; not really
678 if (builder->AlreadyUpToDate()) {
679 printf("ninja: no work to do.\n");
683 if (!builder->Build(&err)) {
684 printf("ninja: build stopped: %s.\n", err.c_str());
693 } // anonymous namespace
695 // Defined in minidump-win32.cc.
696 void CreateWin32MiniDump(_EXCEPTION_POINTERS* pep);
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");
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
715 CreateWin32MiniDump(ep);
716 return EXCEPTION_EXECUTE_HANDLER;
721 int NinjaMain(int argc, char** argv) {
724 globals.ninja_command = argv[0];
725 globals.config = &config;
726 const char* input_file = "build.ninja";
727 const char* working_dir = NULL;
730 setvbuf(stdout, NULL, _IOLBF, BUFSIZ);
732 config.parallelism = GuessParallelism();
734 enum { OPT_VERSION = 1 };
735 const option kLongOptions[] = {
736 { "help", no_argument, NULL, 'h' },
737 { "version", no_argument, NULL, OPT_VERSION },
742 while (tool_name.empty() &&
743 (opt = getopt_long(argc, argv, "d:f:hj:k:l:nt:vC:V", kLongOptions,
747 if (!DebugEnable(optarg, &globals))
754 config.parallelism = atoi(optarg);
758 double value = strtod(optarg, &end);
760 Fatal("-l parameter not numeric: did you mean -l 0.0?");
761 config.max_load_average = value;
766 int value = strtol(optarg, &end, 10);
768 Fatal("-k parameter not numeric; did you mean -k 0?");
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;
777 config.dry_run = true;
780 config.verbosity = BuildConfig::VERBOSE;
786 working_dir = optarg;
789 printf("%s\n", kVersion);
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);
809 if (tool && tool->when == Tool::RUN_AFTER_FLAGS)
810 return tool->func(&globals, argc, argv);
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.
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));
825 bool rebuilt_manifest = false;
828 RealDiskInterface disk_interface;
829 RealFileReader file_reader;
830 ManifestParser parser(globals.state, &file_reader);
832 if (!parser.Load(input_file, &err)) {
833 Error("%s", err.c_str());
837 if (tool && tool->when == Tool::RUN_AFTER_LOAD)
838 return tool->func(&globals, argc, argv);
841 if (!OpenLog(&build_log, &globals, &disk_interface))
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,
848 if (RebuildManifest(&manifest_builder, input_file, &err)) {
849 rebuilt_manifest = true;
850 globals.ResetState();
852 } else if (!err.empty()) {
853 Error("rebuilding '%s': %s", input_file, err.c_str());
858 Builder builder(globals.state, config, &build_log, &disk_interface);
859 int result = RunBuild(&builder, argc, argv);
861 DumpMetrics(&globals);
865 } // anonymous namespace
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);
873 // Running inside __try ... __except suppresses any Windows error
874 // dialogs for errors such as bad_alloc.
875 return NinjaMain(argc, argv);
877 __except(ExceptionFilter(GetExceptionCode(), GetExceptionInformation())) {
878 // Common error situations return exitCode=1. 2 was chosen to
879 // indicate a more serious problem.
883 return NinjaMain(argc, argv);