Introduce NINJA_STATUS env var for customization.

Some people may want to display different relevant information about
the progress of the build.  Also it can be usefull to debug jobs
allocation.
This commit is contained in:
Nicolas Despres 2012-04-19 14:26:33 +02:00
parent 34ff2d9cf2
commit 34ad4de664
2 changed files with 96 additions and 2 deletions

View File

@ -375,6 +375,23 @@ depfiles are not removed. Files created but not referenced in the
graph are not removed. This tool takes in account the +-v+ and the
+-n+ options (note that +-n+ implies +-v+).
Environment variables
---------------------
Ninja supports various environment variables to control its behavior.
`NINJA_STATUS`:: The progress status printed before the rule being run.
Several placeholders are available:
* `%s`: The number of started edges.
* `%t`: The total number of edges that must be run to complete the build.
* `%r`: The number of currently running edges.
* `%u`: The number of remaining edges to start.
* `%f`: The number of finished edges.
* `%%`: A plain `%` character.
* The default progress status is `"[%s/%t] "` (note the trailing space
to separate from the build rule). Another example of possible progress status
could be `"[%u/%r/%f] "`.
Ninja file reference
--------------------

View File

@ -44,6 +44,14 @@ struct BuildStatus {
private:
void PrintStatus(Edge* edge);
/// Print the progress status.
///
/// Get the status from the NINJA_STATUS environment variable if defined.
/// See the user manual for more information about the available
/// placeholders.
///
/// @return The number of printed characters.
int PrintProgressStatus() const;
const BuildConfig& config_;
@ -63,6 +71,9 @@ struct BuildStatus {
/// Whether we can do fancy terminal control codes.
bool smart_terminal_;
/// The custom progress status format to use.
const char* progress_status_format_;
#ifdef _WIN32
HANDLE console_;
#endif
@ -73,7 +84,7 @@ BuildStatus::BuildStatus(const BuildConfig& config)
start_time_millis_(GetTimeMillis()),
last_update_millis_(start_time_millis_),
started_edges_(0), finished_edges_(0), total_edges_(0),
have_blank_line_(true) {
have_blank_line_(true), progress_status_format_(NULL) {
#ifndef _WIN32
const char* term = getenv("TERM");
smart_terminal_ = isatty(1) && term && string(term) != "dumb";
@ -91,6 +102,10 @@ BuildStatus::BuildStatus(const BuildConfig& config)
// Don't do anything fancy in verbose mode.
if (config_.verbosity != BuildConfig::NORMAL)
smart_terminal_ = false;
progress_status_format_ = getenv("NINJA_STATUS");
if (progress_status_format_ == NULL)
progress_status_format_ = "[%s/%t] ";
}
void BuildStatus::PlanHasTotalEdges(int total) {
@ -171,6 +186,68 @@ void BuildStatus::BuildFinished() {
printf("\n");
}
int BuildStatus::PrintProgressStatus() const {
// Print the custom status.
const int kBUFF_SIZE = 1024;
char buff[kBUFF_SIZE] = { '\0' };
int i = 0;
for (const char* s = progress_status_format_;
*s != '\0' && i < kBUFF_SIZE;
++s) {
if (*s == '%') {
++s;
switch(*s) {
case '%':
buff[i] = '%';
++i;
break;
// Started edges.
case 's':
i += snprintf(&buff[i], kBUFF_SIZE - i, "%d", started_edges_);
break;
// Total edges.
case 't':
i += snprintf(&buff[i], kBUFF_SIZE - i, "%d", total_edges_);
break;
// Running edges.
case 'r':
i += snprintf(&buff[i], kBUFF_SIZE - i, "%d",
started_edges_ - finished_edges_);
break;
// Unstarted edges.
case 'u':
i += snprintf(&buff[i], kBUFF_SIZE - i, "%d",
total_edges_ - started_edges_);
break;
// Finished edges.
case 'f':
i += snprintf(&buff[i], kBUFF_SIZE - i, "%d", finished_edges_);
break;
default:
return printf("!! unknown placeholders '%c' in NINJA_STATUS !! ",
*s);
break;
}
} else {
buff[i] = *s;
++i;
}
}
if (i >= kBUFF_SIZE)
return printf("!! custom NINJA_STATUS exceed buffer size %d !! ",
kBUFF_SIZE);
else {
buff[i] = '\0';
return printf("%s", buff);
}
}
void BuildStatus::PrintStatus(Edge* edge) {
if (config_.verbosity == BuildConfig::QUIET)
return;
@ -195,7 +272,7 @@ void BuildStatus::PrintStatus(Edge* edge) {
#endif
}
int progress_chars = printf("[%d/%d] ", started_edges_, total_edges_);
int progress_chars = PrintProgressStatus();
if (smart_terminal_ && !force_full_command) {
#ifndef _WIN32