aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build/algorithm.cxx2
-rw-r--r--build/bin/target.cxx28
-rw-r--r--build/cli/target.cxx8
-rw-r--r--build/cxx/target.cxx24
-rw-r--r--build/dump.cxx4
-rw-r--r--build/parser.cxx43
-rw-r--r--build/prerequisite1
-rw-r--r--build/rule-map5
-rw-r--r--build/target7
-rw-r--r--build/target-key5
-rw-r--r--build/target-type57
-rw-r--r--build/target.cxx48
-rw-r--r--tests/define/buildfile22
-rw-r--r--tests/define/buildfile.alias16
14 files changed, 109 insertions, 161 deletions
diff --git a/build/algorithm.cxx b/build/algorithm.cxx
index 6c3374e..461d8d2 100644
--- a/build/algorithm.cxx
+++ b/build/algorithm.cxx
@@ -111,7 +111,7 @@ namespace build
if (ttm->empty ())
continue; // Empty map for this operation id.
- auto i (ttm->find (tt->id));
+ auto i (ttm->find (tt));
if (i == ttm->end () || i->second.empty ())
continue; // No rules registered for this target type.
diff --git a/build/bin/target.cxx b/build/bin/target.cxx
index c2c5e05..6f2d7b5 100644
--- a/build/bin/target.cxx
+++ b/build/bin/target.cxx
@@ -24,14 +24,12 @@ namespace build
const target_type obja::static_type
{
- typeid (obja),
"obja",
&file::static_type,
&obja_factory,
nullptr,
&search_target, // Note: not _file(); don't look for an existing file.
- false,
- nullptr
+ false
};
static target*
@@ -48,14 +46,12 @@ namespace build
const target_type objso::static_type
{
- typeid (objso),
"objso",
&file::static_type,
&objso_factory,
nullptr,
&search_target, // Note: not _file(); don't look for an existing file.
- false,
- nullptr
+ false
};
static target*
@@ -76,26 +72,22 @@ namespace build
const target_type obj::static_type
{
- typeid (obj),
"obj",
&target::static_type,
&obj_factory,
nullptr,
&search_target,
- false,
- nullptr
+ false
};
const target_type exe::static_type
{
- typeid (exe),
"exe",
&file::static_type,
&target_factory<exe>,
nullptr,
&search_file,
- false,
- nullptr
+ false
};
static target*
@@ -125,14 +117,12 @@ namespace build
constexpr const char a_ext[] = "a";
const target_type liba::static_type
{
- typeid (liba),
"liba",
&file::static_type,
&liba_factory,
&target_extension_fix<a_ext>,
&search_file,
- false,
- nullptr
+ false
};
static target*
@@ -150,14 +140,12 @@ namespace build
constexpr const char so_ext[] = "so";
const target_type libso::static_type
{
- typeid (libso),
"libso",
&file::static_type,
&libso_factory,
&target_extension_fix<so_ext>,
&search_file,
- false,
- nullptr
+ false
};
// lib
@@ -187,14 +175,12 @@ namespace build
const target_type lib::static_type
{
- typeid (lib),
"lib",
&target::static_type,
&lib_factory,
nullptr,
&search_target,
- false,
- nullptr
+ false
};
}
}
diff --git a/build/cli/target.cxx b/build/cli/target.cxx
index 0666335..a480633 100644
--- a/build/cli/target.cxx
+++ b/build/cli/target.cxx
@@ -18,14 +18,12 @@ namespace build
constexpr const char cli_ext[] = "cli";
const target_type cli::static_type
{
- typeid (cli),
"cli",
&file::static_type,
&target_factory<cli>,
&target_extension_fix<cli_ext>,
&search_file,
- false,
- nullptr
+ false
};
// cli.cxx
@@ -66,14 +64,12 @@ namespace build
const target_type cli_cxx::static_type
{
- typeid (cli_cxx),
"cli.cxx",
&mtime_target::static_type,
&cli_cxx_factory,
nullptr,
&search_target,
- true, // "See through" default iteration mode.
- nullptr
+ true // "See through" default iteration mode.
};
}
}
diff --git a/build/cxx/target.cxx b/build/cxx/target.cxx
index e3d98e7..c8680b7 100644
--- a/build/cxx/target.cxx
+++ b/build/cxx/target.cxx
@@ -13,79 +13,67 @@ namespace build
constexpr const char hxx_ext_var[] = "hxx.ext";
const target_type hxx::static_type
{
- typeid (hxx),
"hxx",
&file::static_type,
&target_factory<hxx>,
&target_extension_var<hxx_ext_var>,
&search_file,
- false,
- nullptr
+ false
};
constexpr const char ixx_ext_var[] = "ixx.ext";
const target_type ixx::static_type
{
- typeid (ixx),
"ixx",
&file::static_type,
&target_factory<ixx>,
&target_extension_var<ixx_ext_var>,
&search_file,
- false,
- nullptr
+ false
};
constexpr const char txx_ext_var[] = "txx.ext";
const target_type txx::static_type
{
- typeid (txx),
"txx",
&file::static_type,
&target_factory<txx>,
&target_extension_var<txx_ext_var>,
&search_file,
- false,
- nullptr
+ false
};
constexpr const char cxx_ext_var[] = "cxx.ext";
const target_type cxx::static_type
{
- typeid (cxx),
"cxx",
&file::static_type,
&target_factory<cxx>,
&target_extension_var<cxx_ext_var>,
&search_file,
- false,
- nullptr
+ false
};
constexpr const char h_ext_var[] = "h.ext";
const target_type h::static_type
{
- typeid (h),
"h",
&file::static_type,
&target_factory<h>,
&target_extension_var<h_ext_var>,
&search_file,
- false,
- nullptr
+ false
};
constexpr const char c_ext_var[] = "c.ext";
const target_type c::static_type
{
- typeid (c),
"c",
&file::static_type,
&target_factory<c>,
&target_extension_var<c_ext_var>,
&search_file,
- false,
- nullptr
+ false
};
}
}
diff --git a/build/dump.cxx b/build/dump.cxx
index 7f4502e..62e032b 100644
--- a/build/dump.cxx
+++ b/build/dump.cxx
@@ -56,12 +56,12 @@ namespace build
os << endl
<< ind;
- if (t.id != target::static_type.id)
+ if (t != target::static_type)
os << t.name << '{';
os << p;
- if (t.id != target::static_type.id)
+ if (t != target::static_type)
os << '}';
os << ':';
diff --git a/build/parser.cxx b/build/parser.cxx
index 4981347..05c79db 100644
--- a/build/parser.cxx
+++ b/build/parser.cxx
@@ -808,58 +808,57 @@ namespace build
}
static target*
- alias_factory (const target_type& tt, dir_path d, string n, const string* e)
+ derived_factory (const target_type& t, dir_path d, string n, const string* e)
{
- assert (tt.origin != nullptr);
- target* r (tt.origin->factory (*tt.origin, move (d), move (n), e));
- r->alias_type = &tt;
+ target* r (t.base->factory (*t.base, move (d), move (n), e));
+ r->derived_type = &t;
return r;
}
void parser::
define (token& t, token_type& tt)
{
- // define <alias>=<name>
+ // define <derived>: <base>
//
- // See tests/define/buildfile.
+ // See tests/define.
//
if (next (t, tt) != type::name)
fail (t) << "expected name instead of " << t << " in target type "
<< "definition";
- string a (move (t.value));
- const location al (get_location (t, &path_));
+ string dn (move (t.value));
+ const location dnl (get_location (t, &path_));
- if (next (t, tt) != type::equal)
- fail (t) << "expected '=' instead of " << t << " in target type "
+ if (next (t, tt) != type::colon)
+ fail (t) << "expected ':' instead of " << t << " in target type "
<< "definition";
next (t, tt);
if (tt == type::name)
{
- // Alias.
+ // Target.
//
- const string& n (t.value);
- const target_type* ntt (scope_->find_target_type (n));
+ const string& bn (t.value);
+ const target_type* bt (scope_->find_target_type (bn));
- if (ntt == nullptr)
- fail (t) << "unknown target type " << n;
+ if (bt == nullptr)
+ fail (t) << "unknown target type " << bn;
- unique_ptr<target_type> att (new target_type (*ntt));
- att->factory = &alias_factory;
- att->origin = ntt->origin != nullptr ? ntt->origin : ntt;
+ unique_ptr<target_type> dt (new target_type (*bt));
+ dt->base = bt;
+ dt->factory = &derived_factory;
- target_type& ratt (*att); // Save non-const reference to the object.
+ target_type& rdt (*dt); // Save a non-const reference to the object.
- auto pr (scope_->target_types.emplace (a, target_type_ref (move (att))));
+ auto pr (scope_->target_types.emplace (dn, target_type_ref (move (dt))));
if (!pr.second)
- fail (al) << "target type " << a << " already define in this scope";
+ fail (dnl) << "target type " << dn << " already define in this scope";
// Patch the alias name to use the map's key storage.
//
- ratt.name = pr.first->first.c_str ();
+ rdt.name = pr.first->first.c_str ();
next (t, tt); // Get newline.
}
diff --git a/build/prerequisite b/build/prerequisite
index f91a199..3022e44 100644
--- a/build/prerequisite
+++ b/build/prerequisite
@@ -10,7 +10,6 @@
#include <iosfwd>
#include <utility> // move
#include <cassert>
-#include <typeindex>
#include <functional> // reference_wrapper
#include <build/types>
diff --git a/build/rule-map b/build/rule-map
index 0ce49e7..d262ecd 100644
--- a/build/rule-map
+++ b/build/rule-map
@@ -9,7 +9,6 @@
#include <vector>
#include <string>
#include <memory> // unique_ptr
-#include <typeindex>
#include <functional> // reference_wrapper
#include <butl/prefix-map>
@@ -22,7 +21,7 @@ namespace build
class rule;
using target_type_rule_map = std::map<
- std::type_index, // Target type.
+ const target_type*,
butl::prefix_map<std::string, // Rule hint.
std::reference_wrapper<rule>, '.'>>;
@@ -41,7 +40,7 @@ namespace build
if (oid >= map_.size ())
map_.resize ((oid < 3 ? 3 : oid) + 1);
- map_[oid][typeid (T)].emplace (hint, r);
+ map_[oid][&T::static_type].emplace (hint, r);
}
// Return NULL if not found.
diff --git a/build/target b/build/target
index a1c7880..66daa66 100644
--- a/build/target
+++ b/build/target
@@ -354,15 +354,14 @@ namespace build
const T*
is_a () const {return dynamic_cast<const T*> (this);}
- // An alias target type should be the same as its target type except
- // for the name.
+ // Dynamic derivation to support define.
//
- const target_type* alias_type = nullptr;
+ const target_type* derived_type = nullptr;
const target_type&
type () const
{
- return alias_type != nullptr ? *alias_type : dynamic_type ();
+ return derived_type != nullptr ? *derived_type : dynamic_type ();
}
virtual const target_type& dynamic_type () const = 0;
diff --git a/build/target-key b/build/target-key
index f49efb2..526a33a 100644
--- a/build/target-key
+++ b/build/target-key
@@ -8,7 +8,6 @@
#include <map>
#include <string>
#include <ostream>
-#include <typeindex>
#include <functional> // reference_wrapper
#include <butl/utility> // compare_c_string
@@ -31,8 +30,8 @@ namespace build
friend bool
operator< (const target_key& x, const target_key& y)
{
- const std::type_index& xt (x.type->id);
- const std::type_index& yt (y.type->id);
+ const target_type* xt (x.type);
+ const target_type* yt (y.type);
//@@ TODO: use compare() to compare once.
diff --git a/build/target-type b/build/target-type
index 2c93455..e299fe2 100644
--- a/build/target-type
+++ b/build/target-type
@@ -8,9 +8,6 @@
#include <map>
#include <string>
#include <ostream>
-#include <typeindex>
-
-#include <butl/utility> // compare_c_string
#include <build/types>
@@ -23,9 +20,13 @@ namespace build
// Target type.
//
+ // Note that we assume there is always a single instance of this class
+ // for any target type. As a result, we can use address comparison to
+ // determine if two target types are the same.
+ //
+ //
struct target_type
{
- std::type_index id;
const char* name;
const target_type* base;
target* (*factory) (const target_type&, dir_path, string, const string*);
@@ -33,60 +34,50 @@ namespace build
target* (*search) (const prerequisite_key&);
bool see_through; // A group with the default "see through" semantics.
- const target_type* origin; // Original target if this is an alias.
-
bool
- is_a (const std::type_index&) const; // Defined in target.cxx
+ is_a (const target_type&) const; // Defined in target.cxx
template <typename T>
bool
- is_a () const {return is_a (typeid (T));}
+ is_a () const {return is_a (T::static_type);}
};
inline bool
- operator< (const target_type& x, const target_type& y)
- {
- return x.id < y.id;
- }
+ operator< (const target_type& x, const target_type& y) {return &x < &y;}
+
+ inline bool
+ operator== (const target_type& x, const target_type& y) {return &x == &y;}
+
+ inline bool
+ operator!= (const target_type& x, const target_type& y) {return &x != &y;}
inline std::ostream&
- operator<< (std::ostream& os, const target_type& tt)
- {
- return os << tt.name;
- }
+ operator<< (std::ostream& os, const target_type& tt) {return os << tt.name;}
// Target type map.
//
struct target_type_ref
{
- // Like reference_wrapper except it deletes the target type if it is
- // an alias (aliases are always dynamically allocated).
+ // Like reference_wrapper except it sometimes deletes the target type.
//
explicit
- target_type_ref (const target_type& r): p_ (&r)
- {
- assert (p_->origin == nullptr);
- }
+ target_type_ref (const target_type& r): p_ (&r), d_ (false) {}
explicit
- target_type_ref (unique_ptr<target_type>&& p): p_ (p.release ())
- {
- assert (p_->origin != nullptr);
- }
+ target_type_ref (unique_ptr<target_type>&& p)
+ : p_ (p.release ()), d_ (true) {}
+
+ target_type_ref (target_type_ref&& r)
+ : p_ (r.p_), d_ (r.d_) {r.p_ = nullptr;}
- ~target_type_ref ()
- {
- if (p_ != nullptr && p_->origin != nullptr)
- delete p_;
- }
+ ~target_type_ref () {if (p_ != nullptr && d_) delete p_;}
explicit operator const target_type& () const {return *p_;}
const target_type& get () const {return *p_;}
- target_type_ref (target_type_ref&& r): p_ (r.p_) {r.p_ = nullptr;}
-
private:
const target_type* p_;
+ bool d_;
};
using target_type_map_base = std::map<string, target_type_ref>;
diff --git a/build/target.cxx b/build/target.cxx
index 649e570..7c45e3e 100644
--- a/build/target.cxx
+++ b/build/target.cxx
@@ -20,10 +20,10 @@ namespace build
// target_type
//
bool target_type::
- is_a (const type_index& id) const
+ is_a (const target_type& tt) const
{
for (const target_type* p (this); p != nullptr; p = p->base)
- if (p->id == id)
+ if (*p == tt)
return true;
return false;
@@ -440,38 +440,32 @@ namespace build
const target_type target::static_type
{
- typeid (target),
"target",
nullptr,
nullptr,
nullptr,
&search_target,
- false,
- nullptr
+ false
};
const target_type mtime_target::static_type
{
- typeid (mtime_target),
"mtime_target",
&target::static_type,
nullptr,
nullptr,
&search_target,
- false,
- nullptr
+ false
};
const target_type path_target::static_type
{
- typeid (path_target),
"path_target",
&mtime_target::static_type,
nullptr,
nullptr,
&search_target,
- false,
- nullptr
+ false
};
template <typename T>
@@ -490,50 +484,42 @@ namespace build
constexpr const char file_ext[] = "";
const target_type file::static_type
{
- typeid (file),
"file",
&path_target::static_type,
&file_factory<file>,
&target_extension_fix<file_ext>,
&search_file,
- false,
- nullptr
+ false
};
const target_type alias::static_type
{
- typeid (alias),
"alias",
&target::static_type,
&target_factory<alias>,
nullptr, // Should never need.
&search_alias,
- false,
- nullptr
+ false
};
const target_type dir::static_type
{
- typeid (dir),
"dir",
&alias::static_type,
&target_factory<dir>,
nullptr, // Should never need.
&search_alias,
- false,
- nullptr
+ false
};
const target_type fsdir::static_type
{
- typeid (fsdir),
"fsdir",
&target::static_type,
&target_factory<fsdir>,
nullptr, // Should never need.
&search_target,
- false,
- nullptr
+ false
};
static const std::string&
@@ -547,27 +533,23 @@ namespace build
const target_type buildfile::static_type
{
- typeid (buildfile),
"buildfile",
&file::static_type,
&file_factory<buildfile>,
&buildfile_target_extension,
&search_file,
- false,
- nullptr
+ false
};
constexpr const char doc_ext[] = "";
const target_type doc::static_type
{
- typeid (doc),
"doc",
&file::static_type,
&file_factory<doc>,
&target_extension_fix<doc_ext>,
&search_file,
- false,
- nullptr
+ false
};
static target*
@@ -581,26 +563,22 @@ namespace build
const target_type man::static_type
{
- typeid (man),
"man",
&doc::static_type,
&man_factory,
nullptr, // Should be specified explicitly.
&search_file,
- false,
- nullptr
+ false
};
constexpr const char man1_ext[] = "1";
const target_type man1::static_type
{
- typeid (man1),
"man1",
&man::static_type,
&file_factory<man1>,
&target_extension_fix<man1_ext>,
&search_file,
- false,
- nullptr
+ false
};
}
diff --git a/tests/define/buildfile b/tests/define/buildfile
index d3b9fc4..55b9e92 100644
--- a/tests/define/buildfile
+++ b/tests/define/buildfile
@@ -1,16 +1,14 @@
-#define # expected name
-#define foo # expected =
-#define foo= # expected name
-#define foo=bar # unknown target type
+#define # expected name
+#define foo # expected :
+#define foo: # expected name
+#define foo: bar # unknown target type
-define foo=file
-foo{FOO}: # verify name is foo{FOO} and not file{FOO} with --verbose 6
+define foo: file
+foo{FOO}: # verify name is foo{FOO} and not file{FOO} with --verbose 6
-#define foo=dir # already define in this scope
+#define foo: dir # already define in this scope
-define bar=foo
-bar{FOO}: # verify name is foo{FOO} and not bar{FOO} with --verbose 6
-bar{BAR}: # verify name is bar{BAR}
+define bar: foo
+bar{BAR}: # verify name is bar{FOO} with --verbose 6
-define folder=dir
-folder{./}: # verify prints "folder{} is up to date"
+./:
diff --git a/tests/define/buildfile.alias b/tests/define/buildfile.alias
new file mode 100644
index 0000000..d3b9fc4
--- /dev/null
+++ b/tests/define/buildfile.alias
@@ -0,0 +1,16 @@
+#define # expected name
+#define foo # expected =
+#define foo= # expected name
+#define foo=bar # unknown target type
+
+define foo=file
+foo{FOO}: # verify name is foo{FOO} and not file{FOO} with --verbose 6
+
+#define foo=dir # already define in this scope
+
+define bar=foo
+bar{FOO}: # verify name is foo{FOO} and not bar{FOO} with --verbose 6
+bar{BAR}: # verify name is bar{BAR}
+
+define folder=dir
+folder{./}: # verify prints "folder{} is up to date"