aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/cc
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2021-05-06 14:19:45 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2021-05-06 14:19:45 +0200
commita9f355062690eba4942f789ca3420c9c319ce901 (patch)
tree48506704d08806e780a8c4c92ee0bd3e905a4ca6 /libbuild2/cc
parent17305d124705d9ab8cd89d1355f4ec6aacbf540a (diff)
See through utility libraries when looking for module interfaces
Diffstat (limited to 'libbuild2/cc')
-rw-r--r--libbuild2/cc/compile-rule.cxx109
-rw-r--r--libbuild2/cc/pkgconfig.cxx100
2 files changed, 117 insertions, 92 deletions
diff --git a/libbuild2/cc/compile-rule.cxx b/libbuild2/cc/compile-rule.cxx
index 40fb5bb..f8529fb 100644
--- a/libbuild2/cc/compile-rule.cxx
+++ b/libbuild2/cc/compile-rule.cxx
@@ -5651,6 +5651,66 @@ namespace build2
return r;
};
+ // Find the module in prerequisite targets of a library (recursively)
+ // seeing through libu*{}. Note: sets the `done` flag. See similar
+ // logic in pkgconfig_save().
+ //
+ auto find = [a, &bs, this,
+ &check_exact, &done] (const file& l,
+ const auto& find) -> void
+ {
+ for (const target* pt: l.prerequisite_targets[a])
+ {
+ if (pt == nullptr)
+ continue;
+
+ // Note that here we (try) to use whatever flavor of bmi*{} is
+ // available.
+ //
+ // @@ MOD: BMI compatibility check.
+ //
+ if (pt->is_a<bmix> ())
+ {
+ const string& n (cast<string> (pt->state[a].vars[c_module_name]));
+
+ if (const target** p = check_exact (n))
+ *p = pt;
+ }
+ else if (pt->is_a (*x_mod))
+ {
+ // This is an installed library with a list of module sources (the
+ // source are specified as prerequisites but the fallback file
+ // rule puts them into prerequisite_targets for us).
+ //
+ // The module names should be specified but if not assume
+ // something else is going on and ignore.
+ //
+ // Note also that besides modules, prerequisite_targets may
+ // contain libraries which are interface dependencies of this
+ // library and which may be called to resolve its module
+ // dependencies.
+ //
+ const string* n (cast_null<string> (pt->vars[c_module_name]));
+
+ if (n == nullptr)
+ continue;
+
+ if (const target** p = check_exact (*n))
+ *p = &this->make_module_sidebuild (a, bs, l, *pt, *n); // GCC 4.9
+ }
+ // Note that in prerequisite targets we will have the libux{}
+ // members, not the group.
+ //
+ else if (const libux* pl = pt->is_a<libux> ())
+ find (*pl, find);
+ else
+ continue;
+
+ if (done)
+ break;
+ }
+ };
+
for (prerequisite_member p: group_prerequisite_members (a, t))
{
if (include (a, t, p) != include_type::normal) // Excluded/ad hoc.
@@ -5671,54 +5731,7 @@ namespace build2
//
if (lt != nullptr)
{
- for (const target* bt: lt->prerequisite_targets[a])
- {
- if (bt == nullptr)
- continue;
-
- // Note that here we (try) to use whatever flavor of bmi*{} is
- // available.
- //
- // @@ MOD: BMI compatibility check.
- // @@ UTL: we need to (recursively) see through libu*{} (and
- // also in pkgconfig_save()).
- //
- if (bt->is_a<bmix> ())
- {
- const string& n (
- cast<string> (bt->state[a].vars[c_module_name]));
-
- if (const target** p = check_exact (n))
- *p = bt;
- }
- else if (bt->is_a (*x_mod))
- {
- // This is an installed library with a list of module sources
- // (the source are specified as prerequisites but the fallback
- // file rule puts them into prerequisite_targets for us).
- //
- // The module names should be specified but if not assume
- // something else is going on and ignore.
- //
- // Note also that besides modules, prerequisite_targets may
- // contain libraries which are interface dependencies of this
- // library and which may be called to resolve its module
- // dependencies.
- //
- const string* n (cast_null<string> (bt->vars[c_module_name]));
-
- if (n == nullptr)
- continue;
-
- if (const target** p = check_exact (*n))
- *p = &make_module_sidebuild (a, bs, *lt, *bt, *n);
- }
- else
- continue;
-
- if (done)
- break;
- }
+ find (*lt, find);
if (done)
break;
diff --git a/libbuild2/cc/pkgconfig.cxx b/libbuild2/cc/pkgconfig.cxx
index a70e9a2..fd88b59 100644
--- a/libbuild2/cc/pkgconfig.cxx
+++ b/libbuild2/cc/pkgconfig.cxx
@@ -1715,66 +1715,78 @@ namespace build2
vector<path> x_hdrs;
vector<path> c_hdrs;
+ // We need to (recursively) see through libu*{}. See similar logic
+ // in search_modules().
+ //
// Note that the prerequisite targets are in the member, not the
// group (for now we don't support different sets of modules/headers
// for static/shared library; see load above for details).
//
- for (const target* pt: l.prerequisite_targets[a])
+ auto collect = [a, this,
+ &mods,
+ &x_hdrs, &c_hdrs] (const target& l,
+ const auto& collect) -> void
{
- if (pt == nullptr)
- continue;
-
- // @@ UTL: we need to (recursively) see through libu*{} (and
- // also in search_modules()).
- //
- if (modules && pt->is_a<bmix> ())
+ for (const target* pt: l.prerequisite_targets[a])
{
- // What we have is a binary module interface. What we need is
- // a module interface source it was built from. We assume it's
- // the first mxx{} target that we see.
- //
- const target* mt (nullptr);
- for (const target* t: pt->prerequisite_targets[a])
+ if (pt == nullptr)
+ continue;
+
+ if (modules && pt->is_a<bmix> ())
{
- if ((mt = t->is_a (*x_mod)))
- break;
- }
+ // What we have is a binary module interface. What we need is
+ // a module interface source it was built from. We assume it's
+ // the first mxx{} target that we see.
+ //
+ const target* mt (nullptr);
+ for (const target* t: pt->prerequisite_targets[a])
+ {
+ if ((mt = t->is_a (*x_mod)))
+ break;
+ }
- // Can/should there be a bmi{} without mxx{}? Can't think of a
- // reason.
- //
- assert (mt != nullptr);
+ // Can/should there be a bmi{} without mxx{}? Can't think of a
+ // reason.
+ //
+ assert (mt != nullptr);
- path p (install::resolve_file (mt->as<file> ()));
+ path p (install::resolve_file (mt->as<file> ()));
- if (p.empty ()) // Not installed.
- continue;
+ if (p.empty ()) // Not installed.
+ continue;
- string pp;
- if (const string* v = cast_null<string> ((*mt)[x_preprocessed]))
- pp = *v;
-
- mods.push_back (
- module {
- cast<string> (pt->state[a].vars[c_module_name]),
- move (p),
- move (pp),
- symexport
- });
- }
- else if (pt->is_a (**x_hdr) || pt->is_a<h> ())
- {
- if (cast_false<bool> ((*pt)[c_importable]))
+ string pp;
+ if (const string* v = cast_null<string> ((*mt)[x_preprocessed]))
+ pp = *v;
+
+ mods.push_back (
+ module {
+ cast<string> (pt->state[a].vars[c_module_name]),
+ move (p),
+ move (pp),
+ symexport});
+ }
+ else if (pt->is_a (**x_hdr) || pt->is_a<h> ())
{
- path p (install::resolve_file (pt->as<file> ()));
+ if (cast_false<bool> ((*pt)[c_importable]))
+ {
+ path p (install::resolve_file (pt->as<file> ()));
- if (p.empty ()) // Not installed.
- continue;
+ if (p.empty ()) // Not installed.
+ continue;
- (pt->is_a<h> () ? c_hdrs : x_hdrs).push_back (move (p));
+ (pt->is_a<h> () ? c_hdrs : x_hdrs).push_back (move (p));
+ }
}
+ // Note that in prerequisite targets we will have the libux{}
+ // members, not the group.
+ //
+ else if (pt->is_a<libux> ())
+ collect (*pt, collect);
}
- }
+ };
+
+ collect (l, collect);
if (size_t n = mods.size ())
{