60 const char* input_file;
63 const char* working_dir;
72 NinjaMain(
const char* ninja_command,
const BuildConfig& config) :
73 ninja_command_(ninja_command), config_(config) {}
76 const char* ninja_command_;
94 typedef int (NinjaMain::*ToolFunc)(int,
char**);
98 Node* CollectTarget(
const char* cpath,
string* err);
101 bool CollectTargetsFromArgs(
int argc,
char* argv[],
102 vector<Node*>* targets,
string* err);
105 int ToolGraph(
int argc,
char* argv[]);
106 int ToolQuery(
int argc,
char* argv[]);
107 int ToolDeps(
int argc,
char* argv[]);
108 int ToolBrowse(
int argc,
char* argv[]);
109 int ToolMSVC(
int argc,
char* argv[]);
110 int ToolTargets(
int argc,
char* argv[]);
111 int ToolCommands(
int argc,
char* argv[]);
112 int ToolClean(
int argc,
char* argv[]);
113 int ToolCompilationDatabase(
int argc,
char* argv[]);
114 int ToolRecompact(
int argc,
char* argv[]);
115 int ToolUrtle(
int argc,
char** argv);
119 bool OpenBuildLog(
bool recompact_only =
false);
123 bool OpenDepsLog(
bool recompact_only =
false);
127 bool EnsureBuildDirExists();
132 bool RebuildManifest(
const char* input_file,
string* err);
136 int RunBuild(
int argc,
char** argv);
177 NinjaMain::ToolFunc func;
183 "usage: ninja [options] [targets...]\n" 185 "if targets are unspecified, builds the 'default' target (see manual).\n" 188 " --version print ninja version (\"%s\")\n" 190 " -C DIR change to DIR before doing anything else\n" 191 " -f FILE specify input build file [default=build.ninja]\n" 193 " -j N run N jobs in parallel [default=%d, derived from CPUs available]\n" 194 " -l N do not start new jobs if the load average is greater than N\n" 196 " (not yet implemented on Windows)\n" 198 " -k N keep going until N jobs fail [default=1]\n" 199 " -n dry run (don't run commands but act like they succeeded)\n" 200 " -v show all command lines while building\n" 202 " -d MODE enable debugging (use -d list to list modes)\n" 203 " -t TOOL run a subtool (use -t list to list subtools)\n" 204 " terminates toplevel options; further flags are passed to the tool\n",
209 int GuessParallelism() {
217 return processors + 2;
224 virtual bool ReadFile(
const string& path,
string* content,
string* err) {
231 bool NinjaMain::RebuildManifest(
const char* input_file,
string* err) {
232 string path = input_file;
239 Builder builder(&state_, config_, &build_log_, &deps_log_, &disk_interface_);
240 if (!builder.AddTarget(node, err))
243 if (builder.AlreadyUpToDate())
245 if (!builder.Build(err))
250 return node->
dirty();
253 Node* NinjaMain::CollectTarget(
const char* cpath,
string* err) {
259 bool first_dependent =
false;
260 if (!path.empty() && path[path.size() - 1] ==
'^') {
261 path.resize(path.size() - 1);
262 first_dependent =
true;
267 if (first_dependent) {
269 *err =
"'" + path +
"' has no out edge";
275 Fatal(
"edge has no outputs");
281 *err =
"unknown target '" + path +
"'";
283 if (path ==
"clean") {
284 *err +=
", did you mean 'ninja -t clean'?";
285 }
else if (path ==
"help") {
286 *err +=
", did you mean 'ninja -h'?";
290 *err +=
", did you mean '" + suggestion->
path() +
"'?";
297 bool NinjaMain::CollectTargetsFromArgs(
int argc,
char* argv[],
298 vector<Node*>* targets,
string* err) {
304 for (
int i = 0; i < argc; ++i) {
305 Node* node = CollectTarget(argv[i], err);
308 targets->push_back(node);
313 int NinjaMain::ToolGraph(
int argc,
char* argv[]) {
316 if (!CollectTargetsFromArgs(argc, argv, &nodes, &err)) {
317 Error(
"%s", err.c_str());
323 for (vector<Node*>::const_iterator n = nodes.begin(); n != nodes.end(); ++n)
330 int NinjaMain::ToolQuery(
int argc,
char* argv[]) {
332 Error(
"expected a target to query");
336 for (
int i = 0; i < argc; ++i) {
338 Node* node = CollectTarget(argv[i], &err);
340 Error(
"%s", err.c_str());
344 printf(
"%s:\n", node->
path().c_str());
346 printf(
" input: %s\n", edge->
rule_->
name().c_str());
347 for (
int in = 0; in < (int)edge->
inputs_.size(); in++) {
348 const char* label =
"";
353 printf(
" %s%s\n", label, edge->
inputs_[in]->path().c_str());
356 printf(
" outputs:\n");
357 for (vector<Edge*>::const_iterator edge = node->
out_edges().begin();
358 edge != node->
out_edges().end(); ++edge) {
359 for (vector<Node*>::iterator out = (*edge)->outputs_.begin();
360 out != (*edge)->outputs_.end(); ++out) {
361 printf(
" %s\n", (*out)->path().c_str());
368 #if !defined(_WIN32) && !defined(NINJA_BOOTSTRAP) 369 int NinjaMain::ToolBrowse(
int argc,
char* argv[]) {
371 Error(
"expected a target to browse");
380 #if defined(_MSC_VER) 381 int NinjaMain::ToolMSVC(
int argc,
char* argv[]) {
390 int ToolTargetsList(
const vector<Node*>& nodes,
int depth,
int indent) {
391 for (vector<Node*>::const_iterator n = nodes.begin();
394 for (
int i = 0; i < indent; ++i)
396 const char* target = (*n)->path().c_str();
397 if ((*n)->in_edge()) {
398 printf(
"%s: %s\n", target, (*n)->in_edge()->rule_->name().c_str());
399 if (depth > 1 || depth <= 0)
400 ToolTargetsList((*n)->in_edge()->inputs_, depth - 1, indent + 1);
402 printf(
"%s\n", target);
408 int ToolTargetsSourceList(
State* state) {
409 for (vector<Edge*>::iterator e = state->
edges_.begin();
410 e != state->
edges_.end(); ++e) {
411 for (vector<Node*>::iterator inps = (*e)->inputs_.begin();
412 inps != (*e)->inputs_.end(); ++inps) {
413 if (!(*inps)->in_edge())
414 printf(
"%s\n", (*inps)->path().c_str());
420 int ToolTargetsList(
State* state,
const string& rule_name) {
424 for (vector<Edge*>::iterator e = state->
edges_.begin();
425 e != state->
edges_.end(); ++e) {
426 if ((*e)->rule_->name() == rule_name) {
427 for (vector<Node*>::iterator out_node = (*e)->outputs_.begin();
428 out_node != (*e)->outputs_.end(); ++out_node) {
429 rules.insert((*out_node)->path());
435 for (set<string>::const_iterator i = rules.begin();
436 i != rules.end(); ++i) {
437 printf(
"%s\n", (*i).c_str());
443 int ToolTargetsList(
State* state) {
444 for (vector<Edge*>::iterator e = state->
edges_.begin();
445 e != state->
edges_.end(); ++e) {
446 for (vector<Node*>::iterator out_node = (*e)->outputs_.begin();
447 out_node != (*e)->outputs_.end(); ++out_node) {
449 (*out_node)->path().c_str(),
450 (*e)->rule_->name().c_str());
456 int NinjaMain::ToolDeps(
int argc,
char** argv) {
459 for (vector<Node*>::const_iterator ni = deps_log_.
nodes().begin();
460 ni != deps_log_.
nodes().end(); ++ni) {
462 nodes.push_back(*ni);
466 if (!CollectTargetsFromArgs(argc, argv, &nodes, &err)) {
467 Error(
"%s", err.c_str());
473 for (vector<Node*>::iterator it = nodes.begin(), end = nodes.end();
477 printf(
"%s: deps not found\n", (*it)->path().c_str());
482 printf(
"%s: #deps %d, deps mtime %d (%s)\n",
484 (!mtime || mtime > deps->
mtime ?
"STALE":
"VALID"));
486 printf(
" %s\n", deps->
nodes[i]->
path().c_str());
493 int NinjaMain::ToolTargets(
int argc,
char* argv[]) {
496 string mode = argv[0];
497 if (mode ==
"rule") {
502 return ToolTargetsSourceList(&state_);
504 return ToolTargetsList(&state_, rule);
505 }
else if (mode ==
"depth") {
507 depth = atoi(argv[1]);
508 }
else if (mode ==
"all") {
509 return ToolTargetsList(&state_);
511 const char* suggestion =
514 Error(
"unknown target tool mode '%s', did you mean '%s'?",
515 mode.c_str(), suggestion);
517 Error(
"unknown target tool mode '%s'", mode.c_str());
524 vector<Node*> root_nodes = state_.
RootNodes(&err);
526 return ToolTargetsList(root_nodes, depth, 0);
528 Error(
"%s", err.c_str());
533 void PrintCommands(
Edge* edge, set<Edge*>* seen) {
536 if (!seen->insert(edge).second)
539 for (vector<Node*>::iterator in = edge->
inputs_.begin();
540 in != edge->
inputs_.end(); ++in)
541 PrintCommands((*in)->in_edge(), seen);
547 int NinjaMain::ToolCommands(
int argc,
char* argv[]) {
550 if (!CollectTargetsFromArgs(argc, argv, &nodes, &err)) {
551 Error(
"%s", err.c_str());
556 for (vector<Node*>::iterator in = nodes.begin(); in != nodes.end(); ++in)
557 PrintCommands((*in)->in_edge(), &seen);
562 int NinjaMain::ToolClean(
int argc,
char* argv[]) {
568 bool generator =
false;
569 bool clean_rules =
false;
573 while ((opt =
getopt(argc, argv, const_cast<char*>(
"hgr"))) != -1) {
583 printf(
"usage: ninja -t clean [options] [targets]\n" 586 " -g also clean files marked as ninja generator output\n" 587 " -r interpret targets as a list of rules to clean instead\n" 595 if (clean_rules && argc == 0) {
596 Error(
"expected a rule to clean");
600 Cleaner cleaner(&state_, config_);
603 return cleaner.CleanRules(argc, argv);
605 return cleaner.CleanTargets(argc, argv);
607 return cleaner.CleanAll(generator);
611 void EncodeJSONString(
const char *str) {
613 if (*str ==
'"' || *str ==
'\\')
620 int NinjaMain::ToolCompilationDatabase(
int argc,
char* argv[]) {
625 cwd.resize(cwd.size() + 1024);
627 }
while (!getcwd(&cwd[0], cwd.size()) && errno == ERANGE);
628 if (errno != 0 && errno != ERANGE) {
629 Error(
"cannot determine working directory: %s", strerror(errno));
634 for (vector<Edge*>::iterator e = state_.
edges_.begin();
635 e != state_.
edges_.end(); ++e) {
636 if ((*e)->inputs_.empty())
638 for (
int i = 0; i != argc; ++i) {
639 if ((*e)->rule_->name() == argv[i]) {
643 printf(
"\n {\n \"directory\": \"");
644 EncodeJSONString(&cwd[0]);
645 printf(
"\",\n \"command\": \"");
646 EncodeJSONString((*e)->EvaluateCommand().c_str());
647 printf(
"\",\n \"file\": \"");
648 EncodeJSONString((*e)->inputs_[0]->path().c_str());
660 int NinjaMain::ToolRecompact(
int argc,
char* argv[]) {
661 if (!EnsureBuildDirExists())
664 if (!OpenBuildLog(
true) ||
671 int NinjaMain::ToolUrtle(
int argc,
char** argv) {
674 " 13 ,3;2!2;\n8 ,;<11!;\n5 `'<10!(2`'2!\n11 ,6;, `\\. `\\9 .,c13$ec,.\n6 " 675 ",2;11!>; `. ,;!2> .e8$2\".2 \"?7$e.\n <:<8!'` 2.3,.2` ,3!' ;,(?7\";2!2'<" 676 "; `?6$PF ,;,\n2 `'4!8;<!3'`2 3! ;,`'2`2'3!;4!`2.`!;2 3,2 .<!2'`).\n5 3`5" 677 "'2`9 `!2 `4!><3;5! J2$b,`!>;2!:2!`,d?b`!>\n26 `'-;,(<9!> $F3 )3.:!.2 d\"" 678 "2 ) !>\n30 7`2'<3!- \"=-='5 .2 `2-=\",!>\n25 .ze9$er2 .,cd16$bc.'\n22 .e" 679 "14$,26$.\n21 z45$c .\n20 J50$c\n20 14$P\"`?34$b\n20 14$ dbc `2\"?22$?7$c" 680 "\n20 ?18$c.6 4\"8?4\" c8$P\n9 .2,.8 \"20$c.3 ._14 J9$\n .2,2c9$bec,.2 `?" 681 "21$c.3`4%,3%,3 c8$P\"\n22$c2 2\"?21$bc2,.2` .2,c7$P2\",cb\n23$b bc,.2\"2" 682 "?14$2F2\"5?2\",J5$P\" ,zd3$\n24$ ?$3?%3 `2\"2?12$bcucd3$P3\"2 2=7$\n23$P" 683 "\" ,3;<5!>2;,. `4\"6?2\"2 ,9;, `\"?2$\n";
685 for (
const char* p = urtle; *p; p++) {
686 if (
'0' <= *p && *p <=
'9') {
687 count = count*10 + *p -
'0';
689 for (
int i = 0; i < std::max(count, 1); ++i)
699 const Tool* ChooseTool(
const string& tool_name) {
700 static const Tool kTools[] = {
701 #if !defined(_WIN32) && !defined(NINJA_BOOTSTRAP) 702 {
"browse",
"browse dependency graph in a web browser",
703 Tool::RUN_AFTER_LOAD, &NinjaMain::ToolBrowse },
705 #if defined(_MSC_VER) 706 {
"msvc",
"build helper for MSVC cl.exe (EXPERIMENTAL)",
707 Tool::RUN_AFTER_FLAGS, &NinjaMain::ToolMSVC },
709 {
"clean",
"clean built files",
710 Tool::RUN_AFTER_LOAD, &NinjaMain::ToolClean },
711 {
"commands",
"list all commands required to rebuild given targets",
712 Tool::RUN_AFTER_LOAD, &NinjaMain::ToolCommands },
713 {
"deps",
"show dependencies stored in the deps log",
714 Tool::RUN_AFTER_LOGS, &NinjaMain::ToolDeps },
715 {
"graph",
"output graphviz dot file for targets",
716 Tool::RUN_AFTER_LOAD, &NinjaMain::ToolGraph },
717 {
"query",
"show inputs/outputs for a path",
718 Tool::RUN_AFTER_LOGS, &NinjaMain::ToolQuery },
719 {
"targets",
"list targets by their rule or depth in the DAG",
720 Tool::RUN_AFTER_LOAD, &NinjaMain::ToolTargets },
721 {
"compdb",
"dump JSON compilation database to stdout",
722 Tool::RUN_AFTER_LOAD, &NinjaMain::ToolCompilationDatabase },
723 {
"recompact",
"recompacts ninja-internal data structures",
724 Tool::RUN_AFTER_LOAD, &NinjaMain::ToolRecompact },
726 Tool::RUN_AFTER_FLAGS, &NinjaMain::ToolUrtle },
727 { NULL, NULL, Tool::RUN_AFTER_FLAGS, NULL }
730 if (tool_name ==
"list") {
731 printf(
"ninja subtools:\n");
732 for (
const Tool* tool = &kTools[0]; tool->name; ++tool) {
734 printf(
"%10s %s\n", tool->name, tool->desc);
739 for (
const Tool* tool = &kTools[0]; tool->name; ++tool) {
740 if (tool->name == tool_name)
744 vector<const char*> words;
745 for (
const Tool* tool = &kTools[0]; tool->name; ++tool)
746 words.push_back(tool->name);
749 Fatal(
"unknown tool '%s', did you mean '%s'?",
750 tool_name.c_str(), suggestion);
752 Fatal(
"unknown tool '%s'", tool_name.c_str());
759 bool DebugEnable(
const string& name) {
760 if (name ==
"list") {
761 printf(
"debugging modes:\n" 762 " stats print operation counts/timing info\n" 763 " explain explain what caused a command to execute\n" 764 " keeprsp don't delete @response files on success\n" 766 " nostatcache don't batch stat() calls per directory and cache them\n" 768 "multiple modes can be enabled via -d FOO -d BAR\n");
770 }
else if (name ==
"stats") {
773 }
else if (name ==
"explain") {
776 }
else if (name ==
"keeprsp") {
779 }
else if (name ==
"nostatcache") {
783 const char* suggestion =
785 "nostatcache", NULL);
787 Error(
"unknown debug setting '%s', did you mean '%s'?",
788 name.c_str(), suggestion);
790 Error(
"unknown debug setting '%s'", name.c_str());
796 bool NinjaMain::OpenBuildLog(
bool recompact_only) {
797 string log_path =
".ninja_log";
798 if (!build_dir_.empty())
799 log_path = build_dir_ +
"/" + log_path;
802 if (!build_log_.
Load(log_path, &err)) {
803 Error(
"loading build log %s: %s", log_path.c_str(), err.c_str());
812 if (recompact_only) {
813 bool success = build_log_.
Recompact(log_path, *
this, &err);
815 Error(
"failed recompaction: %s", err.c_str());
821 Error(
"opening build log: %s", err.c_str());
831 bool NinjaMain::OpenDepsLog(
bool recompact_only) {
832 string path =
".ninja_deps";
833 if (!build_dir_.empty())
834 path = build_dir_ +
"/" + path;
837 if (!deps_log_.
Load(path, &state_, &err)) {
838 Error(
"loading deps log %s: %s", path.c_str(), err.c_str());
847 if (recompact_only) {
848 bool success = deps_log_.
Recompact(path, &err);
850 Error(
"failed recompaction: %s", err.c_str());
856 Error(
"opening deps log: %s", err.c_str());
864 void NinjaMain::DumpMetrics() {
868 int count = (int)state_.
paths_.size();
869 int buckets = (int)state_.
paths_.bucket_count();
870 printf(
"path->node hash load %.2f (%d entries / %d buckets)\n",
871 count / (
double) buckets, count, buckets);
874 bool NinjaMain::EnsureBuildDirExists() {
876 if (!build_dir_.empty() && !config_.
dry_run) {
877 if (!disk_interface_.
MakeDirs(build_dir_ +
"/.") && errno != EEXIST) {
878 Error(
"creating build directory %s: %s",
879 build_dir_.c_str(), strerror(errno));
886 int NinjaMain::RunBuild(
int argc,
char** argv) {
888 vector<Node*> targets;
889 if (!CollectTargetsFromArgs(argc, argv, &targets, &err)) {
890 Error(
"%s", err.c_str());
896 Builder builder(&state_, config_, &build_log_, &deps_log_, &disk_interface_);
897 for (
size_t i = 0; i < targets.size(); ++i) {
898 if (!builder.AddTarget(targets[i], &err)) {
900 Error(
"%s", err.c_str());
912 if (builder.AlreadyUpToDate()) {
913 printf(
"ninja: no work to do.\n");
917 if (!builder.Build(&err)) {
918 printf(
"ninja: build stopped: %s.\n", err.c_str());
919 if (err.find(
"interrupted by user") != string::npos) {
935 void TerminateHandler() {
937 Fatal(
"terminate handler called");
942 int ExceptionFilter(
unsigned int code,
struct _EXCEPTION_POINTERS *ep) {
943 Error(
"exception: 0x%X", code);
946 return EXCEPTION_EXECUTE_HANDLER;
953 int ReadFlags(
int* argc,
char*** argv,
957 enum { OPT_VERSION = 1 };
958 const option kLongOptions[] = {
965 while (!options->tool &&
966 (opt =
getopt_long(*argc, *argv,
"d:f:j:k:l:nt:vC:h", kLongOptions,
974 options->input_file =
optarg;
978 int value = strtol(
optarg, &end, 10);
979 if (*end != 0 || value <= 0)
980 Fatal(
"invalid -j parameter");
986 int value = strtol(
optarg, &end, 10);
988 Fatal(
"-k parameter not numeric; did you mean -k 0?");
998 double value = strtod(
optarg, &end);
1000 Fatal(
"-l parameter not numeric: did you mean -l 0.0?");
1008 options->tool = ChooseTool(
optarg);
1016 options->working_dir =
optarg;
1033 int real_main(
int argc,
char** argv) {
1035 Options options = {};
1036 options.input_file =
"build.ninja";
1038 setvbuf(stdout, NULL, _IOLBF, BUFSIZ);
1039 const char* ninja_command = argv[0];
1041 int exit_code = ReadFlags(&argc, &argv, &options, &config);
1045 if (options.tool && options.tool->when == Tool::RUN_AFTER_FLAGS) {
1048 NinjaMain ninja(ninja_command, config);
1049 return (ninja.*options.tool->func)(argc, argv);
1052 if (options.working_dir) {
1059 printf(
"ninja: Entering directory `%s'\n", options.working_dir);
1060 if (chdir(options.working_dir) < 0) {
1061 Fatal(
"chdir to '%s' - %s", options.working_dir, strerror(errno));
1067 for (
int cycle = 0; cycle < 2; ++cycle) {
1068 NinjaMain ninja(ninja_command, config);
1070 RealFileReader file_reader;
1073 if (!parser.Load(options.input_file, &err)) {
1074 Error(
"%s", err.c_str());
1078 if (options.tool && options.tool->when == Tool::RUN_AFTER_LOAD)
1079 return (ninja.*options.tool->func)(argc, argv);
1081 if (!ninja.EnsureBuildDirExists())
1084 if (!ninja.OpenBuildLog() || !ninja.OpenDepsLog())
1087 if (options.tool && options.tool->when == Tool::RUN_AFTER_LOGS)
1088 return (ninja.*options.tool->func)(argc, argv);
1093 if (ninja.RebuildManifest(options.input_file, &err)) {
1096 }
else if (!err.empty()) {
1097 Error(
"rebuilding '%s': %s", options.input_file, err.c_str());
1102 int result = ninja.RunBuild(argc, argv);
1104 ninja.DumpMetrics();
1114 #if !defined(NINJA_BOOTSTRAP) && defined(_MSC_VER) 1117 set_terminate(TerminateHandler);
1121 return real_main(argc, argv);
1123 __except(ExceptionFilter(GetExceptionCode(), GetExceptionInformation())) {
1129 return real_main(argc, argv);
void Report()
Print a summary report to stdout.
const char * SpellcheckString(const char *text,...)
Like SpellcheckStringV, but takes a NULL-terminated list.
vector< Edge * > edges_
All the edges of the graph.
bool Recompact(const string &path, const BuildLogUser &user, string *err)
Rewrite the known log entries, throwing away old data.
double max_load_average
The maximum load average we must not exceed.
int MSVCHelperMain(int argc, char **argv)
StringPiece represents a slice of a string whose memory is managed externally.
bool MakeDirs(const string &path)
Create all the parent directories for path; like mkdir -p basename path.
Information about a node in the dependency graph: the file, whether it's dirty, mtime, etc.
Node * SpellcheckNode(const string &path)
string AsString() const
Convert the slice into a full-fledged std::string, copying the data into a new string.
void Dump(const char *prefix="") const
An edge in the dependency graph; links between Nodes using Rules.
const char * kNinjaVersion
The version number of the current Ninja release.
Store a log of every command ran for every build.
string EvaluateCommand(bool incl_rsp_file=false)
Expand all variables in a command and return it as a string.
bool is_order_only(size_t index)
void RunBrowsePython(State *state, const char *ninja_command, const char *initial_target)
Run in "browse" mode, which execs a Python webserver.
bool CanonicalizePath(string *path, string *err)
Canonicalize a path like "foo/../bar.h" into just "bar.h".
virtual TimeStamp Stat(const string &path) const
stat() a file, returning the mtime, or 0 if missing and -1 on other errors.
void CreateWin32MiniDump(_EXCEPTION_POINTERS *pep)
Creates a windows minidump in temp folder.
As build commands run they can output extra dependency information (e.g.
bool OpenForWrite(const string &path, const BuildLogUser &user, string *err)
Implementation of DiskInterface that actually hits the disk.
bool OpenForWrite(const string &path, string *err)
bool is_implicit(size_t index)
vector< Node * > DefaultNodes(string *error)
int getopt_long(int argc, char **argv, const char *shortopts, const GETOPT_LONG_OPTION_T *longopts, int *longind)
Deps * GetDeps(Node *node)
bool Load(const string &path, State *state, string *err)
int getopt(int argc, char **argv, char *optstring)
virtual string LookupVariable(const string &var)
bool Recompact(const string &path, string *err)
Rewrite the known log entries, throwing away old data.
int ReadFile(const string &path, string *contents, string *err)
Read a file to a string (in text mode: with CRLF conversion on Windows).
int main(int argc, char **argv)
vector< Node * > RootNodes(string *error)
const string & path() const
bool g_experimental_statcache
Builder wraps the build process: starting commands, updating status.
void Fatal(const char *msg,...)
Log a fatal message and exit.
const char * SpellcheckStringV(const string &text, const vector< const char * > &words)
Given a misspelled string and a list of correct spellings, returns the closest match or NULL if there...
The singleton that stores metrics and prints the report.
Runs the process of creating GraphViz .dot file output.
void AllowStatCache(bool allow)
Whether stat information can be cached. Only has an effect on Windows.
Options (e.g. verbosity, parallelism) passed to a build.
Global state (file status, loaded rules) for a single run.
const string & name() const
const vector< Node * > & nodes() const
Used for tests.
bool Load(const string &path, string *err)
Load the on-disk log.
void Warning(const char *msg,...)
Log a warning message.
void AddTarget(Node *node)
const vector< Edge * > & out_edges() const
void Error(const char *msg,...)
Log an error message.
bool IsDepsEntryLiveFor(Node *node)
Returns if the deps entry for a node is still reachable from the manifest.
Node * LookupNode(StringPiece path) const
Can answer questions about the manifest for the BuildLog.
vector< Node * > outputs_