From a94dcda7f00b10cb22b5f2138b1c29bcfbe7de37 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 24 Mar 2015 08:53:06 +0200 Subject: Make meta-operations control build loop; add disfigure skeleton --- build/operation.cxx | 140 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 139 insertions(+), 1 deletion(-) (limited to 'build/operation.cxx') diff --git a/build/operation.cxx b/build/operation.cxx index 28cb13d..bbd474f 100644 --- a/build/operation.cxx +++ b/build/operation.cxx @@ -5,11 +5,22 @@ #include #include +#include +#include // reference_wrapper + +#include +#include +#include +#include +#include +#include using namespace std; namespace build { + // action + // ostream& operator<< (ostream& os, action a) { @@ -19,8 +30,135 @@ namespace build << ')'; } - meta_operation_info perform {"perform"}; + // perform + // + void + load (const path& bf, + scope& root, + const path& out_base, + const path& src_base, + const location&) + { + // Load project's root[-pre].build. + // + root_pre (root); + + // Create the base scope. Note that its existence doesn't + // mean it was already processed as a base scope; it can + // be the same as root. + // + scope& base (scopes[out_base]); + + base.variables["out_base"] = out_base; + auto v (base.variables["src_base"] = src_base); + base.src_path_ = &v.as (); + + // Load the buildfile unless it has already been loaded. + // + source_once (bf, root, base, root); + } + + void + match (action a, + const target_key& tk, + const location& l, + action_targets& ts) + { + tracer trace ("match"); + + auto i (targets.find (tk, trace)); + if (i == targets.end ()) + fail (l) << "unknown target " << tk; + + target& t (**i); + + //@@ dump + + level4 ([&]{trace << "matching " << t;}); + match (a, t); + + //@@ dump + + ts.push_back (&t); + } + + void + execute (action a, const action_targets& ts) + { + tracer trace ("execute"); + + // Build collecting postponed targets (to be re-examined later). + // + vector> psp; + + for (void* v: ts) + { + target& t (*static_cast (v)); + + level4 ([&]{trace << "executing target " << t;}); + + switch (execute (a, t)) + { + case target_state::postponed: + { + info << "target " << t << " is postponed"; + psp.push_back (t); + break; + } + case target_state::unchanged: + { + info << "target " << t << " is unchanged"; + break; + } + case target_state::changed: + break; + case target_state::failed: + //@@ This could probably happen in a parallel build. + default: + assert (false); + } + } + + // Re-examine postponed targets. + // + for (target& t: psp) + { + switch (t.state) + { + case target_state::postponed: + { + info << "unable to execute target " << t << " at this time"; + break; + } + case target_state::unchanged: + { + info << "target " << t << " is unchanged"; + break; + } + case target_state::unknown: // Assume something was done to it. + case target_state::changed: + break; + case target_state::failed: + //@@ This could probably happen in a parallel build. + default: + assert (false); + } + } + } + + meta_operation_info perform { + "perform", + nullptr, // meta-operation pre + nullptr, // operation pre + &load, + &match, + &execute, + nullptr, // operation post + nullptr // meta-operation post + }; + // operations + // operation_info default_ {"", execution_mode::first}; operation_info update {"update", execution_mode::first}; operation_info clean {"clean", execution_mode::last}; -- cgit v1.1