aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2021-02-11 09:08:55 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2021-02-11 09:08:55 +0200
commit635f75c7b3fbb6053059827c73a4df52733850e0 (patch)
tree3e1734b7edfd3c370aead2002d1bed416f2a551b
parent76a4655da2bf544acc65a9cd000c8889cbe763b0 (diff)
Generalize process_libraries() to allow no picking installed library member
-rw-r--r--libbuild2/cc/common.cxx101
-rw-r--r--libbuild2/cc/common.hxx16
-rw-r--r--libbuild2/cc/compile-rule.cxx25
-rw-r--r--libbuild2/cc/link-rule.cxx24
-rw-r--r--libbuild2/cc/pkgconfig.cxx10
-rw-r--r--libbuild2/cc/windows-rpath.cxx12
6 files changed, 107 insertions, 81 deletions
diff --git a/libbuild2/cc/common.cxx b/libbuild2/cc/common.cxx
index d11b216..f307b77 100644
--- a/libbuild2/cc/common.cxx
+++ b/libbuild2/cc/common.cxx
@@ -46,31 +46,42 @@ namespace build2
// The first argument to proc_lib is a pointer to the last element of an
// array that contains the current library dependency chain all the way to
// the library passed to process_libraries(). The first element of this
- // array is NULL.
+ // array is NULL. If this argument is NULL, then this is a library without
+ // a target (e.g., -lpthread) and its name is in the second argument.
+ //
+ // If proc_impl always returns false (that is, we are only interested in
+ // interfaces), then top_li can be absent. This makes process_libraries()
+ // not to pick the liba/libs{} member for installed libraries instead
+ // passing the lib{} group itself. This can be used to match the semantics
+ // of file_rule which, when matching prerequisites, does not pick the
+ // liba/libs{} member (naturally) but just matches the lib{} group.
+ //
+ // Note that if top_li is present, then the target passed to proc_impl,
+ // proc_lib, and proc_opt is always a file.
//
void common::
process_libraries (
action a,
const scope& top_bs,
- linfo top_li,
+ optional<linfo> top_li,
const dir_paths& top_sysd,
- const file& l,
+ const mtime_target& l, // liba/libs{} or lib{}
bool la,
lflags lf,
- const function<bool (const file&,
+ const function<bool (const target&,
bool la)>& proc_impl, // Implementation?
- const function<void (const file* const*, // Can be NULL.
+ const function<void (const target* const*, // Can be NULL.
const string& path, // Library path.
lflags, // Link flags.
bool sys)>& proc_lib, // True if system library.
- const function<void (const file&,
+ const function<void (const target&,
const string& type, // cc.type
bool com, // cc. or x.
bool exp)>& proc_opt, // *.export.
bool self /*= false*/, // Call proc_lib on l?
- small_vector<const file*, 16>* chain) const
+ small_vector<const target*, 16>* chain) const
{
- small_vector<const file*, 16> chain_storage;
+ small_vector<const target*, 16> chain_storage;
if (chain == nullptr)
{
chain = &chain_storage;
@@ -193,7 +204,8 @@ namespace build2
// stub the path to the DLL may not be known and so the path will be
// empty (but proc_lib() will use the import stub).
//
- const path& p (l.path ());
+ const file* f;
+ const path& p ((f = l.is_a<file> ()) ? f->path () : empty_path);
bool s (t != nullptr // If cc library (matched or imported).
? cast_false<bool> (l.vars[c_system])
@@ -203,7 +215,7 @@ namespace build2
}
const scope& bs (t == nullptr || cc ? top_bs : l.base_scope ());
- optional<linfo> li; // Calculate lazily.
+ optional<optional<linfo>> li; // Calculate lazily.
const dir_paths* sysd (nullptr); // Resolve lazily.
// Find system search directories corresponding to this library, i.e.,
@@ -225,7 +237,7 @@ namespace build2
{
li = (t == nullptr || cc)
? top_li
- : link_info (bs, link_type (l).type);
+ : optional<linfo> (link_info (bs, link_type (l).type));
};
// Only go into prerequisites (implementation) if instructed and we are
@@ -234,6 +246,8 @@ namespace build2
//
if (impl && !c_e_libs.defined () && !x_e_libs.defined ())
{
+ assert (top_li); // Must pick a member if implementation (see above).
+
for (const prerequisite_target& pt: l.prerequisite_targets[a])
{
// Note: adhoc prerequisites are not part of the library metadata
@@ -303,7 +317,7 @@ namespace build2
{
// This is something like -lpthread or shell32.lib so should be
// a valid path. But it can also be an absolute library path
- // (e.g., something that may come from our .static/shared.pc
+ // (e.g., something that may come from our .{static/shared}.pc
// files).
//
if (proc_lib)
@@ -316,7 +330,7 @@ namespace build2
if (sysd == nullptr) find_sysd ();
if (!li) find_linfo ();
- const file& t (
+ const mtime_target& t (
resolve_library (a,
bs,
n,
@@ -449,12 +463,16 @@ namespace build2
// will select exactly the same target as the library's matched rule and
// that's the only way to guarantee it will be up-to-date.
//
- const file& common::
+ // If li is absent, then don't pick the liba/libs{} member, returning the
+ // lib{} target itself. If li is present, then the returned target is
+ // always a file.
+ //
+ const mtime_target& common::
resolve_library (action a,
const scope& s,
const name& cn,
const dir_path& out,
- linfo li,
+ optional<linfo> li,
const dir_paths& sysd,
optional<dir_paths>& usrd) const
{
@@ -491,12 +509,16 @@ namespace build2
fail << "unable to find library " << pk;
}
- // If this is lib{}/libu*{}, pick appropriate member.
+ // If this is lib{}/libu*{}, pick appropriate member unless we were
+ // instructed not to.
//
- if (const libx* l = xt->is_a<libx> ())
- xt = link_member (*l, a, li); // Pick lib*{e,a,s}{}.
+ if (li)
+ {
+ if (const libx* l = xt->is_a<libx> ())
+ xt = link_member (*l, a, *li); // Pick lib*{e,a,s}{}.
+ }
- return xt->as<file> ();
+ return xt->as<mtime_target> ();
}
// Note that pk's scope should not be NULL (even if dir is absolute).
@@ -868,6 +890,24 @@ namespace build2
return l;
};
+ // Mark as a "cc" library (unless already marked) and set the system
+ // flag.
+ //
+ auto mark_cc = [sys, this] (target& t) -> bool
+ {
+ auto p (t.vars.insert (c_type));
+
+ if (p.second)
+ {
+ p.first = string ("cc");
+
+ if (sys)
+ t.vars.assign (c_system) = true;
+ }
+
+ return p.second;
+ };
+
target_lock ll (lock (lt));
// Set lib{} group members to indicate what's available. Note that we
@@ -879,6 +919,11 @@ namespace build2
{
if (s != nullptr) {lt->s = s; mt = s->mtime ();}
if (a != nullptr) {lt->a = a; mt = a->mtime ();}
+
+ // Mark the group since sometimes we use it itself instead of one of
+ // the liba/libs{} members (see process_libraries() for details).
+ //
+ mark_cc (*lt);
}
target_lock al (lock (a));
@@ -890,24 +935,6 @@ namespace build2
if (a != nullptr) a->group = lt;
if (s != nullptr) s->group = lt;
- // Mark as a "cc" library (unless already marked) and set the system
- // flag.
- //
- auto mark_cc = [sys, this] (target& t) -> bool
- {
- auto p (t.vars.insert (c_type));
-
- if (p.second)
- {
- p.first = string ("cc");
-
- if (sys)
- t.vars.assign (c_system) = true;
- }
-
- return p.second;
- };
-
// If the library already has cc.type, then assume it was either
// already imported or was matched by a rule.
//
diff --git a/libbuild2/cc/common.hxx b/libbuild2/cc/common.hxx
index 856c0ce..612d081 100644
--- a/libbuild2/cc/common.hxx
+++ b/libbuild2/cc/common.hxx
@@ -272,16 +272,16 @@ namespace build2
process_libraries (
action,
const scope&,
- linfo,
+ optional<linfo>,
const dir_paths&,
- const file&,
+ const mtime_target&,
bool,
lflags,
- const function<bool (const file&, bool)>&,
- const function<void (const file* const*, const string&, lflags, bool)>&,
- const function<void (const file&, const string&, bool, bool)>&,
+ const function<bool (const target&, bool)>&,
+ const function<void (const target* const*, const string&, lflags, bool)>&,
+ const function<void (const target&, const string&, bool, bool)>&,
bool = false,
- small_vector<const file*, 16>* = nullptr) const;
+ small_vector<const target*, 16>* = nullptr) const;
const target*
search_library (action a,
@@ -308,12 +308,12 @@ namespace build2
}
public:
- const file&
+ const mtime_target&
resolve_library (action,
const scope&,
const name&,
const dir_path&,
- linfo,
+ optional<linfo>,
const dir_paths&,
optional<dir_paths>&) const;
diff --git a/libbuild2/cc/compile-rule.cxx b/libbuild2/cc/compile-rule.cxx
index 2c53a62..bd4b481 100644
--- a/libbuild2/cc/compile-rule.cxx
+++ b/libbuild2/cc/compile-rule.cxx
@@ -413,11 +413,13 @@ namespace build2
// See through utility libraries.
//
- auto imp = [] (const file& l, bool la) {return la && l.is_a<libux> ();};
+ auto imp = [] (const target& l, bool la) {return la && l.is_a<libux> ();};
- auto opt = [&d, this] (const file& l,
+ auto opt = [&d, this] (const target& lt,
const string& t, bool com, bool exp)
{
+ const file& l (lt.as<file> ());
+
// Note that in our model *.export.poptions are always "interface",
// even if set on liba{}/libs{}, unlike loptions.
//
@@ -504,10 +506,10 @@ namespace build2
target& t,
linfo li) const
{
- auto imp = [] (const file& l, bool la) {return la && l.is_a<libux> ();};
+ auto imp = [] (const target& l, bool la) {return la && l.is_a<libux> ();};
auto opt = [&m, this] (
- const file& l, const string& t, bool com, bool exp)
+ const target& l, const string& t, bool com, bool exp)
{
if (!exp)
return;
@@ -524,8 +526,8 @@ namespace build2
// The same logic as in append_library_options().
//
- const function<bool (const file&, bool)> impf (imp);
- const function<void (const file&, const string&, bool, bool)> optf (opt);
+ const function<bool (const target&, bool)> impf (imp);
+ const function<void (const target&, const string&, bool, bool)> optf (opt);
for (prerequisite_member p: group_prerequisite_members (a, t))
{
@@ -6097,10 +6099,7 @@ namespace build2
// Note that any such library would necessarily be an interface
// dependency so we never need to go into implementations.
//
- auto imp = [] (const file&, bool)
- {
- return false;
- };
+ auto imp = [] (const target&, bool) { return false; };
// The same logic as in append_libraries().
//
@@ -6111,7 +6110,7 @@ namespace build2
const file*& lt;
} d {a, ht, lt};
- auto lib = [&d] (const file* const* lc,
+ auto lib = [&d] (const target* const* lc,
const string&,
lflags,
bool)
@@ -6121,7 +6120,7 @@ namespace build2
if (d.lt != nullptr)
return;
- const file* l (lc != nullptr ? *lc : nullptr);
+ const file* l (lc != nullptr ? &(*lc)->as<file> () : nullptr);
if (l == nullptr)
return;
@@ -6175,7 +6174,7 @@ namespace build2
process_libraries (
a, bs, li, sys_lib_dirs,
*f, la, 0, // lflags unused.
- imp, lib, {},
+ imp, lib, nullptr,
true);
}
}
diff --git a/libbuild2/cc/link-rule.cxx b/libbuild2/cc/link-rule.cxx
index 8b81536..2b3f22a 100644
--- a/libbuild2/cc/link-rule.cxx
+++ b/libbuild2/cc/link-rule.cxx
@@ -1553,19 +1553,19 @@ namespace build2
compile_target_types tts;
} d {ls, args, l, a, li, rel, compile_types (li.type)};
- auto imp = [] (const file&, bool la)
+ auto imp = [] (const target&, bool la)
{
return la;
};
- auto lib = [&d, this] (const file* const* lc,
+ auto lib = [&d, this] (const target* const* lc,
const string& p,
lflags f,
bool)
{
// Note: see also make_header_sidebuild().
- const file* l (lc != nullptr ? *lc : nullptr);
+ const file* l (lc != nullptr ? &(*lc)->as<file> () : nullptr);
// Suppress duplicates.
//
@@ -1745,11 +1745,13 @@ namespace build2
al.end = d.args.size (); // Close.
};
- auto opt = [&d, this] (const file& l,
+ auto opt = [&d, this] (const target& lt,
const string& t,
bool com,
bool exp)
{
+ const file& l (lt.as<file> ());
+
// Don't try to pass any loptions when linking a static library.
//
// Note also that we used to pass non-export loptions but that didn't
@@ -1806,17 +1808,17 @@ namespace build2
linfo li;
} d {cs, bs.root_scope ()->out_path (), update, mt, li};
- auto imp = [] (const file&, bool la)
+ auto imp = [] (const target&, bool la)
{
return la;
};
- auto lib = [&d, this] (const file* const* lc,
+ auto lib = [&d, this] (const target* const* lc,
const string& p,
lflags f,
bool)
{
- const file* l (lc != nullptr ? *lc : nullptr);
+ const file* l (lc != nullptr ? &(*lc)->as<file> () : nullptr);
if (l == nullptr)
{
@@ -1868,7 +1870,7 @@ namespace build2
}
};
- auto opt = [&d, this] (const file& l,
+ auto opt = [&d, this] (const target& l,
const string& t,
bool com,
bool exp)
@@ -1908,7 +1910,7 @@ namespace build2
return;
}
- auto imp = [link] (const file& l, bool la)
+ auto imp = [link] (const target& l, bool la)
{
// If we are not rpath-link'ing, then we only need to rpath interface
// libraries (they will include rpath's for their implementations)
@@ -1937,12 +1939,12 @@ namespace build2
bool link;
} d {ls, args, link};
- auto lib = [&d, this] (const file* const* lc,
+ auto lib = [&d, this] (const target* const* lc,
const string& f,
lflags,
bool sys)
{
- const file* l (lc != nullptr ? *lc : nullptr);
+ const file* l (lc != nullptr ? &(*lc)->as<file> () : nullptr);
// We don't rpath system libraries. Why, you may ask? There are many
// good reasons and I have them written on a napkin somewhere...
diff --git a/libbuild2/cc/pkgconfig.cxx b/libbuild2/cc/pkgconfig.cxx
index 48219f2..d44b0ec 100644
--- a/libbuild2/cc/pkgconfig.cxx
+++ b/libbuild2/cc/pkgconfig.cxx
@@ -1633,15 +1633,15 @@ namespace build2
// pretty similar to link_rule::append_libraries()).
//
bool priv (false);
- auto imp = [&priv] (const file&, bool la) {return priv && la;};
+ auto imp = [&priv] (const target&, bool la) {return priv && la;};
auto lib = [&save_library_target,
- &save_library_name] (const file* const* c,
+ &save_library_name] (const target* const* lc,
const string& p,
lflags,
bool)
{
- const file* l (c != nullptr ? *c : nullptr);
+ const file* l (lc != nullptr ? &(*lc)->as<file> () : nullptr);
if (l != nullptr)
{
@@ -1652,9 +1652,7 @@ namespace build2
save_library_name (p); // Something "system'y", save as is.
};
- auto opt = [] (const file&,
- const string&,
- bool, bool)
+ auto opt = [] (const target&, const string&, bool, bool)
{
//@@ TODO: should we filter -L similar to -I?
//@@ TODO: how will the Libs/Libs.private work?
diff --git a/libbuild2/cc/windows-rpath.cxx b/libbuild2/cc/windows-rpath.cxx
index eddb9c4..70eef73 100644
--- a/libbuild2/cc/windows-rpath.cxx
+++ b/libbuild2/cc/windows-rpath.cxx
@@ -56,14 +56,14 @@ namespace build2
// We need to collect all the DLLs, so go into implementation of both
// shared and static (in case they depend on shared).
//
- auto imp = [] (const file&, bool) {return true;};
+ auto imp = [] (const target&, bool) {return true;};
- auto lib = [&r] (const file* const* lc,
+ auto lib = [&r] (const target* const* lc,
const string& f,
lflags,
bool sys)
{
- const file* l (lc != nullptr ? *lc : nullptr);
+ const file* l (lc != nullptr ? &(*lc)->as<file> () : nullptr);
// We don't rpath system libraries.
//
@@ -137,14 +137,14 @@ namespace build2
{
windows_dlls r;
- auto imp = [] (const file&, bool) {return true;};
+ auto imp = [] (const target&, bool) {return true;};
- auto lib = [&r, &bs] (const file* const* lc,
+ auto lib = [&r, &bs] (const target* const* lc,
const string& f,
lflags,
bool sys)
{
- const file* l (lc != nullptr ? *lc : nullptr);
+ const file* l (lc != nullptr ? &(*lc)->as<file> () : nullptr);
if (sys)
return;