From a1cec9e0df14f3c1a833e2a447b5324ff9c430d3 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 21 Jul 2015 16:21:07 +0200 Subject: Test module genesis --- build/b.cxx | 2 ++ build/buildfile | 5 ++-- build/context.cxx | 24 ++++++---------- build/rule | 20 ++++++++++++-- build/rule.cxx | 6 ++++ build/test/module | 21 ++++++++++++++ build/test/module.cxx | 72 ++++++++++++++++++++++++++++++++++++++++++++++++ build/test/operation | 18 ++++++++++++ build/test/operation.cxx | 34 +++++++++++++++++++++++ build/test/rule | 32 +++++++++++++++++++++ build/test/rule.cxx | 49 ++++++++++++++++++++++++++++++++ build/variable | 4 +++ build/variable.cxx | 16 +++++++++++ 13 files changed, 284 insertions(+), 19 deletions(-) create mode 100644 build/test/module create mode 100644 build/test/module.cxx create mode 100644 build/test/operation create mode 100644 build/test/operation.cxx create mode 100644 build/test/rule create mode 100644 build/test/rule.cxx (limited to 'build') 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 #include #include +#include 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 (default_id, "alias", alias_); - rs.insert (update_id, "alias", alias_); - rs.insert (clean_id, "alias", alias_); + rs.insert (default_id, "alias", alias_rule::instance); + rs.insert (update_id, "alias", alias_rule::instance); + rs.insert (clean_id, "alias", alias_rule::instance); - rs.insert (default_id, "fsdir", fsdir_); - rs.insert (update_id, "fsdir", fsdir_); - rs.insert (clean_id, "fsdir", fsdir_); + rs.insert (default_id, "fsdir", fsdir_rule::instance); + rs.insert (update_id, "fsdir", fsdir_rule::instance); + rs.insert (clean_id, "fsdir", fsdir_rule::instance); - rs.insert (default_id, "file", file_); - rs.insert (update_id, "file", file_); - rs.insert (clean_id, "file", file_); + rs.insert (default_id, "file", file_rule::instance); + rs.insert (update_id, "file", file_rule::instance); + rs.insert (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 +#include + +namespace build +{ + namespace test + { + extern "C" void + test_init ( + scope&, scope&, const location&, std::unique_ptr&, 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 + +#include +#include +#include +#include + +#include +#include + +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& 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 m (new module (test_id)); + + { + auto& rs (base.rules); + + // Register the standard alias rule for the test operation. + // + rs.insert (test_id, "alias", alias_rule::instance); + + // Register our test running rule. + // + rs.insert (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 + +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 + +#include + +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 +#include + +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 + +#include +#include +#include +#include + +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 ()) + 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; + + template <> + bool value_proxy:: + as () 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 () const + { + const list_value& lv (as ()); + 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'. + } } -- cgit v1.1