diff options
Diffstat (limited to 'build/bd.cxx')
-rw-r--r-- | build/bd.cxx | 167 |
1 files changed, 97 insertions, 70 deletions
diff --git a/build/bd.cxx b/build/bd.cxx index 03d0aa4..e48de21 100644 --- a/build/bd.cxx +++ b/build/bd.cxx @@ -8,48 +8,82 @@ #include <cstdlib> // exit #include <cassert> #include <iostream> +#include <typeinfo> #include <system_error> -#include <build/process> -#include <build/timestamp> #include <build/target> +#include <build/rule> +#include <build/process> using namespace std; namespace build { bool - update (target& t) + match (target& t) { - auto tts (path_timestamp (t.name ())); - cout << t.name () << ": " << tts << endl; + if (!t.recipe ()) + { + for (auto ti (&t.type_id ()); + ti != nullptr && !t.recipe (); + ti = ti->base) + { + for (auto rs (rules.equal_range (ti->id)); + rs.first != rs.second; + ++rs.first) + { + const rule& ru (rs.first->second); + + if (recipe re = ru.match (t)) + { + t.recipe (re); + break; + } + } + } + + if (!t.recipe ()) + { + cerr << "error: no rule to build target " << t << endl; + return false; + } + } - bool u (tts == timestamp_nonexistent); for (target& p: t.prerequisites ()) { - if (!update (p)) + if (!match (p)) + { + cerr << "info: required by " << t << endl; return false; + } + } + + return true; + } + + target_state + update (target& t) + { + assert (t.state () == target_state::unknown); - if (!u) + target_state ts; + + for (target& p: t.prerequisites ()) + { + if (p.state () == target_state::unknown) { - auto tps (path_timestamp (p.name ())); + p.state ((ts = update (p))); - if (tts <= tps) // Note: not just less. - { - cout << t.name () << " vs " << p.name () << ": " << (tps - tts) - << " ahead" << endl; - u = true; - } + if (ts == target_state::failed) + return ts; } } - if (!u) // Nothing to do. - return true; - try { - auto r (t.rule ()); - return r != 0 ? r (t) : true; + t.state ((ts = t.recipe () (t))); + assert (ts != target_state::unknown); + return ts; } catch (const process_error& e) { @@ -63,52 +97,13 @@ namespace build } } -using namespace build; +#include <build/native> -bool -cxx_compile_rule (target& t) -{ - const targets& ps (t.prerequisites ()); - - //@@ TODO: assuming .cxx is first. - // - const target& p0 (ps[0]); - const char* args[] { - "g++-4.9", - "-std=c++11", - "-I..", - "-c", - "-o", t.name ().c_str (), - p0.name ().c_str (), - nullptr}; - - cerr << "c++ " << t.name () << endl; - - try - { - process pr (args); - return pr.wait (); - } - catch (const process_error& e) - { - cerr << "error: unable to execute '" << args[0] << "': " << - e.what () << endl; - - if (e.child ()) - throw; // Let our caller terminate us quickly without causing a scene. +#include <build/cxx/target> +#include <build/cxx/rule> - return false; - } -} - -bool -cxx_link_rule (target& t) -{ - const targets& ps (t.prerequisites ()); - cerr << "ld " << t.name () << endl; - return true; -} +using namespace build; int main (int argc, char* argv[]) @@ -117,20 +112,52 @@ main (int argc, char* argv[]) // tzset (); + cxx::link cxx_link; + rules.emplace (typeid (exe), cxx_link); + + cxx::compile cxx_compile; + rules.emplace (typeid (obj), cxx_compile); + + default_path_rule path_exists; + rules.emplace (typeid (path_target), path_exists); + + // + // + using namespace build::cxx; + exe bd ("bd"); - obj bd_o ("bd.o"); + obj bd_o ("bd"); bd.prerequisite (bd_o); - bd.rule (&cxx_link_rule); - cxx bd_cxx ("bd.cxx"); + cxx::cxx bd_cxx ("bd"); + bd_cxx.path (path ("bd.cxx")); + hxx target ("target"); + target.path (path ("target")); + bd_o.prerequisite (bd_cxx); bd_o.prerequisite (target); - bd_o.rule (&cxx_compile_rule); - if (!update (bd)) + // + // + if (!match (bd)) + return 1; // Diagnostics has already been issued. + + switch (update (bd)) { - cerr << "unable to update '" << bd.name () << "'" << endl; - return 1; + case target_state::uptodate: + { + cerr << "info: target " << bd << " is up to date" << endl; + break; + } + case target_state::updated: + break; + case target_state::failed: + { + cerr << "error: failed to update target " << bd << endl; + return 1; + } + case target_state::unknown: + assert (false); } } |