From 34ad4de66455d06b5586579f9f304b4c904ac7cc Mon Sep 17 00:00:00 2001 From: Nicolas Despres Date: Thu, 19 Apr 2012 14:26:33 +0200 Subject: 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. --- doc/manual.asciidoc | 17 +++++++++++ src/build.cc | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 96 insertions(+), 2 deletions(-) diff --git a/doc/manual.asciidoc b/doc/manual.asciidoc index a330095..0201820 100644 --- a/doc/manual.asciidoc +++ b/doc/manual.asciidoc @@ -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 -------------------- diff --git a/src/build.cc b/src/build.cc index 6063cec..303f134 100644 --- a/src/build.cc +++ b/src/build.cc @@ -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 -- cgit v0.12