aboutsummaryrefslogtreecommitdiff
path: root/build/target
blob: 3ef31921b995a62e5b4934ed5101747f4a7b6fa0 (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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
// file      : build/target -*- C++ -*-
// copyright : Copyright (c) 2014-2015 Code Synthesis Tools CC
// license   : MIT; see accompanying LICENSE file

#ifndef BUILD_TARGET
#define BUILD_TARGET

#include <string>
#include <vector>
#include <functional> // function, reference_wrapper
#include <typeindex>
#include <iosfwd>
#include <cassert>

#include <build/path>
#include <build/timestamp>

namespace build
{
  class target;

  enum class target_state {unknown, uptodate, updated, failed};
  typedef std::function<target_state (target&)> recipe;

  typedef std::vector<std::reference_wrapper<target>> targets;

  class target
  {
  public:
    target (std::string n): name_ (n) {}

    const std::string&
    name () const {return name_;}

    const targets&
    prerequisites () const {return prerequisites_;}

    targets&
    prerequisites () {return prerequisites_;}

    void
    prerequisite (target& t) {prerequisites_.push_back (t);}

  public:
    typedef build::recipe recipe_type;

    const recipe_type&
    recipe () const {return recipe_;}

    void
    recipe (recipe_type r) {assert (!recipe_); recipe_ = r;}

  public:
    target_state
    state () const {return state_;}

    void
    state (target_state s) {state_ = s;}

  private:
    target (const target&) = delete;
    target& operator= (const target&) = delete;

  public:
    struct type_info
    {
      std::type_index id;
      const char* name;
      const type_info* base;
    };

    virtual const type_info&
    type_id () const = 0;

  protected:
    static const type_info ti_;

  private:
    std::string name_;
    targets prerequisites_;
    recipe_type recipe_;
    target_state state_ {target_state::unknown};
  };

  std::ostream&
  operator<< (std::ostream&, const target&);

  // Modification time-based target.
  //
  class mtime_target: public target
  {
  public:
    using target::target;

    timestamp
    mtime () const
    {
      if (mtime_ == timestamp_unknown)
        mtime_ = load_mtime ();

      return mtime_;
    }

    void
    mtime (timestamp mt) {mtime_ = mt;}

  protected:
    virtual timestamp
    load_mtime () const = 0;

  protected: static const type_info ti_;

  private:
    mutable timestamp mtime_ {timestamp_unknown};
  };

  // Filesystem path-bases target.
  //
  class path_target: public mtime_target
  {
  public:
    using mtime_target::mtime_target;

    typedef build::path path_type;

    const path_type&
    path () const {return path_;}

    void
    path (path_type p) {assert (path_.empty ()); path_ = p;}

  protected:
    virtual timestamp
    load_mtime () const;

  protected: static const type_info ti_;

  private:
    path_type path_;
  };

  // File target.
  //
  class file: public path_target
  {
  public:
    using path_target::path_target;

  public: virtual const type_info& type_id () const {return ti_;}
  protected: static const type_info ti_;
  };
}

#endif // BUILD_TARGET