mirror of
https://github.com/ninja-build/ninja.git
synced 2026-06-24 08:48:42 +00:00
Migrate explanation printing from StatusPrinter to Explanations
It makes more sense to live in the latter. Suggested-by: David 'Digit' Turner <digit+github@google.com>
This commit is contained in:
@@ -604,7 +604,7 @@ Builder::Builder(State* state, const BuildConfig& config, BuildLog* build_log,
|
||||
Status* status, int64_t start_time_millis)
|
||||
: state_(state), config_(config), plan_(this), status_(status),
|
||||
start_time_millis_(start_time_millis), disk_interface_(disk_interface),
|
||||
explanations_(g_explaining ? new Explanations() : nullptr),
|
||||
explanations_(g_explaining ? new Explanations(status) : nullptr),
|
||||
scan_(state, build_log, deps_log, disk_interface,
|
||||
&config_.depfile_parser_options, explanations_.get()) {
|
||||
lock_file_path_ = ".ninja_lock";
|
||||
|
||||
@@ -21,6 +21,26 @@
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "graph.h"
|
||||
#include "status_printer.h"
|
||||
|
||||
namespace {
|
||||
void Explain(const char* msg, va_list ap) {
|
||||
fputs("ninja explain: ", stderr);
|
||||
vfprintf(stderr, msg, ap);
|
||||
fputs("\n", stderr);
|
||||
}
|
||||
|
||||
void Explain(const char* msg, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, msg);
|
||||
Explain(msg, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
} // anonymous namespace
|
||||
|
||||
Explanations::Explanations(Status* status) : status_(status) {}
|
||||
|
||||
void Explanations::Record(const void* item, const char* fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
@@ -34,6 +54,24 @@ void Explanations::RecordArgs(const void* item, const char* fmt, va_list args) {
|
||||
map_[item].emplace_back(buffer);
|
||||
}
|
||||
|
||||
void Explanations::ExplainEdge(const Edge* edge) {
|
||||
// Collect all explanations for the current edge's outputs.
|
||||
std::vector<std::string> explanations;
|
||||
for (Node* output : edge->outputs_) {
|
||||
this->LookupAndAppend(output, &explanations);
|
||||
}
|
||||
if (!explanations.empty()) {
|
||||
if (status_) {
|
||||
// Start a new line so that the first explanation
|
||||
// does not append to the status line.
|
||||
status_->NewLine();
|
||||
}
|
||||
for (const auto& exp : explanations) {
|
||||
Explain("%s", exp.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Explanations::LookupAndAppend(const void* item,
|
||||
std::vector<std::string>* out) {
|
||||
auto it = map_.find(item);
|
||||
|
||||
@@ -20,23 +20,32 @@
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
struct Edge;
|
||||
struct Status;
|
||||
|
||||
/// A class used to record a list of explanation strings associated
|
||||
/// with a given 'item' pointer. This is used to implement the
|
||||
/// `-d explain` feature.
|
||||
struct Explanations {
|
||||
public:
|
||||
Explanations(Status* status = nullptr);
|
||||
|
||||
/// Record an explanation for |item| if this instance is enabled.
|
||||
void Record(const void* item, const char* fmt, ...);
|
||||
|
||||
/// Same as Record(), but uses a va_list to pass formatting arguments.
|
||||
void RecordArgs(const void* item, const char* fmt, va_list args);
|
||||
|
||||
/// Print recorded explanations for an edge.
|
||||
void ExplainEdge(const Edge* edge);
|
||||
|
||||
/// Lookup the explanations recorded for |item|, and append them
|
||||
/// to |*out|, if any.
|
||||
void LookupAndAppend(const void* item, std::vector<std::string>* out);
|
||||
|
||||
private:
|
||||
std::unordered_map<const void*, std::vector<std::string>> map_;
|
||||
Status* status_;
|
||||
};
|
||||
|
||||
/// Convenience wrapper for an Explanations pointer, which can be null
|
||||
|
||||
@@ -40,6 +40,9 @@ struct Status {
|
||||
/// (which is the default).
|
||||
virtual void SetExplanations(Explanations*) = 0;
|
||||
|
||||
/// Start a new line so that new output does not append to the status line.
|
||||
virtual void NewLine() = 0;
|
||||
|
||||
virtual void Info(const char* msg, ...) = 0;
|
||||
virtual void Warning(const char* msg, ...) = 0;
|
||||
virtual void Error(const char* msg, ...) = 0;
|
||||
|
||||
@@ -407,19 +407,7 @@ string StatusPrinter::FormatProgressStatus(const char* progress_status_format,
|
||||
|
||||
void StatusPrinter::PrintStatus(const Edge* edge, int64_t time_millis) {
|
||||
if (explanations_) {
|
||||
// Collect all explanations for the current edge's outputs.
|
||||
std::vector<std::string> explanations;
|
||||
for (Node* output : edge->outputs_) {
|
||||
explanations_->LookupAndAppend(output, &explanations);
|
||||
}
|
||||
if (!explanations.empty()) {
|
||||
// Start a new line so that the first explanation does not append to the
|
||||
// status line.
|
||||
printer_.PrintOnNewLine("");
|
||||
for (const auto& exp : explanations) {
|
||||
fprintf(stderr, "ninja explain: %s\n", exp.c_str());
|
||||
}
|
||||
}
|
||||
explanations_->ExplainEdge(edge);
|
||||
}
|
||||
|
||||
if (config_.verbosity == BuildConfig::QUIET
|
||||
@@ -441,6 +429,10 @@ void StatusPrinter::PrintStatus(const Edge* edge, int64_t time_millis) {
|
||||
force_full_command ? LinePrinter::FULL : LinePrinter::ELIDE);
|
||||
}
|
||||
|
||||
void StatusPrinter::NewLine() {
|
||||
printer_.PrintOnNewLine("");
|
||||
}
|
||||
|
||||
void StatusPrinter::Warning(const char* msg, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, msg);
|
||||
|
||||
@@ -37,6 +37,7 @@ struct StatusPrinter : Status {
|
||||
void BuildStarted() override;
|
||||
void BuildFinished() override;
|
||||
|
||||
void NewLine() override;
|
||||
void Info(const char* msg, ...) override;
|
||||
void Warning(const char* msg, ...) override;
|
||||
void Error(const char* msg, ...) override;
|
||||
|
||||
Reference in New Issue
Block a user