diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2016-08-28 06:31:47 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2016-08-28 06:31:47 +0200 |
commit | d3c5559f9d0969ec91ed0113223b2ec18e53c9ff (patch) | |
tree | c03212c0b567767446798d0df9cb59d683d6d0b8 | |
parent | 457f83ee501ba8f9a6a576de741e43ff9dfef039 (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/compile | 8 | ||||
-rw-r--r-- | build2/cc/compile.cxx | 43 | ||||
-rw-r--r-- | build2/cc/link | 25 | ||||
-rw-r--r-- | build2/cc/link.cxx | 219 | ||||
-rw-r--r-- | build2/cc/pkgconfig.cxx | 82 |
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 ? < : (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; |