aboutsummaryrefslogtreecommitdiff
path: root/build/operation.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'build/operation.cxx')
-rw-r--r--build/operation.cxx140
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};