aboutsummaryrefslogtreecommitdiff
path: root/build/trace
blob: 1764a69e397a65dd0ba2db8728d7bb353fe4a389 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
// file      : build/trace -*- C++ -*-
// copyright : Copyright (c) 2014-2015 Code Synthesis Tools CC
// license   : MIT; see accompanying LICENSE file

#ifndef BUILD_TRACE
#define BUILD_TRACE

#include <cstdint>
#include <iostream>

namespace build
{
  // 1 - command lines to update explicit targets (e.g., .o)
  // 2 - command lines to update implicit targets (e.g., .d)
  // 3 - things didn't work out (e.g., rule did not match)
  // 4 - additional information
  // 5 - more additional information
  //
  extern std::uint8_t verb;

  struct tracer
  {
    explicit
    tracer (const char* name): name_ (name) {}

    struct record
    {
      ~record () {if (!empty_) std::cerr << std::endl;}

      template <typename T>
      std::ostream&
      operator<< (const T& x) const
      {
        return std::cerr << x;
      }

      explicit record (tracer& t): empty_ (false) {t.begin ();}
      explicit record (bool e = true): empty_ (e) {}

      // Movable-only type.
      //
      record (record&& r) {empty_ = r.empty_; r.empty_ = true;}
      record& operator= (record&& r) {empty_ = r.empty_; r.empty_ = true;}

      record (const record&) = delete;
      record& operator= (const record&) = delete;

    private:
      mutable bool empty_;
    };

    template <typename T>
    record
    operator<< (const T& x) const
    {
      begin ();
      std::cerr << x;
      return record (false);
    }

    void
    begin () const
    {
      std::cerr << "trace: " << name_ << ": ";
    }

  private:
    const char* name_;
  };

  template <typename F>
  inline void
  trace (std::uint8_t level, const F& f)
  {
    if (verb >= level)
      f ();
  }
}

#endif // BUILD_TRACE