From 7c57f2a85aa520db784a36ced65ec5c832dbfbc8 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 24 Jun 2022 05:44:37 +0200 Subject: Add ability to get common interface options via $x.lib_poptions() Specifically, the output target type may now be omitted for utility libraries (libul{} and libu[eas]{}). In this case, only "common interface" options will be returned for lib{} dependencies. This is primarily useful for obtaining poptions to be passed to tools other than C/C++ compilers (for example, Qt moc). --- libbuild2/cc/functions.cxx | 77 +++++++++++++++++++++++++++++++++------------- 1 file changed, 56 insertions(+), 21 deletions(-) (limited to 'libbuild2/cc/functions.cxx') diff --git a/libbuild2/cc/functions.cxx b/libbuild2/cc/functions.cxx index 9b7a3d9..a0a0b4f 100644 --- a/libbuild2/cc/functions.cxx +++ b/libbuild2/cc/functions.cxx @@ -85,14 +85,26 @@ namespace build2 return value (move (r)); } - // Common thunk for $x.lib_*(, [, ...]) functions. + // Common thunk for $x.lib_*(...) functions. + // + // The two supported function signatures are: + // + // $x.lib_*(, [, ...]]) + // + // $x.lib_*() + // + // For the first signature, the passed targets cannot be library groups + // (so they are always file-based) and linfo is always present. + // + // For the second signature, targets can only be utility libraries + // (including the libul{} group). // struct lib_thunk_data { const char* x; void (*f) (void*, strings&, const vector_view&, const module&, const scope&, - action, const file&, bool, linfo); + action, const target&, bool, optional); }; static value @@ -120,13 +132,15 @@ namespace build2 if (m == nullptr) fail << f.name << " called without " << d.x << " module loaded"; - // We can assume these are present due to function's types signature. + // We can assume this is present due to function's types signature. // names& ts_ns (vs[0].as ()); // - names& ot_ns (vs[1].as ()); // - linfo li; + optional li; + if (vs.size () > 1) { + names& ot_ns (vs[1].as ()); // + string t (convert (move (ot_ns))); const target_type* tt (bs->find_target_type (t)); @@ -172,21 +186,22 @@ namespace build2 name& n (*i), o; const target& t (to_target (*bs, move (n), move (n.pair ? *++i : o))); - const file* f; bool la (false); - - if ((la = (f = t.is_a ())) || - (la = (f = t.is_a ())) || - ( (f = t.is_a ()))) + if (li + ? ((la = t.is_a ()) || + (la = t.is_a ()) || + ( t.is_a ())) + : ((la = t.is_a ()) || + ( t.is_a ()))) { if (!t.matched (a)) fail << t << " is not matched" << info << "make sure this target is listed as prerequisite"; - d.f (ls, r, vs, *m, *bs, a, *f, la, li); + d.f (ls, r, vs, *m, *bs, a, t, la, li); } else - fail << t << " is not a library target"; + fail << t << " is not a library of expected type"; } return value (move (r)); @@ -213,12 +228,18 @@ namespace build2 void compile_rule:: functions (function_family& f, const char* x) { - // $.lib_poptions(, ) + // $.lib_poptions([, ]) // // Return the preprocessor options that should be passed when compiling // sources that depend on the specified libraries. The second argument // is the output target type (obje, objs, etc). // + // The output target type may be omitted for utility libraries (libul{} + // or libu[eas]{}). In this case, only "common interface" options will + // be returned for lib{} dependencies. This is primarily useful for + // obtaining poptions to be passed to tools other than C/C++ compilers + // (for example, Qt moc). + // // Note that passing multiple targets at once is not a mere convenience: // this also allows for more effective duplicate suppression. // @@ -230,17 +251,31 @@ namespace build2 // Note that this function is not pure. // f.insert (".lib_poptions", false). - insert ( + insert> ( &lib_thunk, lib_thunk_data { x, [] (void* ls, strings& r, const vector_view&, const module& m, const scope& bs, - action a, const file& l, bool la, linfo li) + action a, const target& l, bool la, optional li) { + // If this is libul{}, get the matched member (see bin::libul_rule + // for details). + // + const file& f ( + la || li + ? l.as () + : (la = true, + l.prerequisite_targets[a].back ().target->as ())); + + bool common (!li); + + if (!li) + li = link_info (bs, link_type (f).type); + m.append_library_options ( *static_cast (ls), r, - bs, a, l, la, li); + bs, a, f, la, *li, common); }}); // $.find_system_header() @@ -318,7 +353,7 @@ namespace build2 x, [] (void* ls, strings& r, const vector_view& vs, const module& m, const scope& bs, - action a, const file& l, bool la, linfo li) + action a, const target& l, bool la, optional li) { lflags lf (0); bool rel (true); @@ -342,7 +377,8 @@ namespace build2 m.append_libraries ( *static_cast (ls), r, nullptr /* sha256 */, nullptr /* update */, timestamp_unknown, - bs, a, l, la, lf, li, nullopt /* for_install */, self, rel); + bs, a, l.as (), la, lf, *li, + nullopt /* for_install */, self, rel); }}); // $.lib_rpaths(, [, [, ]]) @@ -374,13 +410,12 @@ namespace build2 x, [] (void* ls, strings& r, const vector_view& vs, const module& m, const scope& bs, - action a, const file& l, bool la, linfo li) + action a, const target& l, bool la, optional li) { bool link (vs.size () > 2 ? convert (vs[2]) : false); bool self (vs.size () > 3 ? convert (vs[3]) : true); m.rpath_libraries (*static_cast (ls), r, - bs, - a, l, la, li, link, self); + bs, a, l.as (), la, *li, link, self); }}); // $cxx.obj_modules() -- cgit v1.1