From 43d8568acd65e51e978a9ac19908b444c0ef141f Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Tue, 15 Nov 2016 16:05:34 -0800 Subject: [PATCH] Put builder output through status interface Send all output after manifest parsing is finished to the Status interface, so that when status frontends are added they can handle build messages. --- src/build.cc | 2 +- src/ninja.cc | 25 +++++++++++++------------ src/status.cc | 22 ++++++++++++++++++++++ src/status.h | 10 ++++++++++ src/util.cc | 30 +++++++++++++++++++++++++----- src/util.h | 8 ++++++++ 6 files changed, 79 insertions(+), 18 deletions(-) diff --git a/src/build.cc b/src/build.cc index a1bdfebeb7..5cd29c1f24 100644 --- a/src/build.cc +++ b/src/build.cc @@ -535,7 +535,7 @@ void Builder::Cleanup() { string err; TimeStamp new_mtime = disk_interface_->Stat((*o)->path(), &err); if (new_mtime == -1) // Log and ignore Stat() errors. - Error("%s", err.c_str()); + status_->Error("%s", err.c_str()); if (!depfile.empty() || (*o)->mtime() != new_mtime) disk_interface_->RemoveFile((*o)->path()); } diff --git a/src/ninja.cc b/src/ninja.cc index df3db35eb7..5f9a8110c3 100644 --- a/src/ninja.cc +++ b/src/ninja.cc @@ -244,7 +244,7 @@ int GuessParallelism() { /// Rebuild the build manifest, if necessary. /// Returns true if the manifest was rebuilt. bool NinjaMain::RebuildManifest(const char* input_file, string* err, - Status *status) { + Status* status) { string path = input_file; uint64_t slash_bits; // Unused because this path is only used for lookup. if (!CanonicalizePath(&path, &slash_bits, err)) @@ -1124,7 +1124,7 @@ int NinjaMain::RunBuild(int argc, char** argv, Status* status) { string err; vector targets; if (!CollectTargetsFromArgs(argc, argv, &targets, &err)) { - Error("%s", err.c_str()); + status->Error("%s", err.c_str()); return 1; } @@ -1135,7 +1135,7 @@ int NinjaMain::RunBuild(int argc, char** argv, Status* status) { for (size_t i = 0; i < targets.size(); ++i) { if (!builder.AddTarget(targets[i], &err)) { if (!err.empty()) { - Error("%s", err.c_str()); + status->Error("%s", err.c_str()); return 1; } else { // Added a target that is already up-to-date; not really @@ -1148,12 +1148,12 @@ int NinjaMain::RunBuild(int argc, char** argv, Status* status) { disk_interface_.AllowStatCache(false); if (builder.AlreadyUpToDate()) { - printf("ninja: no work to do.\n"); + status->Info("no work to do."); return 0; } if (!builder.Build(&err)) { - printf("ninja: build stopped: %s.\n", err.c_str()); + status->Info("build stopped: %s.", err.c_str()); if (err.find("interrupted by user") != string::npos) { return 2; } @@ -1296,8 +1296,6 @@ NORETURN void real_main(int argc, char** argv) { kDepfileDistinctTargetLinesActionError; } - Status* status = new StatusPrinter(config); - if (options.working_dir) { // The formatting of this string, complete with funny quotes, is // so Emacs can properly identify that the cwd has changed for @@ -1305,9 +1303,10 @@ NORETURN void real_main(int argc, char** argv) { // Don't print this if a tool is being used, so that tool output // can be piped into a file without this string showing up. if (!options.tool) - printf("ninja: Entering directory `%s'\n", options.working_dir); + Info("Entering directory `%s'", options.working_dir); if (chdir(options.working_dir) < 0) { - Fatal("chdir to '%s' - %s", options.working_dir, strerror(errno)); + Error("chdir to '%s' - %s", options.working_dir, strerror(errno)); + return 1; } } @@ -1318,6 +1317,8 @@ NORETURN void real_main(int argc, char** argv) { exit((ninja.*options.tool->func)(&options, argc, argv)); } + Status* status = new StatusPrinter(config); + // Limit number of rebuilds, to prevent infinite loops. const int kCycleLimit = 100; for (int cycle = 1; cycle <= kCycleLimit; ++cycle) { @@ -1333,7 +1334,7 @@ NORETURN void real_main(int argc, char** argv) { ManifestParser parser(&ninja.state_, &ninja.disk_interface_, parser_opts); string err; if (!parser.Load(options.input_file, &err)) { - Error("%s", err.c_str()); + status->Error("%s", err.c_str()); exit(1); } @@ -1358,7 +1359,7 @@ NORETURN void real_main(int argc, char** argv) { // Start the build over with the new manifest. continue; } else if (!err.empty()) { - Error("rebuilding '%s': %s", options.input_file, err.c_str()); + status->Error("rebuilding '%s': %s", options.input_file, err.c_str()); exit(1); } @@ -1368,7 +1369,7 @@ NORETURN void real_main(int argc, char** argv) { exit(result); } - Error("manifest '%s' still dirty after %d tries\n", + status->Error("manifest '%s' still dirty after %d tries", options.input_file, kCycleLimit); exit(1); } diff --git a/src/status.cc b/src/status.cc index eb15682cc5..12d559939f 100644 --- a/src/status.cc +++ b/src/status.cc @@ -14,6 +14,7 @@ #include "status.h" +#include #include #ifdef _WIN32 @@ -242,3 +243,24 @@ void StatusPrinter::PrintStatus(Edge* edge, int64_t time_millis) { printer_.Print(to_print, force_full_command ? LinePrinter::FULL : LinePrinter::ELIDE); } + +void StatusPrinter::Warning(const char* msg, ...) { + va_list ap; + va_start(ap, msg); + ::Warning(msg, ap); + va_end(ap); +} + +void StatusPrinter::Error(const char* msg, ...) { + va_list ap; + va_start(ap, msg); + ::Error(msg, ap); + va_end(ap); +} + +void StatusPrinter::Info(const char* msg, ...) { + va_list ap; + va_start(ap, msg); + ::Info(msg, ap); + va_end(ap); +} diff --git a/src/status.h b/src/status.h index 91b35ec6e0..0ab2811bc6 100644 --- a/src/status.h +++ b/src/status.h @@ -32,6 +32,11 @@ struct Status { virtual void BuildLoadDyndeps() = 0; virtual void BuildStarted() = 0; virtual void BuildFinished() = 0; + + virtual void Info(const char* msg, ...) = 0; + virtual void Warning(const char* msg, ...) = 0; + virtual void Error(const char* msg, ...) = 0; + virtual ~Status() { } }; @@ -46,6 +51,11 @@ struct StatusPrinter : Status { virtual void BuildLoadDyndeps(); virtual void BuildStarted(); virtual void BuildFinished(); + + virtual void Info(const char* msg, ...); + virtual void Warning(const char* msg, ...); + virtual void Error(const char* msg, ...); + virtual ~StatusPrinter() { } /// Format the progress status string by replacing the placeholders. diff --git a/src/util.cc b/src/util.cc index 666cf9d3ff..5e5cb51647 100644 --- a/src/util.cc +++ b/src/util.cc @@ -56,7 +56,6 @@ void Fatal(const char* msg, ...) { va_list ap; - fprintf(stderr, "ninja: fatal: "); va_start(ap, msg); vfprintf(stderr, msg, ap); va_end(ap); @@ -72,24 +71,45 @@ void Fatal(const char* msg, ...) { #endif } +void Warning(const char* msg, va_list ap) { + fprintf(stderr, "ninja: warning: "); + vfprintf(stderr, msg, ap); + fprintf(stderr, "\n"); +} + void Warning(const char* msg, ...) { va_list ap; - fprintf(stderr, "ninja: warning: "); va_start(ap, msg); - vfprintf(stderr, msg, ap); + Warning(msg, ap); va_end(ap); +} + +void Error(const char* msg, va_list ap) { + fprintf(stderr, "ninja: error: "); + vfprintf(stderr, msg, ap); fprintf(stderr, "\n"); } void Error(const char* msg, ...) { va_list ap; - fprintf(stderr, "ninja: error: "); va_start(ap, msg); - vfprintf(stderr, msg, ap); + Error(msg, ap); va_end(ap); +} + +void Info(const char* msg, va_list ap) { + fprintf(stderr, "ninja: "); + vfprintf(stderr, msg, ap); fprintf(stderr, "\n"); } +void Info(const char* msg, ...) { + va_list ap; + va_start(ap, msg); + Info(msg, ap); + va_end(ap); +} + bool CanonicalizePath(string* path, uint64_t* slash_bits, string* err) { METRIC_RECORD("canonicalize str"); size_t len = path->size(); diff --git a/src/util.h b/src/util.h index 6a4a7a9f84..bb958eb606 100644 --- a/src/util.h +++ b/src/util.h @@ -21,6 +21,8 @@ #include #endif +#include + #include #include using namespace std; @@ -50,9 +52,15 @@ NORETURN void Fatal(const char* msg, ...); /// Log a warning message. void Warning(const char* msg, ...); +void Warning(const char* msg, va_list ap); /// Log an error message. void Error(const char* msg, ...); +void Error(const char* msg, va_list ap); + +/// Log an informational message. +void Info(const char* msg, ...); +void Info(const char* msg, va_list ap); /// Canonicalize a path like "foo/../bar.h" into just "bar.h". /// |slash_bits| has bits set starting from lowest for a backslash that was