aboutsummaryrefslogtreecommitdiff
path: root/build/prerequisite
blob: e33feb682eb16c3f730bf1a8d55369bf5d7a3b14 (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
// file      : build/prerequisite -*- C++ -*-
// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd
// license   : MIT; see accompanying LICENSE file

#ifndef BUILD_PREREQUISITE
#define BUILD_PREREQUISITE

#include <set>
#include <string>
#include <iosfwd>
#include <utility>    // move
#include <cassert>
#include <typeindex>
#include <functional> // reference_wrapper

#include <build/types>
#include <build/target-key>
#include <build/utility> // extension_pool
#include <build/diagnostics>

namespace build
{
  class scope;
  class target;

  // Light-weight (by being shallow-pointing) prerequisite key, similar
  // to (and based on) target key.
  //
  class prerequisite_key
  {
  public:
    typedef build::scope scope_type;

    target_key tk;
    mutable scope_type* scope; // Can be NULL if tk.dir is absolute.
  };

  inline bool
  operator< (const prerequisite_key& x, const prerequisite_key& y)
  {
    assert (x.scope == y.scope);
    return x.tk < y.tk;
  }

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

  class prerequisite
  {
  public:
    typedef build::target target_type;
    typedef build::target_type target_type_type;
    typedef build::scope scope_type;

    prerequisite (const target_type_type& t,
                  dir_path d,
                  std::string n,
                  const std::string* e,
                  scope_type& s)
        : type (t), dir (std::move (d)), name (std::move (n)), ext (e),
          scope (s), target (nullptr) {}

  public:
    const target_type_type& type;
    const dir_path dir;     // Normalized absolute or relative (to scope).
    const std::string name;
    const std::string* ext; // NULL if unspecified.
    scope_type& scope;
    target_type* target;    // NULL if not yet resolved. Note that this should
                            // always be the "primary target", not a member of
                            // a target group.

    prerequisite_key
    key () const
    {
      return prerequisite_key {{&type, &dir, &name, &ext}, &scope};
    }

  public:
    // Prerequisite (target) type.
    //
    template <typename T>
    bool
    is_a () const {return type.is_a<T> ();}
  };

  inline bool
  operator< (const prerequisite& x, const prerequisite& y)
  {
    return x.key () < y.key ();
  }

  inline std::ostream&
  operator<< (std::ostream& os, const prerequisite& p)
  {
    return os << p.key ();
  }

  // Set of prerequisites in a scope.
  //
  struct prerequisite_set: std::set<prerequisite>
  {
    std::pair<prerequisite&, bool>
    insert (const target_type&,
            dir_path dir,
            std::string name,
            const std::string* ext,
            scope&,
            tracer&);

    std::pair<prerequisite&, bool>
    insert (const target_key& tk, scope& s, tracer& t)
    {
      return insert (*tk.type, *tk.dir, *tk.name, *tk.ext, s, t);
    }
  };
}

#endif // BUILD_PREREQUISITE