aboutsummaryrefslogtreecommitdiff
path: root/build/target-type
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2015-12-01 14:46:45 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2015-12-01 14:46:45 +0200
commit10fd2aface4486fc7f873dd2b54a1c2073c0b434 (patch)
tree5133810cf33b3e4ba4dfe78f659ee65599c31ffd /build/target-type
parent7996c2bfc2d7e998e2f9f1236d457ec7bea8ad8a (diff)
Reimplement define as dynamic derivation rather than alias
New syntax: define cli: file The rationale is we need to be able to assign the file extension (using type/pattern-specific variables). And if it is an alias, we will assign it to the original target type. Note that we could still support aliases if we need to. Will need to bring back the id member in target_type that would normally point to itself but for an alias would point to the origin.
Diffstat (limited to 'build/target-type')
-rw-r--r--build/target-type57
1 files changed, 24 insertions, 33 deletions
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>;