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.
This commit is contained in:
Colin Cross 2016-11-15 16:05:34 -08:00
parent 589f5b2497
commit ad3d29fb53
6 changed files with 76 additions and 15 deletions

View File

@ -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());
}

View File

@ -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<Node*> 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);
}

View File

@ -14,6 +14,7 @@
#include "status.h"
#include <stdarg.h>
#include <stdlib.h>
#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);
}

View File

@ -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.

View File

@ -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();

View File

@ -21,6 +21,8 @@
#include <stdint.h>
#endif
#include <stdarg.h>
#include <string>
#include <vector>
@ -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