aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/target-type.hxx
diff options
context:
space:
mode:
Diffstat (limited to 'libbuild2/target-type.hxx')
-rw-r--r--libbuild2/target-type.hxx120
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_;
};
}