// file : build/operation.cxx -*- C++ -*- // copyright : Copyright (c) 2014-2015 Code Synthesis Ltd // license : MIT; see accompanying LICENSE file #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) { return os << '(' << static_cast<uint16_t> (a.meta_operation ()) << ',' << static_cast<uint16_t> (a.operation ()) << ')'; } // perform // void load (const path& bf, scope& root, const dir_path& out_base, const dir_path& src_base, const location&) { // Load project's root[-pre].build. // load_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.assign ("out_base") = out_base; auto v (base.assign ("src_base") = src_base); base.src_path_ = &v.as<const dir_path&> (); // Load the buildfile unless it has already been loaded. // source_once (bf, root, base, root); } void match (action a, scope&, 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); if (verb >= 5) dump (a); level4 ([&]{trace << "matching " << t;}); match (a, t); if (verb >= 5) dump (a); 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 << diag_doing (a, t);}); switch (execute (a, 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); } } // Re-examine postponed targets. // for (target& t: psp) { switch (t.state ()) { case target_state::postponed: { info << "unable to " << diag_do (a, t) << " at this time"; break; } case target_state::unchanged: { info << diag_already_done (a, t); 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", "update", "updating", "up to date", execution_mode::first }; operation_info clean { "clean", "clean", "cleaning", "clean", execution_mode::last}; }