aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2016-08-28 06:31:47 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2016-08-28 06:31:47 +0200
commitd3c5559f9d0969ec91ed0113223b2ec18e53c9ff (patch)
treec03212c0b567767446798d0df9cb59d683d6d0b8
parent457f83ee501ba8f9a6a576de741e43ff9dfef039 (diff)
Extract pkg-config information for both static/shared at once
We also no longer pick shared/static file rather entering them as "our" lib{} target. This way we use the link order of the importer "transitively".
-rw-r--r--build2/cc/compile8
-rw-r--r--build2/cc/compile.cxx43
-rw-r--r--build2/cc/link25
-rw-r--r--build2/cc/link.cxx219
-rw-r--r--build2/cc/pkgconfig.cxx82
5 files changed, 203 insertions, 174 deletions
diff --git a/build2/cc/compile b/build2/cc/compile
index 5bff6b1..6c00b73 100644
--- a/build2/cc/compile
+++ b/build2/cc/compile
@@ -42,10 +42,10 @@ namespace build2
private:
void
- append_lib_options (cstrings&, target&) const;
+ append_lib_options (cstrings&, target&, scope&, lorder) const;
void
- hash_lib_options (sha256&, target&) const;
+ hash_lib_options (sha256&, target&, scope&, lorder) const;
// Mapping of include prefixes (e.g., foo in <foo/bar>) for auto-
// generated headers to directories where they will be generated.
@@ -63,10 +63,10 @@ namespace build2
append_prefixes (prefix_map&, target&, const variable&) const;
void
- append_lib_prefixes (prefix_map&, target&) const;
+ append_lib_prefixes (prefix_map&, target&, scope&, lorder) const;
prefix_map
- build_prefix_map (target&, lorder) const;
+ build_prefix_map (target&, scope&, lorder) const;
// Reverse-lookup target type from extension.
//
diff --git a/build2/cc/compile.cxx b/build2/cc/compile.cxx
index 10171ed..c1f87ba 100644
--- a/build2/cc/compile.cxx
+++ b/build2/cc/compile.cxx
@@ -66,7 +66,7 @@ namespace build2
// (first one is cc.export.*) recursively, prerequisite libraries first.
//
void compile::
- append_lib_options (cstrings& args, target& xt) const
+ append_lib_options (cstrings& args, target& xt, scope& bs, lorder lo) const
{
file& l (static_cast<file&> (xt));
@@ -85,12 +85,13 @@ namespace build2
append_options (args, l, var);
};
- link_.process_libraries (
- sys_lib_dirs, l, l.is_a<liba> (), nullptr, nullptr, opt);
+ link_.process_libraries (bs, lo, sys_lib_dirs,
+ l, l.is_a<liba> (),
+ nullptr, nullptr, opt);
}
void compile::
- hash_lib_options (sha256& cs, target& xt) const
+ hash_lib_options (sha256& cs, target& xt, scope& bs, lorder lo) const
{
file& l (static_cast<file&> (xt));
@@ -107,7 +108,7 @@ namespace build2
};
link_.process_libraries (
- sys_lib_dirs, l, l.is_a<liba> (), nullptr, nullptr, opt);
+ bs, lo, sys_lib_dirs, l, l.is_a<liba> (), nullptr, nullptr, opt);
}
recipe compile::
@@ -179,10 +180,6 @@ namespace build2
//
optional<dir_paths> usr_lib_dirs; // Extract lazily.
- lorder lo;
- if (a.operation () == update_id)
- lo = link_order (bs, ct);
-
for (prerequisite_member p: group_prerequisite_members (a, t))
{
// A dependency on a library is there so that we can get its
@@ -202,7 +199,7 @@ namespace build2
//
if (p.proj () == nullptr ||
link_.search_library (
- sys_lib_dirs, usr_lib_dirs, p.prerequisite, lo) == nullptr)
+ sys_lib_dirs, usr_lib_dirs, p.prerequisite) == nullptr)
{
match_only (a, p.search ());
}
@@ -226,6 +223,8 @@ namespace build2
//
if (a == perform_update_id)
{
+ lorder lo (link_order (bs, ct));
+
// The cached prerequisite target should be the same as what is in
// t.prerequisite_targets since we used standard search() and match()
// above.
@@ -278,7 +277,7 @@ namespace build2
else if (!pt->is_a<liba> () && !pt->is_a<libs> ())
continue;
- hash_lib_options (cs, *pt);
+ hash_lib_options (cs, *pt, bs, lo);
}
hash_options (cs, t, c_poptions);
@@ -450,7 +449,8 @@ namespace build2
// recursively, prerequisite libraries first.
//
void compile::
- append_lib_prefixes (prefix_map& m, target& xt) const
+ append_lib_prefixes (
+ prefix_map& m, target& xt, scope& bs, lorder lo) const
{
file& l (static_cast<file&> (xt));
@@ -467,11 +467,11 @@ namespace build2
};
link_.process_libraries (
- sys_lib_dirs, l, l.is_a<liba> (), nullptr, nullptr, opt);
+ bs, lo, sys_lib_dirs, l, l.is_a<liba> (), nullptr, nullptr, opt);
}
auto compile::
- build_prefix_map (target& t, lorder lo) const -> prefix_map
+ build_prefix_map (target& t, scope& bs, lorder lo) const -> prefix_map
{
prefix_map m;
@@ -487,7 +487,7 @@ namespace build2
else if (!pt->is_a<liba> () && !pt->is_a<libs> ())
continue;
- append_lib_prefixes (m, *pt);
+ append_lib_prefixes (m, *pt, bs, lo);
}
// Then process our own.
@@ -689,14 +689,15 @@ namespace build2
info << "while extracting header dependencies from " << src;
}));
- scope& rs (t.root_scope ());
+ scope& bs (t.base_scope ());
+ scope& rs (*bs.root_scope ());
// Initialize lazily, only if required.
//
const process_path* xc (nullptr);
cstrings args;
- auto init_args = [&t, lo, &src, &rs, &xc, &args, this] ()
+ auto init_args = [&t, lo, &src, &rs, &bs, &xc, &args, this] ()
{
xc = &cast<process_path> (rs[x_path]);
args.push_back (xc->recall_string ());
@@ -713,7 +714,7 @@ namespace build2
else if (!pt->is_a<liba> () && !pt->is_a<libs> ())
continue;
- append_lib_options (args, *pt);
+ append_lib_options (args, *pt, bs, lo);
}
append_options (args, t, c_poptions);
@@ -864,7 +865,7 @@ namespace build2
// from the depdb cache or from the compiler run. Return whether the
// extraction process should be restarted.
//
- auto add = [&trace, &update, &pm, a, &t, lo, &dd, this]
+ auto add = [&trace, &update, &pm, a, &t, lo, &dd, &bs, this]
(path f, bool cache) -> bool
{
// Find or maybe insert the target.
@@ -961,7 +962,7 @@ namespace build2
// then we would have failed below.
//
if (pm.empty ())
- pm = build_prefix_map (t, lo);
+ pm = build_prefix_map (t, bs, lo);
// First try the whole file. Then just the directory.
//
@@ -1385,7 +1386,7 @@ namespace build2
else if (!pt->is_a<liba> () && !pt->is_a<libs> ())
continue;
- append_lib_options (args, *pt);
+ append_lib_options (args, *pt, bs, lo);
}
append_options (args, t, c_poptions);
diff --git a/build2/cc/link b/build2/cc/link
index 8c85343..2652285 100644
--- a/build2/cc/link
+++ b/build2/cc/link
@@ -40,7 +40,9 @@ namespace build2
friend class compile;
void
- process_libraries (const dir_paths&,
+ process_libraries (scope&,
+ lorder,
+ const dir_paths&,
file&,
bool,
const function<bool (file&, bool)>&,
@@ -50,13 +52,13 @@ namespace build2
bool,
bool)>&) const;
void
- append_libraries (strings&, file&, bool) const;
+ append_libraries (strings&, file&, bool, scope&, lorder) const;
void
- hash_libraries (sha256&, file&, bool) const;
+ hash_libraries (sha256&, file&, bool, scope&, lorder) const;
void
- rpath_libraries (strings&, file&, bool, bool) const;
+ rpath_libraries (strings&, file&, bool, scope&, lorder, bool) const;
file&
resolve_library (name,
@@ -70,12 +72,13 @@ namespace build2
bool
pkgconfig_extract (scope&,
- file&,
+ bin::lib&,
+ bin::liba*,
+ bin::libs*,
const string*,
const string&,
const dir_path&,
- const dir_paths&,
- lorder) const;
+ const dir_paths&) const;
// Alternative search logic for VC (msvc.cxx).
//
@@ -92,11 +95,10 @@ namespace build2
target*
search_library (const dir_paths& sysd,
optional<dir_paths>& usrd,
- prerequisite& p,
- lorder lo) const
+ prerequisite& p) const
{
if (p.target == nullptr) // First check the cache.
- p.target = search_library (sysd, usrd, p.key (), lo);
+ p.target = search_library (sysd, usrd, p.key ());
return p.target;
}
@@ -104,8 +106,7 @@ namespace build2
target*
search_library (const dir_paths&,
optional<dir_paths>&,
- const prerequisite_key&,
- lorder) const;
+ const prerequisite_key&) const;
// Windows-specific (windows-manifest.cxx).
//
diff --git a/build2/cc/link.cxx b/build2/cc/link.cxx
index 0f7a525..d8ccc0e 100644
--- a/build2/cc/link.cxx
+++ b/build2/cc/link.cxx
@@ -104,8 +104,7 @@ namespace build2
target* link::
search_library (const dir_paths& sysd,
optional<dir_paths>& usrd,
- const prerequisite_key& p,
- lorder lo) const
+ const prerequisite_key& p) const
{
tracer trace (x, "link::search_library");
@@ -417,6 +416,27 @@ namespace build2
}
};
+ // Enter (or find) the lib{} target group. Note that we must be careful
+ // here since its possible we have already imported some of its members.
+ //
+ lib& lt (
+ targets.insert<lib> (
+ *pd, dir_path (), name, l ? p.tk.ext : nullptr, trace));
+
+ // It should automatically link-up to the members we have found.
+ //
+ assert (a == nullptr || lt.a == a);
+ assert (s == nullptr || lt.s == s);
+
+ // Update the bin.lib variable to indicate what's available.
+ //
+ const char* bl (lt.a != nullptr
+ ? (lt.s != nullptr ? "both" : "static")
+ : "shared");
+ lt.assign ("bin.lib") = bl;
+
+ target* r (l ? &lt : (p.is_a<liba> () ? static_cast<target*> (a) : s));
+
// Mark as a "cc" library (unless already marked) and set the system
// flag.
//
@@ -438,46 +458,28 @@ namespace build2
// If the library already has cc.type, then assume it was either already
// imported or was matched by a rule.
//
- if (a != nullptr && mark_cc (*a))
- {
- // Only add the default macro if we could not extract more precise
- // information. The idea is that when we auto-generate .pc files, we
- // will copy those macros (or custom ones) from *.export.poptions.
- //
- if (pkgconfig == nullptr ||
- !pkgconfig_extract (*p.scope, *a, p.proj, name, *pd, sysd, lo))
- add_macro (*a, "STATIC");
- }
+ if (a != nullptr && !mark_cc (*a))
+ a = nullptr;
- if (s != nullptr && mark_cc (*s))
- {
- if (pkgconfig == nullptr ||
- !pkgconfig_extract (*p.scope, *s, p.proj, name, *pd, sysd, lo))
- add_macro (*s, "SHARED");
- }
+ if (s != nullptr && !mark_cc (*s))
+ s = nullptr;
- if (l)
+ if (a != nullptr || s != nullptr)
{
- // Enter the target group.
- //
- lib& l (targets.insert<lib> (*pd, dir_path (), name, p.tk.ext, trace));
-
- // It should automatically link-up to the members we have found.
- //
- assert (l.a == a);
- assert (l.s == s);
-
- // Set the bin.lib variable to indicate what's available.
+ // Try to extract library information from pkg-config. We only add the
+ // default macro if we could not extract more precise information. The
+ // idea is that when we auto-generate .pc files, we will copy those
+ // macros (or custom ones) from *.export.poptions.
//
- const char* bl (a != nullptr
- ? (s != nullptr ? "both" : "static")
- : "shared");
- l.assign ("bin.lib") = bl;
-
- return &l;
+ if (pkgconfig == nullptr ||
+ !pkgconfig_extract (*p.scope, lt, a, s, p.proj, name, *pd, sysd))
+ {
+ if (a != nullptr) add_macro (*a, "STATIC");
+ if (s != nullptr) add_macro (*s, "SHARED");
+ }
}
- else
- return p.is_a<liba> () ? static_cast<target*> (a) : s;
+
+ return r;
}
match_result link::
@@ -578,8 +580,6 @@ namespace build2
if (t.group != nullptr)
t.group->prerequisite_targets.clear (); // lib{}'s
- scope& bs (t.base_scope ());
- lorder lo (link_order (bs, lt));
optional<dir_paths> usr_lib_dirs; // Extract lazily.
for (prerequisite_member p: group_prerequisite_members (a, t))
@@ -591,8 +591,7 @@ namespace build2
// Handle imported libraries.
//
if (p.proj () != nullptr)
- pt = search_library (
- sys_lib_dirs, usr_lib_dirs, p.prerequisite, lo);
+ pt = search_library (sys_lib_dirs, usr_lib_dirs, p.prerequisite);
if (pt == nullptr)
{
@@ -785,8 +784,7 @@ namespace build2
// Handle imported libraries.
//
if (p.proj () != nullptr)
- pt = search_library (
- sys_lib_dirs, usr_lib_dirs, p.prerequisite, lo);
+ pt = search_library (sys_lib_dirs, usr_lib_dirs, p.prerequisite);
// The rest is the same basic logic as in search_and_match().
//
@@ -1011,6 +1009,8 @@ namespace build2
//
void link::
process_libraries (
+ scope& top_bs,
+ lorder top_lo,
const dir_paths& top_sysd,
file& l,
bool la,
@@ -1031,12 +1031,17 @@ namespace build2
// look into prerequisites.
//
const string* t (cast_null<string> (l.vars[c_type]));
+ bool cc, same;
+ auto& vp (var_pool);
lookup c_e_libs;
lookup x_e_libs;
if (t != nullptr)
{
+ cc = *t == "cc";
+ same = !cc && *t == x;
+
// The explicit export override should be set on the liba/libs{}
// target itself. Note also that we only check for *.libs. If one
// doesn't have any libraries but needs to set, say, *.loptions, then
@@ -1048,11 +1053,11 @@ namespace build2
else if (l.group != nullptr) // lib{} group.
c_e_libs = l.group->vars[c_export_libs];
- if (*t != "cc")
+ if (!cc)
{
- const variable& var (*t == x
+ const variable& var (same
? x_export_libs
- : var_pool[*t + ".export.libs"]);
+ : vp[*t + ".export.libs"]);
if (impl)
x_e_libs = l.vars[var]; // Override.
@@ -1064,30 +1069,26 @@ namespace build2
// Find system search directories corresponding to this library, i.e.,
// from its project and for its type (C, C++, etc).
//
- auto find_sysd = [&top_sysd, this] (file& l, const string* t, scope* bs)
- -> const dir_paths&
+ auto find_sysd = [&top_sysd, this] (
+ bool cc, bool same, const string& t, scope& bs) -> const dir_paths&
{
- if (t == nullptr)
- t = cast_null<string> (l.vars[c_type]);
-
- assert (t != nullptr);
+ // Use the search dirs corresponding to this library scope/type.
+ //
+ return cc
+ ? top_sysd // Imported library, use importer's sysd.
+ : cast<dir_paths> (
+ bs.root_scope ()->vars[same
+ ? x_sys_lib_dirs
+ : var_pool[t + ".sys_lib_dirs"]]);
+ };
- if (*t == "cc")
- return top_sysd; // Imported library, use importer's sysd.
- else
- {
- // Use the search dirs corresponding to this library scope/type.
- //
- scope& rs (bs != nullptr ? *bs->root_scope () : l.root_scope ());
- return cast<dir_paths> (
- rs.vars[*t == x
- ? x_sys_lib_dirs
- : var_pool[*t + ".sys_lib_dirs"]]);
- }
+ auto find_lo = [top_lo, this] (file& l, bool cc, scope& bs) -> lorder
+ {
+ return cc ? top_lo : link_order (bs, link_type (l));
};
// Determine if an absolute path is to a system library. Note that
- // we assume both paths are normalized.
+ // we assume both paths to be normalized.
//
auto sys = [] (const dir_paths& sysd, const string& p) -> bool
{
@@ -1108,7 +1109,7 @@ namespace build2
return false;
};
- // Only go into prerequisites (implementation) if instructed and it's
+ // Only go into prerequisites (implementation) if instructed and we are
// not using explicit export. Otherwise, interface dependencies come
// from the lib{}:*.export.libs below.
//
@@ -1128,7 +1129,15 @@ namespace build2
proc_lib (f, p, sys (top_sysd, p));
}
- process_libraries (find_sysd (*f, nullptr, nullptr),
+ const string& t (cast<string> (f->vars[c_type])); // Must be there.
+ bool cc (t == "cc");
+ bool same (!cc && t == x);
+
+ scope& bs (cc ? top_bs : f->base_scope ());
+
+ process_libraries (bs,
+ find_lo (*f, cc, bs),
+ find_sysd (cc, same, t, bs),
*f, a,
proc_impl, proc_lib, proc_opt);
}
@@ -1138,32 +1147,28 @@ namespace build2
// Process libraries (recursively) from *.export.libs (of type names)
// handling import, etc.
//
-
// If it is not a C-common library, then it probably doesn't have any of
// the *.libs and we are done.
//
if (t == nullptr)
return;
- scope* bs (nullptr); // Resolve lazily.
- optional<lorder> lo; // Calculate lazily.
- const dir_paths* sysd (nullptr); // Resolve lazily.
- optional<dir_paths> usrd; // Extract lazily.
+ scope& bs (cc ? top_bs : l.base_scope ());
+ optional<lorder> lo; // Calculate lazily.
+ const dir_paths* sysd (nullptr); // Resolve lazily.
+ optional<dir_paths> usrd; // Extract lazily.
// Determine if a "simple path" is a system library.
//
- auto sys_simple = [&l, t, &bs, &sysd, &sys, &find_sysd] (const string& p)
- -> bool
+ auto sys_simple = [cc, same, t, &bs, &sysd, &sys, &find_sysd] (
+ const string& p) -> bool
{
bool s (!path::traits::absolute (p));
if (!s)
{
- if (bs == nullptr)
- bs = &l.base_scope ();
-
if (sysd == nullptr)
- sysd = &find_sysd (l, t, bs);
+ sysd = &find_sysd (cc, same, *t, bs);
s = sys (*sysd, p);
}
@@ -1171,13 +1176,12 @@ namespace build2
return s;
};
- auto proc_int = [&l, la, t,
+ auto proc_int = [&l, cc, same, t,
&proc_impl, &proc_lib, &proc_opt,
- &sysd, &usrd, &sys_simple, &sys, &find_sysd,
+ &sysd, &usrd,
+ &find_sysd, &find_lo, &sys, &sys_simple,
&bs, &lo, this] (const lookup& lu)
{
- assert (t != nullptr);
-
const names* ns (cast_null<names> (lu));
if (ns == nullptr || ns->empty ())
return;
@@ -1198,16 +1202,13 @@ namespace build2
{
// This is a potentially project-qualified target.
//
- if (bs == nullptr)
- bs = &l.base_scope ();
-
if (sysd == nullptr)
- sysd = &find_sysd (l, t, bs);
+ sysd = &find_sysd (cc, same, *t, bs);
if (!lo)
- lo = link_order (*bs, la ? otype::a : otype::s);
+ lo = find_lo (l, cc, bs);
- file& t (resolve_library (n, *bs, *lo, *sysd, usrd));
+ file& t (resolve_library (n, bs, *lo, *sysd, usrd));
if (proc_lib)
{
@@ -1232,8 +1233,9 @@ namespace build2
// Process it recursively.
//
- process_libraries (
- *sysd, t, t.is_a<liba> (), proc_impl, proc_lib, proc_opt);
+ process_libraries (bs, *lo, *sysd,
+ t, t.is_a<liba> (),
+ proc_impl, proc_lib, proc_opt);
}
}
};
@@ -1258,16 +1260,13 @@ namespace build2
// If all we know is it's a C-common library, then in both cases we only
// look for cc.export.libs.
//
- if (*t == "cc")
+ if (cc)
{
if (proc_opt) proc_opt (l, *t, true, true);
if (c_e_libs) proc_int (c_e_libs);
}
else
{
- bool same (*t == x); // Same as us.
- auto& vp (var_pool);
-
if (impl)
{
// Interface and implementation: as discussed above, we can have two
@@ -1346,14 +1345,14 @@ namespace build2
const target_type* tt (s.find_target_type (n, ext)); // Changes name.
if (tt == nullptr)
- fail << "unknown target type " << n.type << " in library " << n;
+ fail << "unknown target type '" << n.type << "' in library " << n;
// @@ OUT: for now we assume out is undetermined, just like in
// search (name, scope).
//
dir_path out;
prerequisite_key pk {n.proj, {tt, &n.dir, &out, &n.value, ext}, &s};
- xt = search_library (sysd, usrd, pk, lo);
+ xt = search_library (sysd, usrd, pk);
if (xt == nullptr)
{
@@ -1373,7 +1372,9 @@ namespace build2
}
void link::
- append_libraries (strings& args, file& l, bool la) const
+ append_libraries (strings& args,
+ file& l, bool la,
+ scope& bs, lorder lo) const
{
auto imp = [] (file&, bool la) {return la;};
@@ -1399,11 +1400,11 @@ namespace build2
}
};
- process_libraries (sys_lib_dirs, l, la, imp, lib, opt);
+ process_libraries (bs, lo, sys_lib_dirs, l, la, imp, lib, opt);
}
void link::
- hash_libraries (sha256& cs, file& l, bool la) const
+ hash_libraries (sha256& cs, file& l, bool la, scope& bs, lorder lo) const
{
auto imp = [] (file&, bool la) {return la;};
@@ -1427,11 +1428,14 @@ namespace build2
}
};
- process_libraries (sys_lib_dirs, l, la, imp, lib, opt);
+ process_libraries (bs, lo, sys_lib_dirs, l, la, imp, lib, opt);
}
void link::
- rpath_libraries (strings& args, file& l, bool la, bool for_install) const
+ rpath_libraries (strings& args,
+ file& l, bool la,
+ scope& bs, lorder lo,
+ bool for_install) const
{
// Use -rpath-link on targets that support it (Linux, FreeBSD). Note
// that we don't really need it for top-level libraries.
@@ -1528,7 +1532,7 @@ namespace build2
d.args.push_back (move (o));
};
- process_libraries (sys_lib_dirs, l, la, imp, lib, nullptr);
+ process_libraries (bs, lo, sys_lib_dirs, l, la, imp, lib, nullptr);
}
// See windows-rpath.cxx.
@@ -1559,8 +1563,11 @@ namespace build2
file& t (static_cast<file&> (xt));
- scope& rs (t.root_scope ());
+ scope& bs (t.base_scope ());
+ scope& rs (*bs.root_scope ());
+
otype lt (link_type (t));
+ lorder lo (link_order (bs, lt));
// Update prerequisites.
//
@@ -1828,7 +1835,7 @@ namespace build2
if ((f = a = pt->is_a<liba> ()) ||
(f = pt->is_a<libs> ()))
- rpath_libraries (sargs, *f, a != nullptr, for_install);
+ rpath_libraries (sargs, *f, a != nullptr, bs, lo, for_install);
}
if (auto l = t["bin.rpath"])
@@ -1891,7 +1898,7 @@ namespace build2
// interface and implementation (static), recursively.
//
if (a != nullptr || s != nullptr)
- hash_libraries (cs, *f, a != nullptr);
+ hash_libraries (cs, *f, a != nullptr, bs, lo);
}
}
@@ -2127,7 +2134,7 @@ namespace build2
// and implementation (static), recursively.
//
if (a != nullptr || s != nullptr)
- append_libraries (sargs, *f, a != nullptr);
+ append_libraries (sargs, *f, a != nullptr, bs, lo);
}
}
diff --git a/build2/cc/pkgconfig.cxx b/build2/cc/pkgconfig.cxx
index eb7f0a6..1efe3a4 100644
--- a/build2/cc/pkgconfig.cxx
+++ b/build2/cc/pkgconfig.cxx
@@ -27,7 +27,7 @@ namespace build2
// Try to find a .pc file in the pkgconfig/ subdirectory of libd, trying
// several names derived from stem. If not found, return false. If found,
// extract poptions, loptions, and libs, set the corresponding *.export.*
- // variables on lib, and return true.
+ // variables on targets, and return true.
//
// System library search paths (those extracted from the compiler) are
// passed in sys_sp and should already be extracted.
@@ -37,16 +37,18 @@ namespace build2
//
bool link::
pkgconfig_extract (scope& s,
- file& lt,
+ lib& lt,
+ liba* at,
+ libs* st,
const string* proj,
const string& stem,
const dir_path& libd,
- const dir_paths& sysd,
- lorder lo) const
+ const dir_paths& sysd) const
{
tracer trace (x, "link::pkgconfig_extract");
assert (pkgconfig != nullptr);
+ assert (at != nullptr || st != nullptr);
// Check if we have the pkgconfig/ subdirectory in this library's
// directory.
@@ -97,26 +99,22 @@ namespace build2
}
// Ok, we are in business. Time to run pkg-config. To keep things
- // simple, we run it twice, first time for --cflag, then for --libs.
+ // simple, we run it multiple times, for --cflag/--libs and --static.
//
- bool la (lt.is_a<liba> ());
-
- const char* args[] = {
- pkgconfig->initial,
- nullptr, // --cflags/--libs
- (la ? "--static" : f.string ().c_str ()),
- (la ? f.string ().c_str () : nullptr),
- nullptr
+ auto extract = [&f, this] (const char* op, bool impl) -> string
+ {
+ const char* args[] = {
+ pkgconfig->initial,
+ op, // --cflags/--libs
+ (impl ? "--static" : f.string ().c_str ()),
+ (impl ? f.string ().c_str () : nullptr),
+ nullptr
+ };
+
+ return run<string> (
+ *pkgconfig, args, [] (string& s) -> string {return move (s);});
};
- auto retline = [] (string& s) -> string {return move (s);};
-
- args[1] = "--cflags";
- string cstr (run<string> (*pkgconfig, args, retline));
-
- args[1] = "--libs";
- string lstr (run<string> (*pkgconfig, args, retline));
-
// On Windows pkg-config (at least the MSYS2 one which we are using)
// will escape backslahses in paths. In fact, it may escape things
// even on non-Windows platforms, for example, spaces. So we use a
@@ -157,9 +155,12 @@ namespace build2
return r;
};
- // Parse --cflags into poptions.
+ // First extract --cflags and set them as lib{}:export.poptions (i.e.,
+ // they will be common for both liba{} and libs{}; later when we do
+ // split .pc files, we will have to run this twice).
//
{
+ string cstr (extract ("--cflags", false));
strings pops;
bool arg (false);
@@ -207,8 +208,10 @@ namespace build2
}
}
- // Parse --libs into loptions/libs.
+ // Now parse --libs into loptions/libs (interface and implementation).
//
+ auto parse_libs = [&s, &f, sysd, &next, this] (
+ const string& lstr, target& t)
{
strings lops;
names libs;
@@ -373,11 +376,14 @@ namespace build2
prerequisite_key pk {
nullptr, {&lib::static_type, &out, &out, &name, ext}, &s};
- if (lib* lt = static_cast<lib*> (
- search_library (sysd, usrd, pk, lo)))
+ if (lib* lt = static_cast<lib*> (search_library (sysd, usrd, pk)))
{
- file& f (static_cast<file&> (link_member (*lt, lo)));
- l = f.path ().string ();
+ // We used to pick a member but that doesn't seem right since the
+ // same target could be used with different link orders.
+ //
+ n.dir = lt->dir;
+ n.type = lib::static_type.name;
+ n.value = lt->name;
}
else
// If we couldn't find the library, then leave it as -l.
@@ -391,7 +397,7 @@ namespace build2
if (all && known)
lops.clear ();
- if (!lops.empty ())
+ if (lops.empty ())
{
if (cid == "msvc")
{
@@ -418,19 +424,33 @@ namespace build2
}
}
- auto p (lt.vars.insert (c_export_loptions));
+ auto p (t.vars.insert (c_export_loptions));
if (p.second)
p.first.get () = move (lops);
}
- if (!libs.empty ())
+ // Set even if empty (export override).
+ //
{
- auto p (lt.vars.insert (c_export_libs));
+ auto p (t.vars.insert (c_export_libs));
if (p.second)
p.first.get () = move (libs);
}
+ };
+
+ {
+ string lstr_int (extract ("--libs", false));
+ string lstr_imp (extract ("--libs", true));
+
+ parse_libs (lstr_int, lt);
+
+ // Currently, these will result in the same values but it will be
+ // different once we support split .pc files.
+ //
+ if (at != nullptr) parse_libs (lstr_imp, *at);
+ if (st != nullptr) parse_libs (lstr_imp, *st);
}
return true;