1// Copyright 2016 Google Inc. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#ifndef NINJA_STATUS_H_
16#define NINJA_STATUS_H_
17
18#include <map>
19#include <string>
20
21#include "build.h"
22#include "line_printer.h"
23
24/// Abstract interface to object that tracks the status of a build:
25/// completion fraction, printing updates.
26struct Status {
27 virtual void PlanHasTotalEdges(int total) = 0;
28 virtual void BuildEdgeStarted(const Edge* edge, int64_t start_time_millis) = 0;
29 virtual void BuildEdgeFinished(Edge* edge, int64_t end_time_millis,
30 bool success, const std::string& output) = 0;
31 virtual void BuildLoadDyndeps() = 0;
32 virtual void BuildStarted() = 0;
33 virtual void BuildFinished() = 0;
34
35 virtual void Info(const char* msg, ...) = 0;
36 virtual void Warning(const char* msg, ...) = 0;
37 virtual void Error(const char* msg, ...) = 0;
38
39 virtual ~Status() { }
40};
41
42/// Implementation of the Status interface that prints the status as
43/// human-readable strings to stdout
44struct StatusPrinter : Status {
45 explicit StatusPrinter(const BuildConfig& config);
46 virtual void PlanHasTotalEdges(int total);
47 virtual void BuildEdgeStarted(const Edge* edge, int64_t start_time_millis);
48 virtual void BuildEdgeFinished(Edge* edge, int64_t end_time_millis,
49 bool success, const std::string& output);
50 virtual void BuildLoadDyndeps();
51 virtual void BuildStarted();
52 virtual void BuildFinished();
53
54 virtual void Info(const char* msg, ...);
55 virtual void Warning(const char* msg, ...);
56 virtual void Error(const char* msg, ...);
57
58 virtual ~StatusPrinter() { }
59
60 /// Format the progress status string by replacing the placeholders.
61 /// See the user manual for more information about the available
62 /// placeholders.
63 /// @param progress_status_format The format of the progress status.
64 /// @param status The status of the edge.
65 std::string FormatProgressStatus(const char* progress_status_format,
66 int64_t time_millis) const;
67
68 private:
69 void PrintStatus(const Edge* edge, int64_t time_millis);
70
71 const BuildConfig& config_;
72
73 int started_edges_, finished_edges_, total_edges_, running_edges_;
74 int64_t time_millis_;
75
76 /// Prints progress output.
77 LinePrinter printer_;
78
79 /// The custom progress status format to use.
80 const char* progress_status_format_;
81
82 template<size_t S>
83 void SnprintfRate(double rate, char(&buf)[S], const char* format) const {
84 if (rate == -1)
85 snprintf(buf, S, "?");
86 else
87 snprintf(buf, S, format, rate);
88 }
89
90 struct SlidingRateInfo {
91 SlidingRateInfo(int n) : rate_(-1), N(n), last_update_(-1) {}
92
93 double rate() { return rate_; }
94
95 void UpdateRate(int update_hint, int64_t time_millis) {
96 if (update_hint == last_update_)
97 return;
98 last_update_ = update_hint;
99
100 if (times_.size() == N)
101 times_.pop();
102 times_.push(time_millis);
103 if (times_.back() != times_.front())
104 rate_ = times_.size() / ((times_.back() - times_.front()) / 1e3);
105 }
106
107 private:
108 double rate_;
109 const size_t N;
110 std::queue<double> times_;
111 int last_update_;
112 };
113
114 mutable SlidingRateInfo current_rate_;
115};
116
117#endif // NINJA_STATUS_H_
118