diff options
Diffstat (limited to 'libbuild2/target-type.hxx')
-rw-r--r-- | libbuild2/target-type.hxx | 120 |
1 files changed, 100 insertions, 20 deletions
diff --git a/libbuild2/target-type.hxx b/libbuild2/target-type.hxx index 88171f5..93c5744 100644 --- a/libbuild2/target-type.hxx +++ b/libbuild2/target-type.hxx @@ -4,8 +4,6 @@ #ifndef LIBBUILD2_TARGET_TYPE_HXX #define LIBBUILD2_TARGET_TYPE_HXX -#include <map> - #include <libbuild2/types.hxx> #include <libbuild2/forward.hxx> #include <libbuild2/utility.hxx> @@ -24,10 +22,23 @@ namespace build2 // type does not use extensions. Note that this is relied upon when deciding // whether to print the extension. // - // The fixed extension function should return the fixed extension (which can - // point to the key's ext member; note that for performance reasons we - // currently only verify the explicitly specified extension on target - // insersion -- see target_key comparison for details). + // If the fixed extension function is specified, then it means that this + // target type has a fixed extension (including the no-extension case) and + // this function should return such a fixed extension (which, if overriding + // by the user is allowed, can point to the key's ext member; note that for + // performance reasons we currently only verify the explicitly specified + // extension on target insersion -- see target_key comparison for details). + // It is called eraly, during the target insertion, in contrast to the + // default extension function described below (you would specify one or the + // other). + // + // Note that the fixed no-extension case that allows overriding by the user + // is used to implement the "if extension is not specified by the user then + // there is no extension" semantics of the file{} and similar target types. + // For such cases the target_extension_none() function should be used (we + // compare to it's address to detect target types with such semantics). + // Similarly, for cases where the user must specify the extension explicitly + // (e.g., man{}), use target_extension_must(). // // The root scope argument to the fixed extension function may be NULL which // means the root scope is not known. A target type that relies on this must @@ -78,11 +89,41 @@ namespace build2 const location&, bool reverse); - void (*print) (ostream&, const target_key&); + // See to_stream(ostream,target_key) for details. + // + bool (*print) (ostream&, const target_key&, bool name_only); + + // Target type-specific prerequisite to target search. + // + // If passed target is NULL, then only search for an existing target (and + // which can be performed during execute, not only match). + // + const target* (*search) (context&, + const target*, + const prerequisite_key&); + + // Target type flags. + // + // Note that the member_hint flag should only be used on groups with + // link-up during load (see lib{}, for example). In particular, if the + // group link-up only happens during match, then the hint would be looked + // up before the group is known. + // + // Note: consider exposing as an attribute in define if adding a new flag. + // + enum class flag: uint64_t + { + none = 0, + group = 0x01, // A (non-adhoc) group. + see_through = group | 0x02, // A group with "see through" semantics. + member_hint = group | 0x04, // Untyped rule hint applies to members. + dyn_members = group | 0x08 // A group with dynamic members. + }; - const target* (*search) (const target&, const prerequisite_key&); + flag flags; - bool see_through; // A group with the default "see through" semantics. + bool + see_through () const; template <typename T> bool @@ -91,14 +132,18 @@ namespace build2 bool is_a (const target_type& tt) const { - return this == &tt || (base != nullptr && is_a_base (tt)); + for (const target_type* b (this); b != nullptr; b = b->base) + if (b == &tt) + return true; + + return false; } bool is_a (const char*) const; // Defined in target.cxx - bool - is_a_base (const target_type&) const; // Defined in target.cxx + target_type& operator= (target_type&&) = delete; + target_type& operator= (const target_type&) = delete; }; inline bool @@ -113,6 +158,32 @@ namespace build2 inline ostream& operator<< (ostream& os, const target_type& tt) {return os << tt.name;} + inline target_type::flag + operator&= (target_type::flag& x, target_type::flag y) + { + return x = static_cast<target_type::flag> ( + static_cast<uint64_t> (x) & static_cast<uint64_t> (y)); + } + + inline target_type::flag + operator|= (target_type::flag& x, target_type::flag y) + { + return x = static_cast<target_type::flag> ( + static_cast<uint64_t> (x) | static_cast<uint64_t> (y)); + } + + inline target_type::flag + operator& (target_type::flag x, target_type::flag y) {return x &= y;} + + inline target_type::flag + operator| (target_type::flag x, target_type::flag y) {return x |= y;} + + inline bool target_type:: + see_through () const + { + return (flags & flag::see_through) == flag::see_through; + } + // Target type map. // class target_type_map @@ -133,18 +204,18 @@ namespace build2 return type_map_.empty (); } - const target_type& + pair<reference_wrapper<const target_type>, bool> insert (const target_type& tt) { - type_map_.emplace (tt.name, target_type_ref (tt)); - return tt; + auto r (type_map_.emplace (tt.name, target_type_ref (tt))); + return {r.second ? tt : r.first->second.get (), r.second}; } template <typename T> const target_type& insert () { - return insert (T::static_type); + return insert (T::static_type).first; } pair<reference_wrapper<const target_type>, bool> @@ -178,7 +249,7 @@ namespace build2 file_map_.emplace (n, tt); } - private: + public: struct target_type_ref { // Like reference_wrapper except it sometimes deletes the target type. @@ -190,7 +261,7 @@ namespace build2 target_type_ref (unique_ptr<target_type>&& p) : p_ (p.release ()), d_ (true) {} - target_type_ref (target_type_ref&& r) + target_type_ref (target_type_ref&& r) noexcept : p_ (r.p_), d_ (r.d_) {r.p_ = nullptr;} ~target_type_ref () {if (p_ != nullptr && d_) delete p_;} @@ -203,8 +274,17 @@ namespace build2 bool d_; }; - std::map<string, target_type_ref> type_map_; - std::map<string, reference_wrapper<const target_type>> file_map_; + using type_map = map<string, target_type_ref>; + using file_map = map<string, reference_wrapper<const target_type>>; + + using type_iterator = type_map::const_iterator; + + type_iterator type_begin () const {return type_map_.begin ();} + type_iterator type_end () const {return type_map_.end ();} + + private: + type_map type_map_; + file_map file_map_; }; } |