diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2015-12-01 13:39:09 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2015-12-01 13:42:10 +0200 |
commit | 7996c2bfc2d7e998e2f9f1236d457ec7bea8ad8a (patch) | |
tree | dca79d3657bec47d4cd5db85899a70d3d49c079e /build/target-type | |
parent | f355a4379f035df61a7702f5ff805eefb004fb20 (diff) |
Implement support for definition target type aliases
For example:
define cli=file
Currently, the semantics is that of a real alias with only name differences
that are used for display. See tests/define/buildfile for more use cases.
Diffstat (limited to 'build/target-type')
-rw-r--r-- | build/target-type | 48 |
1 files changed, 39 insertions, 9 deletions
diff --git a/build/target-type b/build/target-type index 154714c..2c93455 100644 --- a/build/target-type +++ b/build/target-type @@ -9,7 +9,6 @@ #include <string> #include <ostream> #include <typeindex> -#include <functional> // reference_wrapper #include <butl/utility> // compare_c_string @@ -29,11 +28,13 @@ namespace build std::type_index id; const char* name; const target_type* base; - target* (*const factory) (dir_path, std::string, const std::string*); - const std::string& (*const extension) (const target_key&, scope&); - target* (*const search) (const prerequisite_key&); + target* (*factory) (const target_type&, dir_path, string, const string*); + const string& (*extension) (const target_key&, scope&); + 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 @@ -56,16 +57,45 @@ namespace build // Target type map. // - using target_type_map_base = std::map< - const char*, - std::reference_wrapper<const target_type>, - butl::compare_c_string>; + struct target_type_ref + { + // Like reference_wrapper except it deletes the target type if it is + // an alias (aliases are always dynamically allocated). + // + explicit + target_type_ref (const target_type& r): p_ (&r) + { + assert (p_->origin == nullptr); + } + + explicit + target_type_ref (unique_ptr<target_type>&& p): p_ (p.release ()) + { + assert (p_->origin != nullptr); + } + + ~target_type_ref () + { + if (p_ != nullptr && p_->origin != nullptr) + 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_; + }; + + using target_type_map_base = std::map<string, target_type_ref>; class target_type_map: public target_type_map_base { public: void - insert (const target_type& tt) {emplace (tt.name, tt);} + insert (const target_type& tt) {emplace (tt.name, target_type_ref (tt));} template <typename T> void |