aboutsummaryrefslogtreecommitdiff
path: root/build2/algorithm
blob: 2cfec6215a77baaee91d9c41a22fe0c98d39b6c7 (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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
// file      : build2/algorithm -*- C++ -*-
// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd
// license   : MIT; see accompanying LICENSE file

#ifndef BUILD2_ALGORITHM
#define BUILD2_ALGORITHM

#include <string>
#include <utility> // pair

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

namespace build2
{
  class scope;
  class prerequisite;
  class prerequisite_key;

  // The default prerequisite search implementation. It first calls the
  // target-type-specific search function. If that doesn't yeld anything,
  // it creates a new target.
  //
  target&
  search (prerequisite&);

  // As above but specify the prerequisite to search as a key.
  //
  target&
  search (const prerequisite_key&);

  // As above but override the target type. Useful for searching for
  // target group members where we need to search for a different
  // target type.
  //
  target&
  search (const target_type&, const prerequisite_key&);

  // As above but specify the prerequisite to search as individual
  // key components.
  //
  target&
  search (const target_type& type,
          const dir_path& dir,
          const std::string& name,
          const std::string* ext,
          scope*);

  // As above but specify the target type as template argument.
  //
  template <typename T>
  T&
  search (const dir_path& dir,
          const std::string& name,
          const std::string* ext,
          scope*);

  // Search for a target identified by the name. The semantics
  // is "as if" we first created a prerequisite based on this
  // name in exactly the same way as the parser would and then
  // searched based on this prerequisite.
  //
  target&
  search (name, scope&);

  // Match and apply a rule to the action/target with ambiguity
  // detection. Increment the target's dependents count, which
  // means that you should call this function with the intent
  // to also call execute(). In case of optimizations that would
  // avoid calling execute(), call unmatch() to indicate this.
  //
  void
  match (action, target&);

  // Note that calling this function only makes sense if the
  // target itself doesn't have its own dependents.
  //
  void
  unmatch (action, target&);

  // Match (but do not apply) a rule to the action/target with
  // ambiguity detection. Note that this function does not touch
  // the dependents count.
  //
  void
  match_only (action, target&);

  // Match a "delegate rule" from withing another rules' apply()
  // function. Return recipe and recipe action (if any). Note
  // that unlike match(), this call doesn't increment the
  // dependents count. See also the companion execute_delegate().
  //
  std::pair<recipe, action>
  match_delegate (action, target&);

  // The standard prerequisite search and match implementations. They call
  // search_and_match_*() versions below passing non-empty directory for
  // the clean operation.
  //
  void
  search_and_match_prerequisites (action, target&);

  // If we are cleaning, this function doesn't go into group members,
  // as an optimization (the group should clean everything up).
  //
  void
  search_and_match_prerequisite_members (action, target&);

  // The actual prerequisite search and match implementations. They call
  // search() and then match() for each prerequisite in a loop. If this
  // target is a member of a group, then they first do this to the group's
  // prerequisites.
  //
  // If the directory argument is not empty, then they ignore (do not
  // match) prerequisites that are not in the same or its subdirectory.
  //
  void
  search_and_match_prerequisites (action, target&, const dir_path&);

  void
  search_and_match_prerequisite_members (action, target&, const dir_path&);

  // Unless already available, match, and, if necessary, execute the group
  // in order to obtain its members list. Note that even after that the
  // member's list might still not be available (e.g., if some wildcard/
  // fallback rule matched).
  //
  group_view
  resolve_group_members (action, target&);

  // Inject dependency on the parent directory's fsdir{}, unless it is
  // the project's out_root (or is outside of any project; say, for
  // example, an install directory). Normally this function is called
  // from the rule's apply() function.
  //
  void
  inject_parent_fsdir (action, target&);

  // Execute the action on target, assuming a rule has been matched
  // and the recipe for this action has been set. This is the default
  // executor implementation. Decrements the dependents count.
  //
  target_state
  execute (action, target&);

  // Execute the recipe obtained with match_delegate(). Note that
  // the target's state is neither checked nor updated by this
  // function. In other words, the appropriate usage is to call
  // this function from another recipe and to factor the obtained
  // state into the one returned.
  //
  target_state
  execute_delegate (const recipe&, action, target&);

  // A special version of the above that should be used for "direct"
  // and "now" execution, that is, side-stepping the normal target-
  // prerequisite relationship (so no dependents count is decremented)
  // and execution order (so this function will never return postponed
  // target state).
  //
  target_state
  execute_direct (action, target&);

  // The default prerequisite execute implementation. It calls execute()
  // on each non-ignored (non-NULL) prerequisite target in a loop. If this
  // target is a member of a group, then it first does this to the group's
  // prerequisites. Returns target_state::changed if any of them were
  // changed and target_state::unchanged otherwise. Note that this
  // function can be used as a recipe.
  //
  target_state
  execute_prerequisites (action, target&);

  // As above but iterates over the prerequisites in reverse.
  //
  target_state
  reverse_execute_prerequisites (action, target&);

  // A version of the above that also determines whether the action
  // needs to be executed on the target based on the passed mtime
  // timestamp.
  //
  // Note that because we use mtime, this function should normally
  // only be used in the perform_update action.
  //
  bool
  execute_prerequisites (action, target&, const timestamp&);

  // Another version of the above that does two extra things for the
  // caller: it determines whether the action needs to be executed on
  // the target based on the passed timestamp and, if so, finds a
  // prerequisite of the specified type (e.g., a source file). If
  // there are multiple prerequisites of this type, then the last
  // is returned.
  //
  template <typename T>
  T*
  execute_prerequisites (action, target&, const timestamp&);

  // Return noop_recipe instead of using this function directly.
  //
  target_state
  noop_action (action, target&);

  // Default action implementation which forwards to the prerequisites.
  // Use default_recipe instead of using this function directly.
  //
  target_state
  default_action (action, target&);

  // Standard perform(clean) action implementation for the file target
  // or derived.
  //
  target_state
  perform_clean (action, target&);
}

#include <build2/algorithm.ixx>
#include <build2/algorithm.txx>

#endif // BUILD2_ALGORITHM