aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/cc/common.cxx
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 /libbuild2/cc/common.cxx
parent76a4655da2bf544acc65a9cd000c8889cbe763b0 (diff)
Generalize process_libraries() to allow no picking installed library member
Diffstat (limited to 'libbuild2/cc/common.cxx')
-rw-r--r--libbuild2/cc/common.cxx101
1 files changed, 64 insertions, 37 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.
//