// file : build2/target.txx -*- C++ -*- // copyright : Copyright (c) 2014-2018 Code Synthesis Ltd // license : MIT; see accompanying LICENSE file #include // dir_iterator #include #include #include namespace build2 { // prerequisite_members_range // template void prerequisite_members_range::iterator:: switch_mode () { // A group could be empty, so we may have to iterate. // do { g_ = resolve_members (r_->a_, search (r_->t_, *i_)); // Group could not be resolved. // if (g_.members == nullptr) { assert (r_->mode_ != members_mode::always); return; } if (g_.count != 0) // Skip empty see through groups. { j_ = 1; // Start from the first group member. break; } } while (++i_ != r_->e_ && i_->type.see_through); } // // template const char* target_extension_fix (const target_key& tk) { // A generic file target type doesn't imply any extension while a very // specific one (say man1) may have a fixed extension. So if one wasn't // specified set it to fixed ext rather than unspecified. For file{} // itself we make it empty which means we treat file{foo} as file{foo.}. // return tk.ext ? tk.ext->c_str () : ext; } template bool target_pattern_fix (const target_type&, const scope&, string& v, optional& e, const location& l, bool r) { if (r) { // If we get called to reverse then it means we've added the extension // in the first place. // assert (e); e = nullopt; } else { e = target::split_name (v, l); // We only add our extension if there isn't one already. // if (!e) { e = ext; return true; } } return false; } inline optional target_extension_var_impl (const target_type& tt, const string& tn, const scope& s, const char* var, const char* def) { // Include target type/pattern-specific variables. // if (auto l = s.find (var_pool[var], tt, tn)) { // Help the user here and strip leading '.' from the extension. // const string& e (cast (l)); return !e.empty () && e.front () == '.' ? string (e, 1) : e; } return def != nullptr ? optional (def) : nullopt; } template optional target_extension_var (const target_key& tk, const scope& s, const char*, bool) { return target_extension_var_impl (*tk.type, *tk.name, s, var, def); } template bool target_pattern_var (const target_type& tt, const scope& s, string& v, optional& e, const location& l, bool r) { if (r) { // If we get called to reverse then it means we've added the extension // in the first place. // assert (e); e = nullopt; } else { e = target::split_name (v, l); // We only add our extension if there isn't one already. // if (!e) { // Use empty name as a target since we only want target type/pattern- // specific variables that match any target ('*' but not '*.txt'). // if ((e = target_extension_var_impl (tt, string (), s, var, def))) return true; } } return false; } // dir // template const target* dir:: search_implied (const scope& base, const K& k, tracer& trace) { using namespace butl; // See if we have any subdirectories. // prerequisites_type ps; try { for (const dir_entry& e: dir_iterator (base.src_path (), true /* ignore_dangling */)) { if (e.type () == entry_type::directory) ps.push_back ( prerequisite (nullopt, dir::static_type, dir_path (e.path ().representation ()), dir_path (), // In the out tree. string (), nullopt, base)); } } catch (const system_error& e) { fail << "unable to iterate over " << base.src_path () << ": " << e; } if (ps.empty ()) return nullptr; l5 ([&]{trace << "implying buildfile for " << k;}); // We behave as if this target was explicitly mentioned in the (implied) // buildfile. Thus not implied. // target& t (targets.insert (dir::static_type, base.out_path (), dir_path (), string (), nullopt, false, trace).first); t.prerequisites (move (ps)); return &t; } }