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

#ifndef BUILD2_PREREQUISITE
#define BUILD2_PREREQUISITE

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

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

namespace build2
{
  class scope;
  class target;

  // Light-weight (by being shallow-pointing) prerequisite key, similar
  // to (and based on) target key.
  //
  class prerequisite_key
  {
  public:
    typedef build2::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 build2::target target_type;
    typedef build2::target_type target_type_type;
    typedef build2::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* const 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.

    // Note that the returned key "tracks" the prerequisite; that is, any
    // updates to the prerequisite's members will be reflected in the key.
    //
    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 // BUILD2_PREREQUISITE