aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2015-07-21 16:21:07 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2015-07-21 16:21:07 +0200
commita1cec9e0df14f3c1a833e2a447b5324ff9c430d3 (patch)
treee61c7e1cb3fa27ba435053761f5a2a3fb670f728
parentbead742dbac51088e89cdd4dd7a55aaa1d8c98d7 (diff)
Test module genesis
-rw-r--r--build/b.cxx2
-rw-r--r--build/buildfile5
-rw-r--r--build/context.cxx24
-rw-r--r--build/rule20
-rw-r--r--build/rule.cxx6
-rw-r--r--build/test/module21
-rw-r--r--build/test/module.cxx72
-rw-r--r--build/test/operation18
-rw-r--r--build/test/operation.cxx34
-rw-r--r--build/test/rule32
-rw-r--r--build/test/rule.cxx49
-rw-r--r--build/variable4
-rw-r--r--build/variable.cxx16
-rw-r--r--tests/test/simple/build/bootstrap.build4
-rw-r--r--tests/test/simple/buildfile10
-rw-r--r--tests/test/simple/driver.cxx4
-rw-r--r--tests/test/simple/utility.cxx1
17 files changed, 303 insertions, 19 deletions
diff --git a/build/b.cxx b/build/b.cxx
index 2500196..3a6d71f 100644
--- a/build/b.cxx
+++ b/build/b.cxx
@@ -44,6 +44,7 @@ using namespace std;
#include <build/bin/module>
#include <build/cxx/module>
#include <build/cli/module>
+#include <build/test/module>
using namespace build;
@@ -94,6 +95,7 @@ main (int argc, char* argv[])
builtin_modules["bin"] = &bin::bin_init;
builtin_modules["cxx"] = &cxx::cxx_init;
builtin_modules["cli"] = &cli::cli_init;
+ builtin_modules["test"] = &test::test_init;
// Figure out work and home directories.
//
diff --git a/build/buildfile b/build/buildfile
index 90a8dc7..a6715de 100644
--- a/build/buildfile
+++ b/build/buildfile
@@ -8,11 +8,12 @@ config = config/{operation module utility}
bin = bin/{target rule module}
cxx = cxx/{target compile link module utility}
cli = cli/{target rule module}
+test = test/{operation rule module}
exe{b}: cxx{b algorithm name operation spec scope variable target \
prerequisite rule file module context search diagnostics token \
- lexer parser path-io utility dump options $config $bin $cxx $cli} \
- $libs
+ lexer parser path-io utility dump options $config $bin $cxx $cli \
+ $test} $libs
#@@ TODO
#
diff --git a/build/context.cxx b/build/context.cxx
index 9b22478..9d9c322 100644
--- a/build/context.cxx
+++ b/build/context.cxx
@@ -28,12 +28,6 @@ namespace build
const operation_info* current_oif;
execution_mode current_mode;
- // Builtin rules.
- //
- static alias_rule alias_;
- static fsdir_rule fsdir_;
- static file_rule file_;
-
void
reset ()
{
@@ -77,17 +71,17 @@ namespace build
{
rule_map& rs (global_scope->rules);
- rs.insert<alias> (default_id, "alias", alias_);
- rs.insert<alias> (update_id, "alias", alias_);
- rs.insert<alias> (clean_id, "alias", alias_);
+ rs.insert<alias> (default_id, "alias", alias_rule::instance);
+ rs.insert<alias> (update_id, "alias", alias_rule::instance);
+ rs.insert<alias> (clean_id, "alias", alias_rule::instance);
- rs.insert<fsdir> (default_id, "fsdir", fsdir_);
- rs.insert<fsdir> (update_id, "fsdir", fsdir_);
- rs.insert<fsdir> (clean_id, "fsdir", fsdir_);
+ rs.insert<fsdir> (default_id, "fsdir", fsdir_rule::instance);
+ rs.insert<fsdir> (update_id, "fsdir", fsdir_rule::instance);
+ rs.insert<fsdir> (clean_id, "fsdir", fsdir_rule::instance);
- rs.insert<file> (default_id, "file", file_);
- rs.insert<file> (update_id, "file", file_);
- rs.insert<file> (clean_id, "file", file_);
+ rs.insert<file> (default_id, "file", file_rule::instance);
+ rs.insert<file> (update_id, "file", file_rule::instance);
+ rs.insert<file> (clean_id, "file", file_rule::instance);
}
}
diff --git a/build/rule b/build/rule
index 5b0149b..ea0b5ae 100644
--- a/build/rule
+++ b/build/rule
@@ -23,9 +23,19 @@ namespace build
// Can contain neither (both are NULL), one of, or both. If both
// are NULL, then it is a "no match" indicator.
//
- prerequisite_type* prerequisite;
+ // Note that if the "payload" is stored in value instead of
+ // prerequisite, then target must not be NULL.
+ //
+ union
+ {
+ prerequisite_type* prerequisite;
+ bool value;
+ };
+
target_type* target;
+ match_result (target_type& t, bool v): value (v), target (&t) {}
+
match_result (std::nullptr_t v = nullptr): prerequisite (v), target (v) {}
match_result (prerequisite_type& p): prerequisite (&p), target (nullptr) {}
match_result (prerequisite_type* p): prerequisite (p), target (nullptr) {}
@@ -37,7 +47,7 @@ namespace build
explicit
operator bool () const
{
- return prerequisite != nullptr || target != nullptr;
+ return target != nullptr || prerequisite != nullptr;
}
};
@@ -65,6 +75,8 @@ namespace build
static target_state
perform_update (action, target&);
+
+ static file_rule instance;
};
class alias_rule: public rule
@@ -75,6 +87,8 @@ namespace build
virtual recipe
apply (action, target&, const match_result&) const;
+
+ static alias_rule instance;
};
class fsdir_rule: public rule
@@ -91,6 +105,8 @@ namespace build
static target_state
perform_clean (action, target&);
+
+ static fsdir_rule instance;
};
}
diff --git a/build/rule.cxx b/build/rule.cxx
index 03c86c8..f53d9d9 100644
--- a/build/rule.cxx
+++ b/build/rule.cxx
@@ -133,6 +133,8 @@ namespace build
return target_state::unchanged;
}
+ file_rule file_rule::instance;
+
// alias_rule
//
match_result alias_rule::
@@ -148,6 +150,8 @@ namespace build
return default_recipe;
}
+ alias_rule alias_rule::instance;
+
// fsdir_rule
//
match_result fsdir_rule::
@@ -238,4 +242,6 @@ namespace build
default: return ts;
}
}
+
+ fsdir_rule fsdir_rule::instance;
}
diff --git a/build/test/module b/build/test/module
new file mode 100644
index 0000000..0b6af78
--- /dev/null
+++ b/build/test/module
@@ -0,0 +1,21 @@
+// file : build/test/module -*- C++ -*-
+// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd
+// license : MIT; see accompanying LICENSE file
+
+#ifndef BUILD_TEST_MODULE
+#define BUILD_TEST_MODULE
+
+#include <build/types>
+#include <build/module>
+
+namespace build
+{
+ namespace test
+ {
+ extern "C" void
+ test_init (
+ scope&, scope&, const location&, std::unique_ptr<module>&, bool);
+ }
+}
+
+#endif // BUILD_TEST_MODULE
diff --git a/build/test/module.cxx b/build/test/module.cxx
new file mode 100644
index 0000000..d5ba754
--- /dev/null
+++ b/build/test/module.cxx
@@ -0,0 +1,72 @@
+// file : build/test/module.cxx -*- C++ -*-
+// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd
+// license : MIT; see accompanying LICENSE file
+
+#include <build/test/module>
+
+#include <build/scope>
+#include <build/target>
+#include <build/rule>
+#include <build/diagnostics>
+
+#include <build/test/operation>
+#include <build/test/rule>
+
+using namespace std;
+using namespace butl;
+
+namespace build
+{
+ namespace test
+ {
+ class module: public build::module
+ {
+ public:
+ module (operation_id test_id): rule (test_id) {}
+
+ test::rule rule;
+ };
+
+ extern "C" void
+ test_init (scope& root,
+ scope& base,
+ const location& l,
+ unique_ptr<build::module>& r,
+ bool first)
+ {
+ tracer trace ("test::init");
+
+ if (&root != &base)
+ fail (l) << "test module must be initialized in bootstrap.build";
+
+ if (!first)
+ {
+ warn (l) << "multiple test module initializations";
+ return;
+ }
+
+ const dir_path& out_root (root.path ());
+ level4 ([&]{trace << "for " << out_root;});
+
+ // Register the test operation.
+ //
+ operation_id test_id (root.operations.insert (test));
+
+ unique_ptr<module> m (new module (test_id));
+
+ {
+ auto& rs (base.rules);
+
+ // Register the standard alias rule for the test operation.
+ //
+ rs.insert<alias> (test_id, "alias", alias_rule::instance);
+
+ // Register our test running rule.
+ //
+ rs.insert<target> (test_id, "test", m->rule);
+ }
+
+ r = move (m);
+ }
+ }
+}
diff --git a/build/test/operation b/build/test/operation
new file mode 100644
index 0000000..1942936
--- /dev/null
+++ b/build/test/operation
@@ -0,0 +1,18 @@
+// file : build/test/operation -*- C++ -*-
+// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd
+// license : MIT; see accompanying LICENSE file
+
+#ifndef BUILD_TEST_OPERATION
+#define BUILD_TEST_OPERATION
+
+#include <build/operation>
+
+namespace build
+{
+ namespace test
+ {
+ extern operation_info test;
+ }
+}
+
+#endif // BUILD_TEST_OPERATION
diff --git a/build/test/operation.cxx b/build/test/operation.cxx
new file mode 100644
index 0000000..75e3e80
--- /dev/null
+++ b/build/test/operation.cxx
@@ -0,0 +1,34 @@
+// file : build/test/operation.cxx -*- C++ -*-
+// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd
+// license : MIT; see accompanying LICENSE file
+
+#include <build/test/operation>
+
+#include <build/config/operation>
+
+using namespace std;
+using namespace butl;
+
+namespace build
+{
+ namespace test
+ {
+ static operation_id
+ test_pre (meta_operation_id mo)
+ {
+ // Run update as a pre-operation, unless we are disfiguring.
+ //
+ return mo != config::disfigure_id ? update_id : 0;
+ }
+
+ operation_info test {
+ "test",
+ "test",
+ "testing",
+ "tested",
+ execution_mode::first,
+ &test_pre,
+ nullptr
+ };
+ }
+}
diff --git a/build/test/rule b/build/test/rule
new file mode 100644
index 0000000..db10606
--- /dev/null
+++ b/build/test/rule
@@ -0,0 +1,32 @@
+// file : build/test/rule -*- C++ -*-
+// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd
+// license : MIT; see accompanying LICENSE file
+
+#ifndef BUILD_TEST_RULE
+#define BUILD_TEST_RULE
+
+#include <build/rule>
+#include <build/operation>
+
+namespace build
+{
+ namespace test
+ {
+ class rule: public build::rule
+ {
+ public:
+ rule (operation_id o): test_id (o) {}
+
+ virtual match_result
+ match (action, target&, const std::string&) const;
+
+ virtual recipe
+ apply (action, target&, const match_result&) const;
+
+ private:
+ operation_id test_id;
+ };
+ }
+}
+
+#endif // BUILD_TEST_RULE
diff --git a/build/test/rule.cxx b/build/test/rule.cxx
new file mode 100644
index 0000000..3fd3a16
--- /dev/null
+++ b/build/test/rule.cxx
@@ -0,0 +1,49 @@
+// file : build/test/rule.cxx -*- C++ -*-
+// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd
+// license : MIT; see accompanying LICENSE file
+
+#include <build/test/rule>
+
+#include <build/scope>
+#include <build/target>
+#include <build/algorithm>
+#include <build/diagnostics>
+
+using namespace std;
+
+namespace build
+{
+ namespace test
+ {
+ match_result rule::
+ match (action a, target& t, const std::string&) const
+ {
+ // First determine if this is a test.
+ //
+ auto v (t.vars["test"]);
+
+ if (!v)
+ v.rebind (t.base_scope ()[string("test.") + t.type ().name]);
+
+ if (!v || !v.as<bool> ())
+ return match_result (t, false); // "Not a test" result.
+
+ // If this is the update pre-operation, make someone else do
+ // the job.
+ //
+ if (a.operation () != test_id)
+ return nullptr;
+
+ return match_result (t, true);
+ }
+
+ recipe rule::
+ apply (action, target&, const match_result& mr) const
+ {
+ if (!mr.value) // Not a test.
+ return noop_recipe;
+
+ return noop_recipe; //@@ TMP
+ }
+ }
+}
diff --git a/build/variable b/build/variable
index bb29138..9009080 100644
--- a/build/variable
+++ b/build/variable
@@ -218,6 +218,10 @@ namespace build
template <>
const dir_path& value_proxy::
as<const dir_path&> () const;
+
+ template <>
+ bool value_proxy::
+ as<bool> () const;
}
namespace std
diff --git a/build/variable.cxx b/build/variable.cxx
index d00fcf6..eab77e5 100644
--- a/build/variable.cxx
+++ b/build/variable.cxx
@@ -70,4 +70,20 @@ namespace build
assert (n.directory ());
return n.dir;
}
+
+ template <>
+ bool value_proxy::
+ as<bool> () const
+ {
+ const list_value& lv (as<const list_value&> ());
+ assert (lv.size () == 1);
+ const name& n (lv.front ());
+ assert (n.simple ());
+ if (n.value == "true")
+ return true;
+ else if (n.value == "false")
+ return false;
+ else
+ assert (false); // Bool value should be 'true' or 'false'.
+ }
}
diff --git a/tests/test/simple/build/bootstrap.build b/tests/test/simple/build/bootstrap.build
new file mode 100644
index 0000000..0b7a347
--- /dev/null
+++ b/tests/test/simple/build/bootstrap.build
@@ -0,0 +1,4 @@
+project = test-simple
+amalgamation = # Disabled.
+using config
+using test
diff --git a/tests/test/simple/buildfile b/tests/test/simple/buildfile
new file mode 100644
index 0000000..6113968
--- /dev/null
+++ b/tests/test/simple/buildfile
@@ -0,0 +1,10 @@
+using cxx
+
+hxx.ext = hxx
+cxx.ext = cxx
+
+lib{utility}: cxx{utility}
+exe{driver}: cxx{driver} lib{utility}
+exe{driver}: test = true
+
+.: lib{utility} exe{driver}
diff --git a/tests/test/simple/driver.cxx b/tests/test/simple/driver.cxx
new file mode 100644
index 0000000..70b4146
--- /dev/null
+++ b/tests/test/simple/driver.cxx
@@ -0,0 +1,4 @@
+int
+main ()
+{
+}
diff --git a/tests/test/simple/utility.cxx b/tests/test/simple/utility.cxx
new file mode 100644
index 0000000..c4bb446
--- /dev/null
+++ b/tests/test/simple/utility.cxx
@@ -0,0 +1 @@
+void f (){}