From d2b8ba3e586a17e78b480c129bfcf24d6e05bade Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 21 Jan 2022 09:03:28 +0200 Subject: Add search_new() and search_new_locked() variants of search() --- libbuild2/algorithm.cxx | 22 ++++++++++++++++ libbuild2/algorithm.hxx | 52 +++++++++++++++++++++++++++++++------ libbuild2/algorithm.ixx | 64 ++++++++++++++++++++++++++++++++++++++++++++++ libbuild2/cc/link-rule.cxx | 4 +-- 4 files changed, 132 insertions(+), 10 deletions(-) (limited to 'libbuild2') diff --git a/libbuild2/algorithm.cxx b/libbuild2/algorithm.cxx index 0370626..0c8ac6f 100644 --- a/libbuild2/algorithm.cxx +++ b/libbuild2/algorithm.cxx @@ -88,6 +88,28 @@ namespace build2 } const target& + search_new (context& ctx, const prerequisite_key& pk) + { + assert (ctx.phase == run_phase::load || ctx.phase == run_phase::match); + + if (const target* pt = search_existing_target (ctx, pk)) + return *pt; + + return create_new_target (ctx, pk); + } + + pair + search_new_locked (context& ctx, const prerequisite_key& pk) + { + assert (ctx.phase == run_phase::load || ctx.phase == run_phase::match); + + if (const target* pt = search_existing_target (ctx, pk)) + return {const_cast (*pt), ulock ()}; + + return create_new_target_locked (ctx, pk); + } + + const target& search (const target& t, name n, const scope& s, const target_type* tt) { assert (t.ctx.phase == run_phase::match); diff --git a/libbuild2/algorithm.hxx b/libbuild2/algorithm.hxx index 01b69f2..da64b1a 100644 --- a/libbuild2/algorithm.hxx +++ b/libbuild2/algorithm.hxx @@ -17,7 +17,7 @@ namespace build2 { // The default prerequisite search implementation. It first calls the - // prerequisite-type-specific search function. If that doesn't yeld + // prerequisite-type-specific search function. If that doesn't yield // anything, it creates a new target. // LIBBUILD2_SYMEXPORT const target& @@ -45,20 +45,32 @@ namespace build2 LIBBUILD2_SYMEXPORT pair search_locked (const target&, const prerequisite_key&); - // Note that unlike the above version, this one can be called during the - // load and execute phases. + // As above but this one can be called during the load and execute phases. // LIBBUILD2_SYMEXPORT const target* search_existing (context&, const prerequisite_key&); + // First search for an existing target and if that doesn't yield anything, + // creates a new target, bypassing any prerequisite-type-specific search. + // Can be called during the load and match phases but only on project- + // unqualified prerequisites. This version is suitable for cases where you + // know the target is in out and cannot be possibly found in src. + // + LIBBUILD2_SYMEXPORT const target& + search_new (context&, const prerequisite_key&); + + // As above but return the lock if the target was newly created. + // + LIBBUILD2_SYMEXPORT pair + search_new_locked (context&, const prerequisite_key&); + // Uniform search interface for prerequisite/prerequisite_member. // inline const target& search (const target& t, const prerequisite_member& p) {return p.search (t);} - // As above but override the target type. Useful for searching for - // target group members where we need to search for a different - // target type. + // As above but override the target type. Useful for searching for target + // group members where we need to search for a different target type. // const target& search (const target&, const target_type&, const prerequisite_key&); @@ -66,6 +78,12 @@ namespace build2 pair search_locked (const target&, const target_type&, const prerequisite_key&); + const target& + search_new (context&, const target_type&, const prerequisite_key&); + + pair + search_new_locked (context&, const target_type&, const prerequisite_key&); + // As above but specify the prerequisite to search as individual key // components. Scope can be NULL if the directory is absolute. // @@ -85,8 +103,8 @@ namespace build2 const dir_path& dir, const dir_path& out, const string& name, - const string* ext = nullptr, // NULL means unspecified. - const scope* = nullptr); // NULL means dir is absolute. + const string* ext = nullptr, + const scope* = nullptr); const target* search_existing (context&, @@ -98,6 +116,24 @@ namespace build2 const scope* = nullptr, const optional& proj = nullopt); + const target& + search_new (context&, + const target_type&, + const dir_path& dir, + const dir_path& out, + const string& name, + const string* ext = nullptr, + const scope* = nullptr); + + pair + search_new_locked (context&, + const target_type&, + const dir_path& dir, + const dir_path& out, + const string& name, + const string* ext = nullptr, + const scope* = nullptr); + // As above but specify the target type as template argument. // template diff --git a/libbuild2/algorithm.ixx b/libbuild2/algorithm.ixx index d64747d..264a162 100644 --- a/libbuild2/algorithm.ixx +++ b/libbuild2/algorithm.ixx @@ -46,6 +46,28 @@ namespace build2 } inline const target& + search_new (context& ctx, + const target_type& tt, + const prerequisite_key& k) + { + return search_new ( + ctx, + prerequisite_key { + k.proj, {&tt, k.tk.dir, k.tk.out, k.tk.name, k.tk.ext}, k.scope}); + } + + inline pair + search_new_locked (context& ctx, + const target_type& tt, + const prerequisite_key& k) + { + return search_new_locked ( + ctx, + prerequisite_key { + k.proj, {&tt, k.tk.dir, k.tk.out, k.tk.name, k.tk.ext}, k.scope}); + } + + inline const target& search (const target& t, const target_type& type, const dir_path& dir, @@ -110,6 +132,48 @@ namespace build2 scope}); } + inline const target& + search_new (context& ctx, + const target_type& type, + const dir_path& dir, + const dir_path& out, + const string& name, + const string* ext, + const scope* scope) + { + return search_new ( + ctx, + prerequisite_key { + nullopt, + { + &type, + &dir, &out, &name, + ext != nullptr ? optional (*ext) : nullopt + }, + scope}); + } + + inline pair + search_new_locked (context& ctx, + const target_type& type, + const dir_path& dir, + const dir_path& out, + const string& name, + const string* ext, + const scope* scope) + { + return search_new_locked ( + ctx, + prerequisite_key { + nullopt, + { + &type, + &dir, &out, &name, + ext != nullptr ? optional (*ext) : nullopt + }, + scope}); + } + template inline const T& search (const target& t, diff --git a/libbuild2/cc/link-rule.cxx b/libbuild2/cc/link-rule.cxx index 79de01c..551b243 100644 --- a/libbuild2/cc/link-rule.cxx +++ b/libbuild2/cc/link-rule.cxx @@ -976,8 +976,8 @@ namespace build2 // be the group -- we will pick a member in part 2 below. // pair r ( - search_locked ( - t, rtt, d, dir_path (), *cp.tk.name, nullptr, cp.scope)); + search_new_locked ( + ctx, rtt, d, dir_path (), *cp.tk.name, nullptr, cp.scope)); // If we shouldn't clean obj{}, then it is fair to assume we // shouldn't clean the source either (generated source will be in -- cgit v1.1