summaryrefslogtreecommitdiffstats
path: root/src/build.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/build.cc')
-rw-r--r--src/build.cc100
1 files changed, 78 insertions, 22 deletions
diff --git a/src/build.cc b/src/build.cc
index 8e567d9..95f20bc 100644
--- a/src/build.cc
+++ b/src/build.cc
@@ -1,3 +1,17 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
#include "build.h"
#include <stdio.h>
@@ -15,6 +29,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 +38,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 +58,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 +66,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 +89,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 +143,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;
@@ -230,12 +282,16 @@ Edge* RealCommandRunner::NextFinishedCommand(bool* success) {
Edge* edge = i->second;
subproc_to_edge_.erase(i);
- if (!*success)
- printf("FAILED: %s\n", edge->EvaluateCommand().c_str());
- if (!subproc->stdout_.buf_.empty())
- printf("%s\n", subproc->stdout_.buf_.c_str());
- if (!subproc->stderr_.buf_.empty())
- printf("%s\n", subproc->stderr_.buf_.c_str());
+ if (!*success ||
+ !subproc->stdout_.buf_.empty() ||
+ !subproc->stderr_.buf_.empty()) {
+ printf("\n%s%s\n", *success ? "" : "FAILED: ",
+ edge->EvaluateCommand().c_str());
+ if (!subproc->stdout_.buf_.empty())
+ printf("%s\n", subproc->stdout_.buf_.c_str());
+ if (!subproc->stderr_.buf_.empty())
+ printf("%s\n", subproc->stderr_.buf_.c_str());
+ }
delete subproc;
return edge;
@@ -302,7 +358,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();
@@ -312,7 +368,7 @@ bool Builder::Build(string* err) {
if (!StartEdge(edge, err))
return false;
- if (edge->rule_ == &State::kPhonyRule)
+ if (edge->is_phony())
FinishEdge(edge);
}
@@ -338,7 +394,7 @@ bool Builder::Build(string* err) {
}
bool Builder::StartEdge(Edge* edge, string* err) {
- if (edge->rule_ == &State::kPhonyRule)
+ if (edge->is_phony())
return true;
status_->BuildEdgeStarted(edge);
@@ -370,7 +426,7 @@ void Builder::FinishEdge(Edge* edge) {
}
plan_.EdgeFinished(edge);
- if (edge->rule_ == &State::kPhonyRule)
+ if (edge->is_phony())
return;
int ms = status_->BuildEdgeFinished(edge);