From 9ae4897cfe935598333a5f709e967fefc4c161aa Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Wed, 31 May 2017 16:35:50 +0200 Subject: C++ modules work: add target types --- build2/bin/init.cxx | 9 ++++ build2/bin/rule.cxx | 14 ++++++ build2/bin/rule.hxx | 12 +++++ build2/bin/target.cxx | 135 ++++++++++++++++++++++++++++++++------------------ build2/bin/target.hxx | 61 +++++++++++++++++++++++ 5 files changed, 182 insertions(+), 49 deletions(-) (limited to 'build2/bin') diff --git a/build2/bin/init.cxx b/build2/bin/init.cxx index 71c77b2..71c580b 100644 --- a/build2/bin/init.cxx +++ b/build2/bin/init.cxx @@ -25,6 +25,7 @@ namespace build2 namespace bin { static const obj_rule obj_; + static const bmi_rule bmi_; static const lib_rule lib_; // Default config.bin.*.lib values. @@ -362,6 +363,11 @@ namespace build2 t.insert (); t.insert (); + t.insert (); + t.insert (); + t.insert (); + t.insert (); + t.insert (); t.insert (); t.insert (); @@ -419,6 +425,9 @@ namespace build2 r.insert (perform_update_id, "bin.obj", obj_); r.insert (perform_clean_id, "bin.obj", obj_); + r.insert (perform_update_id, "bin.bmi", bmi_); + r.insert (perform_clean_id, "bin.bmi", bmi_); + r.insert (perform_update_id, "bin.lib", lib_); r.insert (perform_clean_id, "bin.lib", lib_); diff --git a/build2/bin/rule.cxx b/build2/bin/rule.cxx index 3aa3c81..b6e5a53 100644 --- a/build2/bin/rule.cxx +++ b/build2/bin/rule.cxx @@ -31,6 +31,20 @@ namespace build2 recipe obj_rule:: apply (action, target&) const {return empty_recipe;} + // bmi + // + match_result bmi_rule:: + match (action a, target& t, const string&) const + { + fail << diag_doing (a, t) << " target group" << + info << "explicitly select bmie{}, bmia{}, or bmis{} member"; + + return false; + } + + recipe bmi_rule:: + apply (action, target&) const {return empty_recipe;} + // lib // // The whole logic is pretty much as if we had our two group members as diff --git a/build2/bin/rule.hxx b/build2/bin/rule.hxx index 7109473..4637479 100644 --- a/build2/bin/rule.hxx +++ b/build2/bin/rule.hxx @@ -26,6 +26,18 @@ namespace build2 apply (action, target&) const override; }; + class bmi_rule: public rule + { + public: + bmi_rule () {} + + virtual match_result + match (action, target&, const string&) const override; + + virtual recipe + apply (action, target&) const override; + }; + class lib_rule: public rule { public: diff --git a/build2/bin/target.cxx b/build2/bin/target.cxx index 962befa..f0e0152 100644 --- a/build2/bin/target.cxx +++ b/build2/bin/target.cxx @@ -19,27 +19,41 @@ namespace build2 extern const char ext_var[] = "extension"; // VC14 rejects constexpr. - template + // obj*{} and bmi*{} member factory. + // + template static pair> - objx_factory (const target_type&, - dir_path dir, - dir_path out, - string n, - optional ext) + m_factory (const target_type&, + dir_path dir, + dir_path out, + string n, + optional ext) { - const obj* g (targets.find (dir, out, n)); + const G* g (targets.find (dir, out, n)); - T* x (new T (move (dir), move (out), move (n))); - x->group = g; + M* m (new M (move (dir), move (out), move (n))); + m->group = g; - return make_pair (x, move (ext)); + return make_pair (m, move (ext)); } const target_type obje::static_type { "obje", &file::static_type, - &objx_factory, + &m_factory, + &target_extension_var, + &target_pattern_var, + nullptr, + &target_search, // Note: not _file(); don't look for an existing file. + false + }; + + const target_type bmie::static_type + { + "bmie", + &file::static_type, + &m_factory, &target_extension_var, &target_pattern_var, nullptr, @@ -51,7 +65,19 @@ namespace build2 { "obja", &file::static_type, - &objx_factory, + &m_factory, + &target_extension_var, + &target_pattern_var, + nullptr, + &target_search, // Note: not _file(); don't look for an existing file. + false + }; + + const target_type bmia::static_type + { + "bmia", + &file::static_type, + &m_factory, &target_extension_var, &target_pattern_var, nullptr, @@ -63,7 +89,7 @@ namespace build2 { "objs", &file::static_type, - &objx_factory, + &m_factory, &target_extension_var, &target_pattern_var, nullptr, @@ -71,39 +97,54 @@ namespace build2 false }; + const target_type bmis::static_type + { + "bmis", + &file::static_type, + &m_factory, + &target_extension_var, + &target_pattern_var, + nullptr, + &target_search, // Note: not _file(); don't look for an existing file. + false + }; + + // obj{} and bmi{} group factory. + // + template static pair> - obj_factory (const target_type&, - dir_path dir, - dir_path out, - string n, - optional ext) + g_factory (const target_type&, + dir_path dir, + dir_path out, + string n, + optional ext) { // Casts are MT-aware (during serial load). // - obje* e (phase == run_phase::load - ? const_cast (targets.find (dir, out, n)) - : nullptr); - obja* a (phase == run_phase::load - ? const_cast (targets.find (dir, out, n)) - : nullptr); - objs* s (phase == run_phase::load - ? const_cast (targets.find (dir, out, n)) - : nullptr); + E* e (phase == run_phase::load + ? const_cast (targets.find (dir, out, n)) + : nullptr); + A* a (phase == run_phase::load + ? const_cast (targets.find (dir, out, n)) + : nullptr); + S* s (phase == run_phase::load + ? const_cast (targets.find (dir, out, n)) + : nullptr); - obj* o (new obj (move (dir), move (out), move (n))); + G* g (new G (move (dir), move (out), move (n))); - if (e != nullptr) e->group = o; - if (a != nullptr) a->group = o; - if (s != nullptr) s->group = o; + if (e != nullptr) e->group = g; + if (a != nullptr) a->group = g; + if (s != nullptr) s->group = g; - return make_pair (o, move (ext)); + return make_pair (g, move (ext)); } const target_type obj::static_type { "obj", &target::static_type, - &obj_factory, + &g_factory, nullptr, nullptr, nullptr, @@ -111,21 +152,17 @@ namespace build2 false }; - template - static pair> - libx_factory (const target_type&, - dir_path dir, - dir_path out, - string n, - optional ext) + const target_type bmi::static_type { - const lib* g (targets.find (dir, out, n)); - - T* x (new T (move (dir), move (out), move (n))); - x->group = g; - - return make_pair (x, move (ext)); - } + "bmi", + &target::static_type, + &g_factory, + nullptr, + nullptr, + nullptr, + &target_search, + false + }; // What extensions should we use? At the outset, this is platform- // dependent. And if we consider cross-compilation, is it build or @@ -141,7 +178,7 @@ namespace build2 { "liba", &file::static_type, - &libx_factory, + &m_factory, &target_extension_var, &target_pattern_var, nullptr, @@ -153,7 +190,7 @@ namespace build2 { "libs", &file::static_type, - &libx_factory, + &m_factory, &target_extension_var, &target_pattern_var, nullptr, diff --git a/build2/bin/target.hxx b/build2/bin/target.hxx index d920cc1..13d7596 100644 --- a/build2/bin/target.hxx +++ b/build2/bin/target.hxx @@ -56,6 +56,67 @@ namespace build2 virtual const target_type& dynamic_type () const {return static_type;} }; + // Binary module interface. + // + // While currently there are only C++ modules, if things pan out, chances + // are we will have C (or Obj-C) modules. And in that case it is plausible + // we will also have some binutils to examine BMIs, similar to objdump, + // etc. So that's why this target type is in bin and not cxx. + // + // bmi*{} is similar to obj*{} though the semantics is a bit different: + // the idea is that we should try hard to re-use a single bmiX{} file for + // an entire "build" but if that's not possible (because the compilation + // options are too different), then compile a private version for + // ourselves (the definition of "too different" is, of course, compiler- + // specific). + // + // When we compile a module interface unit, we end up with bmi*{} and + // obj*{}. How that obj*{} is produced is compiler-dependent. While it + // makes sense to decouple the production of the two in order to increase + // parallelism, doing so will further complicate the already hairy + // organization. So, at least for now, we produce the two at the same time + // and make obj*{} an ad hoc member of bmi*{}. + // + class bmie: public file + { + public: + using file::file; + + public: + static const target_type static_type; + virtual const target_type& dynamic_type () const {return static_type;} + }; + + class bmia: public file + { + public: + using file::file; + + public: + static const target_type static_type; + virtual const target_type& dynamic_type () const {return static_type;} + }; + + class bmis: public file + { + public: + using file::file; + + public: + static const target_type static_type; + virtual const target_type& dynamic_type () const {return static_type;} + }; + + class bmi: public target + { + public: + using target::target; + + public: + static const target_type static_type; + virtual const target_type& dynamic_type () const {return static_type;} + }; + // The lib{} target group. // class liba: public file -- cgit v1.1