aboutsummaryrefslogtreecommitdiff
path: root/build2/bin
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2017-05-31 16:35:50 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2017-05-31 16:36:49 +0200
commit9ae4897cfe935598333a5f709e967fefc4c161aa (patch)
tree16bfbcb21a10994a29db602f5cb77a0a50627bdf /build2/bin
parentb2fc1fb4a13ffa58640333a3909dd0e53bd21995 (diff)
C++ modules work: add target types
Diffstat (limited to 'build2/bin')
-rw-r--r--build2/bin/init.cxx9
-rw-r--r--build2/bin/rule.cxx14
-rw-r--r--build2/bin/rule.hxx12
-rw-r--r--build2/bin/target.cxx135
-rw-r--r--build2/bin/target.hxx61
5 files changed, 182 insertions, 49 deletions
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<obja> ();
t.insert<objs> ();
+ t.insert<bmi> ();
+ t.insert<bmie> ();
+ t.insert<bmia> ();
+ t.insert<bmis> ();
+
t.insert<lib> ();
t.insert<liba> ();
t.insert<libs> ();
@@ -419,6 +425,9 @@ namespace build2
r.insert<obj> (perform_update_id, "bin.obj", obj_);
r.insert<obj> (perform_clean_id, "bin.obj", obj_);
+ r.insert<bmi> (perform_update_id, "bin.bmi", bmi_);
+ r.insert<bmi> (perform_clean_id, "bin.bmi", bmi_);
+
r.insert<lib> (perform_update_id, "bin.lib", lib_);
r.insert<lib> (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 <typename T>
+ // obj*{} and bmi*{} member factory.
+ //
+ template <typename M, typename G>
static pair<target*, optional<string>>
- objx_factory (const target_type&,
- dir_path dir,
- dir_path out,
- string n,
- optional<string> ext)
+ m_factory (const target_type&,
+ dir_path dir,
+ dir_path out,
+ string n,
+ optional<string> ext)
{
- const obj* g (targets.find<obj> (dir, out, n));
+ const G* g (targets.find<G> (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<obje>,
+ &m_factory<obje, obj>,
+ &target_extension_var<ext_var, nullptr>,
+ &target_pattern_var<ext_var, nullptr>,
+ 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<bmie, bmi>,
&target_extension_var<ext_var, nullptr>,
&target_pattern_var<ext_var, nullptr>,
nullptr,
@@ -51,7 +65,19 @@ namespace build2
{
"obja",
&file::static_type,
- &objx_factory<obja>,
+ &m_factory<obja, obj>,
+ &target_extension_var<ext_var, nullptr>,
+ &target_pattern_var<ext_var, nullptr>,
+ 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<bmia, bmi>,
&target_extension_var<ext_var, nullptr>,
&target_pattern_var<ext_var, nullptr>,
nullptr,
@@ -63,7 +89,7 @@ namespace build2
{
"objs",
&file::static_type,
- &objx_factory<objs>,
+ &m_factory<objs, obj>,
&target_extension_var<ext_var, nullptr>,
&target_pattern_var<ext_var, nullptr>,
nullptr,
@@ -71,39 +97,54 @@ namespace build2
false
};
+ const target_type bmis::static_type
+ {
+ "bmis",
+ &file::static_type,
+ &m_factory<bmis, bmi>,
+ &target_extension_var<ext_var, nullptr>,
+ &target_pattern_var<ext_var, nullptr>,
+ nullptr,
+ &target_search, // Note: not _file(); don't look for an existing file.
+ false
+ };
+
+ // obj{} and bmi{} group factory.
+ //
+ template <typename G, typename E, typename A, typename S>
static pair<target*, optional<string>>
- obj_factory (const target_type&,
- dir_path dir,
- dir_path out,
- string n,
- optional<string> ext)
+ g_factory (const target_type&,
+ dir_path dir,
+ dir_path out,
+ string n,
+ optional<string> ext)
{
// Casts are MT-aware (during serial load).
//
- obje* e (phase == run_phase::load
- ? const_cast<obje*> (targets.find<obje> (dir, out, n))
- : nullptr);
- obja* a (phase == run_phase::load
- ? const_cast<obja*> (targets.find<obja> (dir, out, n))
- : nullptr);
- objs* s (phase == run_phase::load
- ? const_cast<objs*> (targets.find<objs> (dir, out, n))
- : nullptr);
+ E* e (phase == run_phase::load
+ ? const_cast<E*> (targets.find<E> (dir, out, n))
+ : nullptr);
+ A* a (phase == run_phase::load
+ ? const_cast<A*> (targets.find<A> (dir, out, n))
+ : nullptr);
+ S* s (phase == run_phase::load
+ ? const_cast<S*> (targets.find<S> (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<obj, obje, obja, objs>,
nullptr,
nullptr,
nullptr,
@@ -111,21 +152,17 @@ namespace build2
false
};
- template <typename T>
- static pair<target*, optional<string>>
- libx_factory (const target_type&,
- dir_path dir,
- dir_path out,
- string n,
- optional<string> ext)
+ const target_type bmi::static_type
{
- const lib* g (targets.find<lib> (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<bmi, bmie, bmia, bmis>,
+ 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<liba>,
+ &m_factory<liba, lib>,
&target_extension_var<ext_var, nullptr>,
&target_pattern_var<ext_var, nullptr>,
nullptr,
@@ -153,7 +190,7 @@ namespace build2
{
"libs",
&file::static_type,
- &libx_factory<libs>,
+ &m_factory<libs, lib>,
&target_extension_var<ext_var, nullptr>,
&target_pattern_var<ext_var, nullptr>,
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