diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2022-11-30 09:08:53 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2022-11-30 09:08:53 +0200 |
commit | 3bbbe09e8629ab5311a1bcbb9f56aa6a33e36f55 (patch) | |
tree | f3f6ab4fc633d98ae5a215ba4529b07849ba6792 /libbuild2/dist/rule.cxx | |
parent | d593b19735eec451b091fd46e4cb066e3478d6c9 (diff) |
Deal with order dependence in dist rule
Diffstat (limited to 'libbuild2/dist/rule.cxx')
-rw-r--r-- | libbuild2/dist/rule.cxx | 43 |
1 files changed, 38 insertions, 5 deletions
diff --git a/libbuild2/dist/rule.cxx b/libbuild2/dist/rule.cxx index 0c72ff5..7233eba 100644 --- a/libbuild2/dist/rule.cxx +++ b/libbuild2/dist/rule.cxx @@ -72,6 +72,8 @@ namespace build2 // Search for an existing target or existing file in src. // + // Note: see also similar code in match_postponed() below. + // const prerequisite_key& k (p.key ()); pt = k.tk.type->search (t, k); @@ -85,12 +87,13 @@ namespace build2 !p.dir.sub (out_root)) continue; - // @@ TODO: this can actually be order-dependent: for example - // libs{} prerequisite may be unknown because we haven't - // matched the lib{} group yet. + // This can be order-dependent: for example libs{} prerequisite + // may be unknown because we haven't matched the lib{} group + // yet. So we postpone this for later (see match_postponed()). // - fail << "prerequisite " << k << " is not existing source file " - << "nor known output target" << endf; + mlock l (postponed_.mutex); + postponed_.list.push_back (postponed_prerequisite {a, t, p,}); + continue; } search_custom (p, *pt); // Cache. @@ -107,5 +110,35 @@ namespace build2 return noop_recipe; // We will never be executed. } + + void rule:: + match_postponed (action a, const target& t, const prerequisite& p) + { + const prerequisite_key& k (p.key ()); + const target* pt (k.tk.type->search (t, k)); + + if (pt == nullptr) + { + // Note that we do loose the diag frame that we normally get when + // failing during match. So let's mention the target manually. + // + fail << "prerequisite " << k << " is not existing source file nor " + << "known output target" << + info << "while applying rule dist to " << diag_do (a, t); + } + + search_custom (p, *pt); // Cache. + + // It's theoretically possible that the target gets entered but nobody + // else depends on it but us. So we need to make sure it's matched + // (since it, in turns, can pull in other targets). Note that this could + // potentially add new postponed prerequisites to the list. + // + if (!pt->matched (a)) + { + if (pt->dir.sub (t.root_scope ().out_path ())) + match_direct_sync (a, *pt); + } + } } } |