aboutsummaryrefslogtreecommitdiff
path: root/build/prerequisite
blob: 3022e445d2fcc3ada194c339af218203be9d96c3 (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
// 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* const* proj; // Only *proj can be NULL, points
                                            // to 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