aboutsummaryrefslogtreecommitdiff
path: root/build/operation.cxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2015-07-20 17:35:47 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2015-07-20 17:35:47 +0200
commitcb8399da1f0b1c5f28e443c98bfc3cb4e12b8cbf (patch)
tree434f2137e8ccac53bf6ec8a62bab501363d898f4 /build/operation.cxx
parentf0aca8db08518ab7f66a8c86200616fed8bcc8d4 (diff)
Implement pre/post operation support
Also, extend execution mode/postponed logic to propagate the postponed target state. At the top, we now re-try postponed targets. This results in the expected behavior when, for example, cleaning two targets with one depending on the other.
Diffstat (limited to 'build/operation.cxx')
-rw-r--r--build/operation.cxx126
1 files changed, 85 insertions, 41 deletions
diff --git a/build/operation.cxx b/build/operation.cxx
index 4c32d42..6b3b08d 100644
--- a/build/operation.cxx
+++ b/build/operation.cxx
@@ -8,6 +8,8 @@
#include <cassert>
#include <functional> // reference_wrapper
+#include <butl/utility> // reverse_iterate
+
#include <build/scope>
#include <build/target>
#include <build/file>
@@ -16,6 +18,7 @@
#include <build/dump>
using namespace std;
+using namespace butl;
namespace build
{
@@ -24,10 +27,24 @@ namespace build
ostream&
operator<< (ostream& os, action a)
{
- return os << '('
- << static_cast<uint16_t> (a.meta_operation ()) << ','
- << static_cast<uint16_t> (a.operation ())
- << ')';
+ uint16_t
+ m (a.meta_operation ()),
+ i (a.operation ()),
+ o (a.outer_operation ());
+
+ os << '(' << m << ',';
+
+ if (o != 0)
+ os << o << '(';
+
+ os << i;
+
+ if (o != 0)
+ os << ')';
+
+ os << ')';
+
+ return os;
}
// perform
@@ -59,30 +76,37 @@ namespace build
}
void
- match (action a,
- scope&,
- const target_key& tk,
- const location& l,
- action_targets& ts)
+ search (scope&,
+ const target_key& tk,
+ const location& l,
+ action_targets& ts)
{
- tracer trace ("match");
+ tracer trace ("search");
auto i (targets.find (tk, trace));
if (i == targets.end ())
fail (l) << "unknown target " << tk;
- target& t (**i);
+ ts.push_back (i->get ());
+ }
+
+ void
+ match (action a, action_targets& ts)
+ {
+ tracer trace ("match");
if (verb >= 5)
dump (a);
- level4 ([&]{trace << "matching " << t;});
- match (a, t);
+ for (void* vt: ts)
+ {
+ target& t (*static_cast<target*> (vt));
+ level4 ([&]{trace << "matching " << t;});
+ match (a, t);
+ }
if (verb >= 5)
dump (a);
-
- ts.push_back (&t);
}
void
@@ -94,38 +118,50 @@ namespace build
//
vector<reference_wrapper<target>> psp;
- for (void* v: ts)
- {
- target& t (*static_cast<target*> (v));
+ // Execute targets in reverse if the execution mode is 'last'.
+ //
+ auto body (
+ [a, &psp, &trace] (void* v)
+ {
+ target& t (*static_cast<target*> (v));
- level4 ([&]{trace << diag_doing (a, t);});
+ level4 ([&]{trace << diag_doing (a, t);});
- switch (execute (a, t))
- {
- case target_state::postponed:
+ switch (execute (a, t))
{
- info << diag_doing (a, t) << " is postponed";
- psp.push_back (t);
+ case target_state::postponed:
+ {
+ info << diag_doing (a, t) << " is postponed";
+ psp.push_back (t);
+ break;
+ }
+ case target_state::unchanged:
+ {
+ info << diag_already_done (a, t);
+ break;
+ }
+ case target_state::changed:
break;
+ case target_state::failed:
+ //@@ This could probably happen in a parallel build.
+ default:
+ assert (false);
}
- case target_state::unchanged:
- {
- info << diag_already_done (a, t);
- break;
- }
- case target_state::changed:
- break;
- case target_state::failed:
- //@@ This could probably happen in a parallel build.
- default:
- assert (false);
- }
- }
+ });
+
+ if (current_mode == execution_mode::first)
+ for (void* v: ts) body (v);
+ else
+ for (void* v: reverse_iterate (ts)) body (v);
- // Re-examine postponed targets.
+ // Re-examine postponed targets. Note that we will do it in the
+ // order added, so no need to check the execution mode.
//
for (target& t: psp)
{
+ if (t.state () == target_state::postponed)
+ execute_direct (a, t); // Try again, now ignoring the execution mode.
+
switch (t.state ())
{
case target_state::postponed:
@@ -157,6 +193,7 @@ namespace build
nullptr, // meta-operation pre
nullptr, // operation pre
&load,
+ &search,
&match,
&execute,
nullptr, // operation post
@@ -170,7 +207,9 @@ namespace build
"",
"",
"",
- execution_mode::first
+ execution_mode::first,
+ nullptr,
+ nullptr
};
operation_info update {
@@ -178,7 +217,9 @@ namespace build
"update",
"updating",
"up to date",
- execution_mode::first
+ execution_mode::first,
+ nullptr,
+ nullptr
};
operation_info clean {
@@ -186,5 +227,8 @@ namespace build
"clean",
"cleaning",
"clean",
- execution_mode::last};
+ execution_mode::last,
+ nullptr,
+ nullptr
+ };
}