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

#ifndef BUILD2_RULE
#define BUILD2_RULE

#include <string>
#include <cstddef>        // nullptr_t

#include <build2/types>
#include <build2/target>
#include <build2/operation>

namespace build2
{
  class match_result
  {
  public:
    typedef build2::target target_type;
    typedef build2::prerequisite prerequisite_type;

    // Can contain neither (both are NULL), one of, or both. If both
    // are NULL, then it is a "no match" indicator.
    //
    // Note that if the "payload" is stored in *value instead of
    // prerequisite, then target must not be NULL.
    //
    union
    {
      prerequisite_type* prerequisite;

      bool bvalue;
      void* pvalue;
      const void* cpvalue;
    };

    target_type* target;

    action recipe_action = action (); // Used as recipe's action if set.

    match_result (std::nullptr_t v = nullptr): prerequisite (v), target (v) {}
    match_result (prerequisite_type& p): prerequisite (&p), target (nullptr) {}
    match_result (prerequisite_type* p): prerequisite (p), target (nullptr) {}
    match_result (target_type& t): prerequisite (nullptr), target (&t) {}
    match_result (target_type* t): prerequisite (nullptr), target (t) {}
    match_result (const prerequisite_member& pm)
        : prerequisite (&pm.prerequisite.get ()), target (pm.target) {}

    match_result (target_type& t, bool v): bvalue (v), target (&t) {}
    match_result (target_type& t, void* v): pvalue (v), target (&t) {}
    match_result (target_type& t, const void* v): cpvalue (v), target (&t) {}
    match_result (target_type& t, std::nullptr_t v): pvalue (v), target (&t) {}

    explicit
    operator bool () const
    {
      return target != nullptr || prerequisite != nullptr;
    }
  };

  class rule
  {
  public:
    virtual match_result
    match (action, target&, const std::string& hint) const = 0;

    virtual recipe
    apply (action, target&, const match_result&) const = 0;
  };

  // Fallback rule that on update verifies that the file exists and is
  // not older than any of its prerequisites.
  //
  class file_rule: public rule
  {
  public:
    virtual match_result
    match (action, target&, const std::string& hint) const;

    virtual recipe
    apply (action, target&, const match_result&) const;

    static target_state
    perform_update (action, target&);

    static file_rule instance;
  };

  class alias_rule: public rule
  {
  public:
    virtual match_result
    match (action, target&, const std::string& hint) const;

    virtual recipe
    apply (action, target&, const match_result&) const;

    static alias_rule instance;
  };

  class fsdir_rule: public rule
  {
  public:
    virtual match_result
    match (action, target&, const std::string& hint) const;

    virtual recipe
    apply (action, target&, const match_result&) const;

    static target_state
    perform_update (action, target&);

    static target_state
    perform_clean (action, target&);

    static fsdir_rule instance;
  };

  // Fallback rule that always matches and does nothing.
  //
  class fallback_rule: public build2::rule
  {
  public:
    virtual match_result
    match (action, target& t, const std::string&) const {return t;}

    virtual recipe
    apply (action, target&, const match_result&) const {return noop_recipe;}

    static fallback_rule instance;
  };
}

#endif // BUILD2_RULE