aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2022-08-17 10:00:55 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2022-08-17 10:00:55 +0200
commit54512574c11b196173d432baa3fc13f04095539a (patch)
tree7c3b6ed4201a2fb4bc322a1bcf9172d006c79102
parent287fd8e3bc60fa69f1ae486efbd635f43ba599ce (diff)
Handle another "in *.export.libs but not in prerequisites" case
Also, enable this check even if proc_lib is not specified unless in the execute phase.
-rw-r--r--libbuild2/cc/common.cxx118
-rw-r--r--libbuild2/cc/common.hxx5
-rw-r--r--libbuild2/cc/common.txx4
3 files changed, 78 insertions, 49 deletions
diff --git a/libbuild2/cc/common.cxx b/libbuild2/cc/common.cxx
index 3c4e38d..ded2902 100644
--- a/libbuild2/cc/common.cxx
+++ b/libbuild2/cc/common.cxx
@@ -552,65 +552,85 @@ namespace build2
if (sysd == nullptr) find_sysd ();
if (!li) find_linfo ();
- pair<const mtime_target&, const target*> p (
- resolve_library (a,
+ const mtime_target* t;
+ const target* g;
+
+ const char* w (nullptr);
+ try
+ {
+ pair<const mtime_target&, const target*> p (
+ resolve_library (a,
bs,
- n,
- (n.pair ? (++i)->dir : dir_path ()),
- *li,
- *sysd, usrd,
- cache));
+ n,
+ (n.pair ? (++i)->dir : dir_path ()),
+ *li,
+ *sysd, usrd,
+ cache));
- const mtime_target& t (p.first);
- const target* g (p.second);
+ t = &p.first;
+ g = p.second;
- // Deduplicate.
- //
- // Note that dedup_start makes sure we only consider our
- // interface dependencies while maintaining the "through"
- // list.
- //
- if (dedup != nullptr)
- {
- if (find (dedup->begin () + dedup_start,
- dedup->end (),
- &t) != dedup->end ())
+ // Deduplicate.
+ //
+ // Note that dedup_start makes sure we only consider our
+ // interface dependencies while maintaining the "through"
+ // list.
+ //
+ if (dedup != nullptr)
{
- ++i;
- continue;
+ if (find (dedup->begin () + dedup_start,
+ dedup->end (),
+ t) != dedup->end ())
+ {
+ ++i;
+ continue;
+ }
+
+ dedup->push_back (t);
}
-
- dedup->push_back (&t);
}
-
- if (proc_lib)
+ catch (const non_existent_library& e)
{
- // This can happen if the target is mentioned in
- // *.export.libs (i.e., it is an interface dependency) but
- // not in the library's prerequisites (i.e., it is not an
- // implementation dependency).
+ // This is another manifestation of the "mentioned in
+ // *.export.libs but not in prerequisites" case (see below).
//
- // Note that we used to just check for path being assigned
- // but on Windows import-installed DLLs may legally have
- // empty paths.
+ t = &e.target;
+ w = "unknown";
+ }
+
+ // This can happen if the target is mentioned in *.export.libs
+ // (i.e., it is an interface dependency) but not in the
+ // library's prerequisites (i.e., it is not an implementation
+ // dependency).
+ //
+ // Note that we used to just check for path being assigned but
+ // on Windows import-installed DLLs may legally have empty
+ // paths.
+ //
+ if (w != nullptr)
+ ; // See above.
+ else if (l.ctx.phase == run_phase::match)
+ {
+ if (!t->matched (a))
+ w = "not matched";
+ }
+ else if (proc_lib)
+ {
+ // Note that this check we only do if there is proc_lib
+ // (since it's valid to process library's options before
+ // updating it).
//
- const char* w (nullptr);
- if (t.ctx.phase == run_phase::match)
- {
- if (!t.matched (a))
- w = "not matched";
- }
- else if (t.mtime () == timestamp_unknown)
+ if (t->mtime () == timestamp_unknown)
w = "out of date";
-
- if (w != nullptr)
- fail << (impl ? "implementation" : "interface")
- << " dependency " << t << " is " << w <<
- info << "mentioned in *.export." << (impl ? "impl_" : "")
- << "libs of target " << l <<
- info << "is it a prerequisite of " << l << "?";
}
+ if (w != nullptr)
+ fail << (impl ? "implementation" : "interface")
+ << " dependency " << *t << " is " << w <<
+ info << "mentioned in *.export." << (impl ? "impl_" : "")
+ << "libs of target " << l <<
+ info << "is it a prerequisite of " << l << "?";
+
// Process it recursively.
//
// @@ Where can we get the link flags? Should we try to find
@@ -619,7 +639,7 @@ namespace build2
//
process_libraries_impl (
a, bs, *li, *sysd,
- g, t, t.is_a<liba> () || t.is_a<libux> (), 0,
+ g, *t, t->is_a<liba> () || t->is_a<libux> (), 0,
proc_impl, proc_lib, proc_opt,
true /* self */, proc_opt_group,
cache, chain, dedup);
@@ -770,6 +790,8 @@ namespace build2
// always a file. The second half of the returned pair is the group, if
// the member was picked.
//
+ // Note: may throw non_existent_library.
+ //
pair<const mtime_target&, const target*> common::
resolve_library (action a,
const scope& s,
diff --git a/libbuild2/cc/common.hxx b/libbuild2/cc/common.hxx
index 9c276f7..c11fa7a 100644
--- a/libbuild2/cc/common.hxx
+++ b/libbuild2/cc/common.hxx
@@ -384,6 +384,11 @@ namespace build2
optional<dir_paths>&,
library_cache* = nullptr) const;
+ struct non_existent_library
+ {
+ const mtime_target& target;
+ };
+
template <typename T>
static ulock
insert_library (context&,
diff --git a/libbuild2/cc/common.txx b/libbuild2/cc/common.txx
index d14f966..f55072c 100644
--- a/libbuild2/cc/common.txx
+++ b/libbuild2/cc/common.txx
@@ -27,7 +27,9 @@ namespace build2
target_decl::implied,
trace));
- assert (!exist || !p.second);
+ if (exist && p.second)
+ throw non_existent_library {p.first.template as<mtime_target> ()};
+
r = &p.first.template as<T> ();
return move (p.second);
}