summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEvan Martin <martine@danga.com>2011-02-05 19:29:04 (GMT)
committerEvan Martin <martine@danga.com>2011-02-05 19:29:04 (GMT)
commitb9a26e0e5d1045f5814e3ce6341647c92045e3c3 (patch)
tree55eb7e103068c4a8377fa567cc0a0fc2381d608e /src
parent6f3054b9bbfa000510eb0d4d7ca8ae567d186e55 (diff)
downloadNinja-b9a26e0e5d1045f5814e3ce6341647c92045e3c3.zip
Ninja-b9a26e0e5d1045f5814e3ce6341647c92045e3c3.tar.gz
Ninja-b9a26e0e5d1045f5814e3ce6341647c92045e3c3.tar.bz2
fancier output
Diffstat (limited to 'src')
-rw-r--r--src/build.cc64
-rw-r--r--src/build.h9
2 files changed, 58 insertions, 15 deletions
diff --git a/src/build.cc b/src/build.cc
index 3e3482c..b380845 100644
--- a/src/build.cc
+++ b/src/build.cc
@@ -15,6 +15,8 @@ struct BuildStatus {
// Returns the time the edge took, in ms.
int BuildEdgeFinished(Edge* edge);
+ void PrintStatus(Edge* edge);
+
time_t last_update_;
int finished_edges_, total_edges_;
@@ -22,11 +24,16 @@ struct BuildStatus {
RunningEdgeMap running_edges_;
BuildConfig::Verbosity verbosity_;
+ // Whether we can do fancy terminal control codes.
+ bool smart_terminal_;
};
BuildStatus::BuildStatus()
: last_update_(time(NULL)), finished_edges_(0), total_edges_(0),
- verbosity_(BuildConfig::NORMAL) {}
+ verbosity_(BuildConfig::NORMAL) {
+ const char* term = getenv("TERM");
+ smart_terminal_ = isatty(1) && term && string(term) != "dumb";
+}
void BuildStatus::PlanHasTotalEdges(int total) {
total_edges_ = total;
@@ -37,13 +44,7 @@ void BuildStatus::BuildEdgeStarted(Edge* edge) {
gettimeofday(&now, NULL);
running_edges_.insert(make_pair(edge, now));
- string desc = edge->GetDescription();
- if (verbosity_ != BuildConfig::QUIET) {
- if (verbosity_ != BuildConfig::VERBOSE && !desc.empty())
- printf("%s\n", desc.c_str());
- else
- printf("%s\n", edge->EvaluateCommand().c_str());
- }
+ PrintStatus(edge);
}
int BuildStatus::BuildEdgeFinished(Edge* edge) {
@@ -51,10 +52,18 @@ int BuildStatus::BuildEdgeFinished(Edge* edge) {
gettimeofday(&now, NULL);
++finished_edges_;
- if (now.tv_sec - last_update_ > 5) {
- printf("%.1f%% %d/%d\n", finished_edges_ * 100 / (float)total_edges_,
- finished_edges_, total_edges_);
- last_update_ = now.tv_sec;
+ if (verbosity_ != BuildConfig::QUIET) {
+ if (smart_terminal_ && verbosity_ == BuildConfig::NORMAL) {
+ PrintStatus(edge);
+ if (finished_edges_ == total_edges_)
+ printf("\n");
+ } else {
+ if (now.tv_sec - last_update_ > 5) {
+ printf("%.1f%% %d/%d\n", finished_edges_ * 100 / (float)total_edges_,
+ finished_edges_, total_edges_);
+ last_update_ = now.tv_sec;
+ }
+ }
}
RunningEdgeMap::iterator i = running_edges_.find(edge);
@@ -66,6 +75,33 @@ int BuildStatus::BuildEdgeFinished(Edge* edge) {
return ms;
}
+void BuildStatus::PrintStatus(Edge* edge) {
+ switch (verbosity_) {
+ case BuildConfig::QUIET:
+ return;
+
+ case BuildConfig::VERBOSE:
+ printf("%s\n", edge->EvaluateCommand().c_str());
+ break;
+
+ default: {
+ string to_print = edge->GetDescription();
+ if (to_print.empty() || verbosity_ == BuildConfig::VERBOSE)
+ to_print = edge->EvaluateCommand();
+
+ if (smart_terminal_) {
+ printf("\r[%d/%d] %s\e[K", finished_edges_, total_edges_,
+ to_print.c_str());
+ fflush(stdout);
+ } else {
+ printf("%s\n", to_print.c_str());
+ }
+ }
+ }
+}
+
+Plan::Plan() : command_edges_(0) {}
+
bool Plan::AddTarget(Node* node, string* err) {
vector<Node*> stack;
return AddSubTarget(node, &stack, err);
@@ -93,6 +129,8 @@ bool Plan::AddSubTarget(Node* node, vector<Node*>* stack, string* err) {
if (want_.find(edge) != want_.end())
return true; // We've already enqueued it.
want_.insert(edge);
+ if (!edge->is_phony())
+ ++command_edges_;
stack->push_back(node);
bool awaiting_inputs = false;
@@ -302,7 +340,7 @@ bool Builder::Build(string* err) {
return true;
}
- status_->PlanHasTotalEdges(plan_.edge_count());
+ status_->PlanHasTotalEdges(plan_.command_edge_count());
while (plan_.more_to_do()) {
while (command_runner_->CanRunMore()) {
Edge* edge = plan_.FindWork();
diff --git a/src/build.h b/src/build.h
index a1d6d4c..618cc28 100644
--- a/src/build.h
+++ b/src/build.h
@@ -15,6 +15,8 @@ struct State;
// Plan stores the state of a build plan: what we intend to build,
// which steps we're ready to execute.
struct Plan {
+ Plan();
+
// Add a target to our plan (including all its dependencies).
// Returns false if we don't need to build this target; may
// fill in |err| with an error message if there's a problem.
@@ -34,8 +36,8 @@ struct Plan {
// tests.
void EdgeFinished(Edge* edge);
- // Number of edges to run.
- int edge_count() const { return want_.size(); }
+ // Number of edges with commands to run.
+ int command_edge_count() const { return command_edges_; }
private:
bool AddSubTarget(Node* node, vector<Node*>* stack, string* err);
@@ -44,6 +46,9 @@ private:
set<Edge*> want_;
set<Edge*> ready_;
+
+ // Total number of edges that have commands (not phony).
+ int command_edges_;
};
// CommandRunner is an interface that wraps running the build