From c865883666028da1982b082a0754cc4a261afd27 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 8 Jul 2016 17:07:27 +0200 Subject: Add dependency on fsdir{} in alias rules This makes sure that a directory with only dir{} target gets cleaned up. --- build2/algorithm | 16 +++++++++------- build2/algorithm.cxx | 30 ++++++++++++++++-------------- build2/cli/rule.cxx | 2 +- build2/cxx/compile.cxx | 2 +- build2/cxx/link.cxx | 2 +- build2/rule.cxx | 12 +++++++++--- 6 files changed, 37 insertions(+), 27 deletions(-) (limited to 'build2') diff --git a/build2/algorithm b/build2/algorithm index e57b94d..509e478 100644 --- a/build2/algorithm +++ b/build2/algorithm @@ -36,8 +36,8 @@ namespace build2 target& search (const target_type&, const prerequisite_key&); - // As above but specify the prerequisite to search as individual - // key components. + // As above but specify the prerequisite to search as individual key + // components. Scope can be NULL if the directory is absolute. // target& search (const target_type& type, @@ -130,13 +130,15 @@ namespace build2 group_view resolve_group_members (action, target&); - // Inject dependency on the parent directory's fsdir{}, unless it is outside - // of any project (say, for example, an installation directory). Return the - // injected target or NULL. Normally this function is called from the rule's - // apply() function. + // Inject dependency on the target's directory fsdir{}, unless it is in the + // src tree, root of the project, or is outside of any project (say, for + // example, an installation directory). If the parent argument is true, then + // inject the parent directory of a target that is itself a directory (name + // is empty). Return the injected target or NULL. Normally this function is + // called from the rule's apply() function. // fsdir* - inject_parent_fsdir (action, target&); + inject_fsdir (action, target&, bool parent = true); // Execute the action on target, assuming a rule has been matched // and the recipe for this action has been set. This is the default diff --git a/build2/algorithm.cxx b/build2/algorithm.cxx index 51d2725..59a7800 100644 --- a/build2/algorithm.cxx +++ b/build2/algorithm.cxx @@ -305,31 +305,33 @@ namespace build2 } fsdir* - inject_parent_fsdir (action a, target& t) + inject_fsdir (action a, target& t, bool parent) { - tracer trace ("inject_parent_fsdir"); + tracer trace ("inject_fsdir"); - scope& s (t.base_scope ()); - scope* rs (s.root_scope ()); + scope& bs (t.base_scope ()); + scope* rs (bs.root_scope ()); - if (rs == nullptr) // Could be outside any project. + // Handle the outside of any project and at root scope cases. + // + if (rs == nullptr || &bs == rs) return nullptr; - const dir_path& out_root (rs->out_path ()); - - // If t is a directory (name is empty), say foo/bar/, then - // t is bar and its parent directory is foo/. + // If t is a directory (name is empty), say foo/bar/, then t is bar and + // its parent directory is foo/. // - const dir_path& d (t.name.empty () ? t.dir.directory () : t.dir); + const dir_path& d (parent && t.name.empty () ? t.dir.directory () : t.dir); - if (!d.sub (out_root)) + // Handle the src = out and (again) root scope cases. + // + if (d.sub (rs->src_path ()) || d == rs->out_path ()) return nullptr; - l6 ([&]{trace << "for " << t;}); + l6 ([&]{trace << d << " for " << t;}); - // Target in the out tree, so out directory is empty. + // Target is in the out tree, so out directory is empty. // - fsdir* r (&search (d, dir_path (), string (), nullptr, &s)); + fsdir* r (&search (d, dir_path (), string (), nullptr, nullptr)); match (a, *r); t.prerequisite_targets.emplace_back (r); return r; diff --git a/build2/cli/rule.cxx b/build2/cli/rule.cxx index 139abc6..26c17cd 100644 --- a/build2/cli/rule.cxx +++ b/build2/cli/rule.cxx @@ -184,7 +184,7 @@ namespace build2 // Inject dependency on the output directory. // - inject_parent_fsdir (a, t); + inject_fsdir (a, t); // Search and match prerequisite members. // diff --git a/build2/cxx/compile.cxx b/build2/cxx/compile.cxx index e0fabb4..25416e8 100644 --- a/build2/cxx/compile.cxx +++ b/build2/cxx/compile.cxx @@ -82,7 +82,7 @@ namespace build2 // Inject dependency on the output directory. // - fsdir* dir (inject_parent_fsdir (a, t)); + fsdir* dir (inject_fsdir (a, t)); // Search and match all the existing prerequisites. The injection // code (below) takes care of the ones it is adding. diff --git a/build2/cxx/link.cxx b/build2/cxx/link.cxx index 1818be6..82d98a1 100644 --- a/build2/cxx/link.cxx +++ b/build2/cxx/link.cxx @@ -694,7 +694,7 @@ namespace build2 // Inject dependency on the output directory. // - inject_parent_fsdir (a, t); + inject_fsdir (a, t); optional lib_paths; // Extract lazily. diff --git a/build2/rule.cxx b/build2/rule.cxx index b010ae2..cbb7d08 100644 --- a/build2/rule.cxx +++ b/build2/rule.cxx @@ -144,6 +144,11 @@ namespace build2 recipe alias_rule:: apply (action a, target& t, const match_result&) const { + // Inject dependency on our directory (note: not parent) so that it is + // automatically created on update and removed on clean. + // + inject_fsdir (a, t, false); + search_and_match_prerequisites (a, t); return default_recipe; } @@ -161,11 +166,12 @@ namespace build2 recipe fsdir_rule:: apply (action a, target& t, const match_result&) const { - // Inject dependency on the parent directory. Note that we - // don't do it for clean since we shouldn't be removing it. + // Inject dependency on the parent directory. Note that we don't do it for + // clean since we shouldn't (and can't possibly, since it's our parent) be + // removing it. // if (a.operation () != clean_id) - inject_parent_fsdir (a, t); + inject_fsdir (a, t); search_and_match_prerequisites (a, t); -- cgit v1.1