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
136
137
138
139
140
|
// file : build2/rule -*- C++ -*-
// copyright : Copyright (c) 2014-2017 Code Synthesis Ltd
// license : MIT; see accompanying LICENSE file
#ifndef BUILD2_RULE
#define BUILD2_RULE
#include <build2/types>
#include <build2/utility>
#include <build2/target>
#include <build2/operation>
namespace build2
{
class match_result
{
public:
bool result;
// If set, then this is a recipe's action. It must override the original
// action. Normally it is "unconditional inner operation". Only
// noop_recipe can be overridden.
//
// It is passed to rule::apply() so that prerequisites are matched for
// this action. It is also passed to target::recipe() so that if someone
// is matching this target for this action, we won't end-up re-matching
// it. However, the recipe itself is executed with the original action
// so that it can adjust its logic, if necessary.
//
action recipe_action = action ();
explicit
operator bool () const {return result;}
// Note that the from-bool constructor is intentionally implicit so that
// we can return true/false from match().
//
match_result (bool r): result (r) {}
match_result (bool r, action a): result (r), recipe_action (a) {}
};
// Once a rule is registered (for a scope), it is treated as immutable. If
// you need to modify some state (e.g., counters or some such), then make
// sure it is MT-safe.
//
// Note that match() may not be followed by apply() or be called several
// times before the following apply() (see resolve_group_members()) which
// means that it should be idempotent. The target_data object in the call
// to match() may not be the same as target.
//
// match() can also be called by another rules (see cc/install).
//
class rule
{
public:
virtual match_result
match (action, target&, const string& hint) const = 0;
virtual recipe
apply (action, target&) const = 0;
};
// Fallback rule that only matches if the file exists.
//
class file_rule: public rule
{
public:
file_rule () {}
virtual match_result
match (action, target&, const string&) const override;
virtual recipe
apply (action, target&) const override;
static const file_rule instance;
};
class alias_rule: public rule
{
public:
alias_rule () {}
virtual match_result
match (action, target&, const string&) const override;
virtual recipe
apply (action, target&) const override;
static const alias_rule instance;
};
class fsdir_rule: public rule
{
public:
fsdir_rule () {}
virtual match_result
match (action, target&, const string&) const override;
virtual recipe
apply (action, target&) const override;
static target_state
perform_update (action, const target&);
static target_state
perform_clean (action, const target&);
// Sometimes, as an optimization, we want to emulate execute_direct()
// of fsdir{} without the overhead of switching to the execute phase.
//
static void
perform_update_direct (action, const target&);
static const fsdir_rule instance;
};
// Fallback rule that always matches and does nothing.
//
class fallback_rule: public build2::rule
{
public:
fallback_rule () {}
virtual match_result
match (action, target&, const string&) const override
{
return true;
}
virtual recipe
apply (action, target&) const override {return noop_recipe;}
static const fallback_rule instance;
};
}
#endif // BUILD2_RULE
|