// file : build/operation.cxx -*- C++ -*- // copyright : Copyright (c) 2014-2015 Code Synthesis Tools CC // license : MIT; see accompanying LICENSE file #include #include #include #include // reference_wrapper #include #include #include #include #include #include using namespace std; namespace build { // action // ostream& operator<< (ostream& os, action a) { return os << '(' << static_cast (a.meta_operation ()) << ',' << static_cast (a.operation ()) << ')'; } // 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}; }