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