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 = "git";
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 virtual 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 Node* CollectTarget(State* state, const char* cpath, string* err) {
173 if (!CanonicalizePath(&path, err))
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;
183 Node* node = state->LookupNode(path);
185 if (first_dependent) {
186 if (node->out_edges().empty()) {
187 *err = "'" + path + "' has no out edge";
190 Edge* edge = node->out_edges()[0];
191 if (edge->outputs_.empty()) {
193 Fatal("edge has no outputs");
195 node = edge->outputs_[0];
199 *err = "unknown target '" + path + "'";
201 if (path == "clean") {
202 *err += ", did you mean 'ninja -t clean'?";
203 } else if (path == "help") {
204 *err += ", did you mean 'ninja -h'?";
206 Node* suggestion = state->SpellcheckNode(path);
208 *err += ", did you mean '" + suggestion->path() + "'?";
215 bool CollectTargetsFromArgs(State* state, int argc, char* argv[],
216 vector<Node*>* targets, string* err) {
218 *targets = state->DefaultNodes(err);
222 for (int i = 0; i < argc; ++i) {
223 Node* node = CollectTarget(state, argv[i], err);
226 targets->push_back(node);
231 int ToolGraph(Globals* globals, int argc, char* argv[]) {
234 if (!CollectTargetsFromArgs(globals->state, argc, argv, &nodes, &err)) {
235 Error("%s", err.c_str());
241 for (vector<Node*>::const_iterator n = nodes.begin(); n != nodes.end(); ++n)
248 int ToolQuery(Globals* globals, int argc, char* argv[]) {
250 Error("expected a target to query");
253 for (int i = 0; i < argc; ++i) {
255 Node* node = CollectTarget(globals->state, argv[i], &err);
257 Error("%s", err.c_str());
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))
268 else if (edge->is_order_only(in))
270 printf(" %s%s\n", label, edge->inputs_[in]->path().c_str());
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());
285 #if !defined(_WIN32) && !defined(NINJA_BOOTSTRAP)
286 int ToolBrowse(Globals* globals, int argc, char* argv[]) {
288 Error("expected a target to browse");
291 RunBrowsePython(globals->state, globals->ninja_command, argv[0]);
292 // If we get here, the browse failed.
298 int ToolMSVC(Globals* globals, int argc, char* argv[]) {
299 // Reset getopt: push one argument onto the front of argv, reset optind.
303 return MSVCHelperMain(argc, argv);
307 int ToolTargetsList(const vector<Node*>& nodes, int depth, int indent) {
308 for (vector<Node*>::const_iterator n = nodes.begin();
311 for (int i = 0; i < indent; ++i)
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);
319 printf("%s\n", target);
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());
337 int ToolTargetsList(State* state, const string& rule_name) {
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());
352 for (set<string>::const_iterator i = rules.begin();
353 i != rules.end(); ++i) {
354 printf("%s\n", (*i).c_str());
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) {
366 (*out_node)->path().c_str(),
367 (*e)->rule_->name().c_str());
373 int ToolTargets(Globals* globals, int argc, char* argv[]) {
376 string mode = argv[0];
377 if (mode == "rule") {
382 return ToolTargetsSourceList(globals->state);
384 return ToolTargetsList(globals->state, rule);
385 } else if (mode == "depth") {
387 depth = atoi(argv[1]);
388 } else if (mode == "all") {
389 return ToolTargetsList(globals->state);
391 const char* suggestion =
392 SpellcheckString(mode, "rule", "depth", "all", NULL);
394 Error("unknown target tool mode '%s', did you mean '%s'?",
395 mode.c_str(), suggestion);
397 Error("unknown target tool mode '%s'", mode.c_str());
404 vector<Node*> root_nodes = globals->state->RootNodes(&err);
406 return ToolTargetsList(root_nodes, depth, 0);
408 Error("%s", err.c_str());
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());
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());
430 void PrintCommands(Edge* edge, set<Edge*>* seen) {
433 if (!seen->insert(edge).second)
436 for (vector<Node*>::iterator in = edge->inputs_.begin();
437 in != edge->inputs_.end(); ++in)
438 PrintCommands((*in)->in_edge(), seen);
440 if (!edge->is_phony())
441 puts(edge->EvaluateCommand().c_str());
444 int ToolCommands(Globals* globals, int argc, char* argv[]) {
447 if (!CollectTargetsFromArgs(globals->state, argc, argv, &nodes, &err)) {
448 Error("%s", err.c_str());
453 for (vector<Node*>::iterator in = nodes.begin(); in != nodes.end(); ++in)
454 PrintCommands((*in)->in_edge(), &seen);
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".
465 bool generator = false;
466 bool clean_rules = false;
470 while ((opt = getopt(argc, argv, const_cast<char*>("hgr"))) != -1) {
480 printf("usage: ninja -t clean [options] [targets]\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"
492 if (clean_rules && argc == 0) {
493 Error("expected a rule to clean");
497 Cleaner cleaner(globals->state, *globals->config);
500 return cleaner.CleanRules(argc, argv);
502 return cleaner.CleanTargets(argc, argv);
504 return cleaner.CleanAll(generator);
508 int ToolUrtle(Globals* globals, int argc, char** argv) {
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";
522 for (const char* p = urtle; *p; p++) {
523 if ('0' <= *p && *p <= '9') {
524 count = count*10 + *p - '0';
526 for (int i = 0; i < std::max(count, 1); ++i)
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 },
543 { "msvc", "build helper for MSVC cl.exe (EXPERIMENTAL)",
544 Tool::RUN_AFTER_FLAGS, ToolMSVC },
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 },
559 Tool::RUN_AFTER_FLAGS, ToolUrtle },
560 { NULL, NULL, Tool::RUN_AFTER_FLAGS, NULL }
563 if (tool_name == "list") {
564 printf("ninja subtools:\n");
565 for (const Tool* tool = &kTools[0]; tool->name; ++tool) {
567 printf("%10s %s\n", tool->name, tool->desc);
572 for (const Tool* tool = &kTools[0]; tool->name; ++tool) {
573 if (tool->name == tool_name) {
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);
584 Error("unknown tool '%s', did you mean '%s'?",
585 tool_name.c_str(), suggestion);
587 Error("unknown tool '%s'", tool_name.c_str());
592 /// Enable a debugging mode. Returns false if Ninja should exit instead
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");
601 } else if (name == "stats") {
602 g_metrics = new Metrics;
604 } else if (name == "explain") {
608 printf("ninja: unknown debug setting '%s'\n", name.c_str());
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));
629 if (!build_log->Load(log_path, &err)) {
630 Error("loading build log %s: %s", log_path.c_str(), err.c_str());
634 // Hack: Load() can return a warning via err by returning true.
635 Warning("%s", err.c_str());
639 if (!globals->config->dry_run) {
640 if (!build_log->OpenForWrite(log_path, &err)) {
641 Error("opening build log: %s", err.c_str());
649 /// Dump the output requested by '-d stats'.
650 void DumpMetrics(Globals* globals) {
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);
660 int RunBuild(Builder* builder, int argc, char** argv) {
662 vector<Node*> targets;
663 if (!CollectTargetsFromArgs(builder->state_, argc, argv, &targets, &err)) {
664 Error("%s", err.c_str());
668 for (size_t i = 0; i < targets.size(); ++i) {
669 if (!builder->AddTarget(targets[i], &err)) {
671 Error("%s", err.c_str());
674 // Added a target that is already up-to-date; not really
680 if (builder->AlreadyUpToDate()) {
681 printf("ninja: no work to do.\n");
685 if (!builder->Build(&err)) {
686 printf("ninja: build stopped: %s.\n", err.c_str());
687 if (err.find("interrupted by user") != string::npos) {
698 } // anonymous namespace
700 // Defined in minidump-win32.cc.
701 void CreateWin32MiniDump(_EXCEPTION_POINTERS* pep);
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");
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
720 CreateWin32MiniDump(ep);
721 return EXCEPTION_EXECUTE_HANDLER;
726 int NinjaMain(int argc, char** argv) {
729 globals.ninja_command = argv[0];
730 globals.config = &config;
731 const char* input_file = "build.ninja";
732 const char* working_dir = NULL;
735 setvbuf(stdout, NULL, _IOLBF, BUFSIZ);
737 config.parallelism = GuessParallelism();
739 enum { OPT_VERSION = 1 };
740 const option kLongOptions[] = {
741 { "help", no_argument, NULL, 'h' },
742 { "version", no_argument, NULL, OPT_VERSION },
747 while (tool_name.empty() &&
748 (opt = getopt_long(argc, argv, "d:f:j:k:l:nt:vC:h", kLongOptions,
752 if (!DebugEnable(optarg, &globals))
759 config.parallelism = atoi(optarg);
763 int value = strtol(optarg, &end, 10);
765 Fatal("-k parameter not numeric; did you mean -k 0?");
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;
775 double value = strtod(optarg, &end);
777 Fatal("-l parameter not numeric: did you mean -l 0.0?");
778 config.max_load_average = value;
782 config.dry_run = true;
788 config.verbosity = BuildConfig::VERBOSE;
791 working_dir = optarg;
794 printf("%s\n", kVersion);
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);
814 if (tool && tool->when == Tool::RUN_AFTER_FLAGS)
815 return tool->func(&globals, argc, argv);
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.
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));
830 bool rebuilt_manifest = false;
833 RealFileReader file_reader;
834 ManifestParser parser(globals.state, &file_reader);
836 if (!parser.Load(input_file, &err)) {
837 Error("%s", err.c_str());
841 if (tool && tool->when == Tool::RUN_AFTER_LOAD)
842 return tool->func(&globals, argc, argv);
845 RealDiskInterface disk_interface;
846 if (!OpenLog(&build_log, &globals, &disk_interface))
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,
853 if (RebuildManifest(&manifest_builder, input_file, &err)) {
854 rebuilt_manifest = true;
855 globals.ResetState();
857 } else if (!err.empty()) {
858 Error("rebuilding '%s': %s", input_file, err.c_str());
863 Builder builder(globals.state, config, &build_log, &disk_interface);
864 int result = RunBuild(&builder, argc, argv);
866 DumpMetrics(&globals);
870 } // anonymous namespace
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);
878 // Running inside __try ... __except suppresses any Windows error
879 // dialogs for errors such as bad_alloc.
880 return NinjaMain(argc, argv);
882 __except(ExceptionFilter(GetExceptionCode(), GetExceptionInformation())) {
883 // Common error situations return exitCode=1. 2 was chosen to
884 // indicate a more serious problem.
888 return NinjaMain(argc, argv);