From 6cb9d0e810c3336106b6c1f3c8a80cdec6fbdcf0 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Wed, 22 Nov 2017 11:31:35 +0200 Subject: Fix dist bug where missing source file would be silently ignored --- build2/dist/operation.cxx | 16 +++++++--------- build2/dist/rule.cxx | 39 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 43 insertions(+), 12 deletions(-) (limited to 'build2/dist') diff --git a/build2/dist/operation.cxx b/build2/dist/operation.cxx index f42217e..6692156 100644 --- a/build2/dist/operation.cxx +++ b/build2/dist/operation.cxx @@ -79,8 +79,8 @@ namespace build2 fail << "in-tree distribution of target " << t << info << "distribution requires out-of-tree build"; - // Make sure we have the necessary configuration before - // we get down to business. + // Make sure we have the necessary configuration before we get down to + // business. // auto l (rs->vars["dist.root"]); @@ -155,10 +155,9 @@ namespace build2 } } - // Add buildfiles that are not normally loaded as part of the - // project, for example, the export stub. They will still be - // ignored on the next step if the user explicitly marked them - // nodist. + // Add buildfiles that are not normally loaded as part of the project, + // for example, the export stub. They will still be ignored on the next + // step if the user explicitly marked them dist=false. // auto add_adhoc = [&trace] (const scope& rs, const path& f) { @@ -204,9 +203,8 @@ namespace build2 } } - // Collect the files. We want to take the snapshot of targets - // since updating some of them may result in more targets being - // entered. + // Collect the files. We want to take the snapshot of targets since + // updating some of them may result in more targets being entered. // action_targets files; const variable& dist_var (var_pool["dist"]); diff --git a/build2/dist/rule.cxx b/build2/dist/rule.cxx index ab00d41..b288a66 100644 --- a/build2/dist/rule.cxx +++ b/build2/dist/rule.cxx @@ -36,12 +36,45 @@ namespace build2 if (p.proj ()) continue; - const target& pt (p.search (t)); + // We used to always search and match but that resulted in the + // undesirable behavior in case one of the "source" files is + // missing. In this case we would enter a target as "output", this + // rule would match it, and then dist_execute() would ignore it by + // default. + // + // So now if this is a file target (we still want to always "see + // through" other targets like aliases), we will only match it if (1) + // it exists in src or (2) it exists as a target. It feels like we + // don't need the stronger "... and not implied" condition since if it + // is mentioned as a target, then it is in out (we don't do the same + // target in both src/out). + // + const target* pt (nullptr); + if (p.is_a ()) + { + pt = p.load (); + + if (pt == nullptr) + { + // Search for an existing target or existing file in src. + // + const prerequisite_key& k (p.key ()); + pt = k.tk.type->search (t, k); + + if (pt == nullptr) + fail << "prerequisite " << k << " is not existing source file " + << "nor known output target" << endf; + + search_custom (p.prerequisite, *pt); // Cache. + } + } + else + pt = &p.search (t); // Don't match targets that are outside of our project. // - if (pt.dir.sub (out_root)) - build2::match (a, pt); + if (pt->dir.sub (out_root)) + build2::match (a, *pt); } return noop_recipe; // We will never be executed. -- cgit v1.1