aboutsummaryrefslogtreecommitdiff
path: root/build/prerequisite
blob: c435fd3f0daf1bd4e4d8cbd474b15fd290312e75 (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
// 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 <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;

    mutable const std::string* proj; // Can be NULL, from project_name_pool.
    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);

    // Can compare project name pointers since they are from project_name_pool.
    //
    return x.proj < y.proj || (x.proj == y.proj && 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 std::string* p,
                  const target_type_type& t,
                  dir_path d,
                  std::string n,
                  const std::string* e,
                  scope_type& s)
        : proj (p),
          type (t),
          dir (std::move (d)),
          name (std::move (n)),
          ext (e),
          scope (s),
          target (nullptr) {}

  public:
    const std::string* proj; // NULL if not project-qualified.
    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 {proj, {&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 std::string* proj,
            const target_type&,
            dir_path dir,
            std::string name,
            const std::string* ext,
            scope&,
            tracer&);

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

#endif // BUILD_PREREQUISITE