From ad3d29fb5375c3122b2318ea5efad170b83e74e5 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Tue, 15 Nov 2016 16:05:34 -0800 Subject: 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 | 18 +++++++++--------- src/status.cc | 22 ++++++++++++++++++++++ src/status.h | 12 +++++++++++- src/util.cc | 29 +++++++++++++++++++++++++---- src/util.h | 8 ++++++++ 6 files changed, 76 insertions(+), 15 deletions(-) diff --git a/src/build.cc b/src/build.cc index 3d1e76b..fb5890a 100644 --- a/src/build.cc +++ b/src/build.cc @@ -531,7 +531,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 d92e95b..5053fcd 100644 --- a/src/ninja.cc +++ b/src/ninja.cc @@ -245,7 +245,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)) @@ -1199,7 +1199,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; } @@ -1210,7 +1210,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 @@ -1223,12 +1223,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; } @@ -1375,7 +1375,7 @@ 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); + status->Info("Entering directory `%s'", options.working_dir); if (chdir(options.working_dir) < 0) { Fatal("chdir to '%s' - %s", options.working_dir, strerror(errno)); } @@ -1403,7 +1403,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); } @@ -1428,7 +1428,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); } @@ -1438,7 +1438,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 a308f62..171cbeb 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(const 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 8344b8e..e211ba3 100644 --- a/src/status.h +++ b/src/status.h @@ -31,10 +31,15 @@ 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() { } }; -/// Implementation of the BuildStatus interface that prints the status as +/// Implementation of the Status interface that prints the status as /// human-readable strings to stdout struct StatusPrinter : Status { explicit StatusPrinter(const BuildConfig& config); @@ -45,6 +50,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 05bdb2d..76bc262 100644 --- a/src/util.cc +++ b/src/util.cc @@ -78,24 +78,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 4e6ebb8..15414e1 100644 --- a/src/util.h +++ b/src/util.h @@ -21,6 +21,8 @@ #include #endif +#include + #include #include @@ -49,9 +51,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 -- cgit v0.12