// file : build2/target-type -*- C++ -*- // copyright : Copyright (c) 2014-2016 Code Synthesis Ltd // license : MIT; see accompanying LICENSE file #ifndef BUILD2_TARGET_TYPE #define BUILD2_TARGET_TYPE #include #include #include #include #include namespace build2 { class scope; class target; class target_key; class prerequisite_key; // 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. // // If the extension derivation function is NULL, then it means this target // type does not use extensions. Note that this is relied upon when deciding // whether to print the extension; if the target does use extensions but the // defaults could not (and its ok), could not (and its not ok), or should not // (logically) be obtained, then use target_extension_{null,fail,assert}(), // respectively. If the extension function returns NULL, then that means the // default extension for this target could not be derived. // // The extension function is used in two places: search_existing_file() and // in target::derive_path(); see their implementations for details. // struct target_type { const char* name; const target_type* base; target* (*factory) (const target_type&, dir_path, string, const string*); const string* (*extension) (const target_key&, scope&); void (*print) (ostream&, const target_key&); target* (*search) (const prerequisite_key&); bool see_through; // A group with the default "see through" semantics. bool is_a (const target_type&) const; // Defined in target.cxx template bool is_a () const {return is_a (T::static_type);} }; 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 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;} // Target type map. // struct target_type_ref { // Like reference_wrapper except it sometimes deletes the target type. // explicit target_type_ref (const target_type& r): p_ (&r), d_ (false) {} explicit target_type_ref (unique_ptr&& 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 && d_) delete p_;} explicit operator const target_type& () const {return *p_;} const target_type& get () const {return *p_;} private: const target_type* p_; bool d_; }; using target_type_map_base = std::map; class target_type_map: public target_type_map_base { public: void insert (const target_type& tt) {emplace (tt.name, target_type_ref (tt));} template void insert () {insert (T::static_type);} }; } #endif // BUILD2_TARGET_TYPE