diff options
Diffstat (limited to 'build/operation.cxx')
-rw-r--r-- | build/operation.cxx | 140 |
1 files changed, 139 insertions, 1 deletions
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 <build/operation> #include <ostream> +#include <cassert> +#include <functional> // reference_wrapper + +#include <build/scope> +#include <build/target> +#include <build/file> +#include <build/algorithm> +#include <build/diagnostics> +#include <build/dump> 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<const path&> (); + + // 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<reference_wrapper<target>> psp; + + for (void* v: ts) + { + target& t (*static_cast<target*> (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_ {"<default>", execution_mode::first}; operation_info update {"update", execution_mode::first}; operation_info clean {"clean", execution_mode::last}; |