From cab2e9ebc2b9985ae0a2e5d6971ace170c2d5651 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 18 Jul 2016 08:17:02 +0200 Subject: Pick liba{}/libs{} before looking up cxx.export.* This way we can specify static library-specific defines which are necessary to handle DLL export. --- build2/cxx/compile.cxx | 70 ++++++++++++++++++++++++++++++++------------------ build2/cxx/link.cxx | 18 ++++++++----- build2/cxx/utility | 6 +++-- build2/cxx/utility.cxx | 18 ++++++++----- 4 files changed, 73 insertions(+), 39 deletions(-) (limited to 'build2/cxx') diff --git a/build2/cxx/compile.cxx b/build2/cxx/compile.cxx index 645e818..085f6b4 100644 --- a/build2/cxx/compile.cxx +++ b/build2/cxx/compile.cxx @@ -60,7 +60,7 @@ namespace build2 } static void - inject_prerequisites (action, target&, cxx&, scope&, depdb&); + inject_prerequisites (action, target&, lorder, cxx&, scope&, depdb&); recipe compile:: apply (action a, target& xt, const match_result& mr) const @@ -69,7 +69,8 @@ namespace build2 path_target& t (static_cast (xt)); - scope& rs (t.root_scope ()); + scope& bs (t.base_scope ()); + scope& rs (*bs.root_scope ()); const string& cid (cast (rs["cxx.id"])); const string& tsys (cast (rs["cxx.target.system"])); @@ -223,12 +224,16 @@ namespace build2 // Hash cxx.export.poptions from prerequisite libraries. // + lorder lo (link_order (bs, ct)); for (prerequisite& p: group_prerequisites (t)) { - target& pt (*p.target); // Already searched and matched. + target* pt (p.target); // Already searched and matched. + + if (lib* l = pt->is_a ()) + pt = &link_member (*l, lo); - if (pt.is_a () || pt.is_a () || pt.is_a ()) - hash_lib_options (cs, pt, "cxx.export.poptions"); + if (pt->is_a () || pt->is_a ()) + hash_lib_options (cs, *pt, "cxx.export.poptions", lo); } hash_options (cs, t, "cxx.poptions"); @@ -258,7 +263,7 @@ namespace build2 if (dd.writing () || dd.mtime () > t.mtime ()) t.mtime (timestamp_nonexistent); - inject_prerequisites (a, t, st, mr.prerequisite->scope, dd); + inject_prerequisites (a, t, lo, st, mr.prerequisite->scope, dd); dd.close (); } @@ -405,22 +410,25 @@ namespace build2 // recursively, prerequisite libraries first. // static void - append_lib_prefixes (prefix_map& m, target& l) + append_lib_prefixes (prefix_map& m, target& l, lorder lo) { for (target* t: l.prerequisite_targets) { if (t == nullptr) continue; - if (t->is_a () || t->is_a () || t->is_a ()) - append_lib_prefixes (m, *t); + if (lib* l = t->is_a ()) + t = &link_member (*l, lo); // Pick one of the members. + + if (t->is_a () || t->is_a ()) + append_lib_prefixes (m, *t, lo); } append_prefixes (m, l, "cxx.export.poptions"); } static prefix_map - build_prefix_map (target& t) + build_prefix_map (target& t, lorder lo) { prefix_map m; @@ -430,10 +438,13 @@ namespace build2 // for (prerequisite& p: group_prerequisites (t)) { - target& pt (*p.target); // Already searched and matched. + target* pt (p.target); // Already searched and matched. + + if (lib* l = pt->is_a ()) + pt = &link_member (*l, lo); // Pick one of the members. - if (pt.is_a () || pt.is_a () || pt.is_a ()) - append_lib_prefixes (m, pt); + if (pt->is_a () || pt->is_a ()) + append_lib_prefixes (m, *pt, lo); } // Then process our own. @@ -622,7 +633,8 @@ namespace build2 } static void - inject_prerequisites (action a, target& t, cxx& s, scope& ds, depdb& dd) + inject_prerequisites (action a, target& t, lorder lo, + cxx& s, scope& ds, depdb& dd) { tracer trace ("cxx::compile::inject_prerequisites"); @@ -646,7 +658,7 @@ namespace build2 cstrings args; string cxx_std; // Storage. - auto init_args = [&t, &s, &rs, &cid, &args, &cxx_std] () + auto init_args = [&t, lo, &s, &rs, &cid, &args, &cxx_std] () { const path& cxx (cast (rs["config.cxx"])); const string& tclass (cast (rs["cxx.target.class"])); @@ -658,10 +670,13 @@ namespace build2 // for (prerequisite& p: group_prerequisites (t)) { - target& pt (*p.target); // Already searched and matched. + target* pt (p.target); // Already searched and matched. - if (pt.is_a () || pt.is_a () || pt.is_a ()) - append_lib_options (args, pt, "cxx.export.poptions"); + if (lib* l = pt->is_a ()) + pt = &link_member (*l, lo); + + if (pt->is_a () || pt->is_a ()) + append_lib_options (args, *pt, "cxx.export.poptions", lo); } append_options (args, t, "cxx.poptions"); @@ -799,8 +814,8 @@ 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, &ds, &dd] (path f, bool cache) - -> bool + auto add = [&trace, &update, &pm, a, &t, lo, &ds, &dd] + (path f, bool cache) -> bool { if (!f.absolute ()) { @@ -815,7 +830,7 @@ namespace build2 // then we would have failed below. // if (pm.empty ()) - pm = build_prefix_map (t); + pm = build_prefix_map (t, lo); // First try the whole file. Then just the directory. // @@ -1224,7 +1239,8 @@ namespace build2 if (s == nullptr) return target_state::unchanged; - scope& rs (t.root_scope ()); + scope& bs (t.base_scope ()); + scope& rs (*bs.root_scope ()); const path& cxx (cast (rs["config.cxx"])); const string& cid (cast (rs["cxx.id"])); @@ -1243,12 +1259,16 @@ namespace build2 // Add cxx.export.poptions from prerequisite libraries. Note that // here we don't need to see group members (see apply()). // + lorder lo (link_order (bs, ct)); for (prerequisite& p: group_prerequisites (t)) { - target& pt (*p.target); // Already searched and matched. + target* pt (p.target); // Already searched and matched. + + if (lib* l = pt->is_a ()) + pt = &link_member (*l, lo); - if (pt.is_a () || pt.is_a () || pt.is_a ()) - append_lib_options (args, pt, "cxx.export.poptions"); + if (pt->is_a () || pt->is_a ()) + append_lib_options (args, *pt, "cxx.export.poptions", lo); } append_options (args, t, "cxx.poptions"); diff --git a/build2/cxx/link.cxx b/build2/cxx/link.cxx index 002cd42..25e3650 100644 --- a/build2/cxx/link.cxx +++ b/build2/cxx/link.cxx @@ -878,13 +878,19 @@ namespace build2 ot.prerequisites.emplace_back (p.as_prerequisite (trace)); // Add our lib*{} prerequisites to the object file (see - // cxx.export.poptions above for details). Note: no need - // to go into group members. + // cxx.export.poptions above for details). // - // Initially, we were only adding imported libraries, but - // there is a problem with this approach: the non-imported - // library might depend on the imported one(s) which we will - // never "see" unless we start with this library. + // Note that we don't resolve lib{} to liba{}/libs{} here instead + // leaving it to whoever (e.g., the compile rule) will be needing + // cxx.export.*. One reason for doing it there is that the object + // target might be specified explicitly by the user in which case + // they will have to specify the set of lib{} prerequisites and it's + // much cleaner to do as lib{} rather than liba{}/libs{}. + // + // Initially, we were only adding imported libraries, but there is a + // problem with this approach: the non-imported library might depend + // on the imported one(s) which we will never "see" unless we start + // with this library. // for (prerequisite& p: group_prerequisites (t)) { diff --git a/build2/cxx/utility b/build2/cxx/utility index e924ee8..7333af6 100644 --- a/build2/cxx/utility +++ b/build2/cxx/utility @@ -10,6 +10,8 @@ #include +#include + namespace build2 { namespace cxx @@ -28,10 +30,10 @@ namespace build2 // recursively, prerequisite libraries first. // void - append_lib_options (cstrings&, target&, const char* variable); + append_lib_options (cstrings&, target&, const char* variable, lorder); void - hash_lib_options (sha256&, target&, const char* variable); + hash_lib_options (sha256&, target&, const char* variable, lorder); } } diff --git a/build2/cxx/utility.cxx b/build2/cxx/utility.cxx index cf9c4d0..7aae6ac 100644 --- a/build2/cxx/utility.cxx +++ b/build2/cxx/utility.cxx @@ -73,28 +73,34 @@ namespace build2 } void - append_lib_options (cstrings& args, target& l, const char* var) + append_lib_options (cstrings& args, target& l, const char* var, lorder lo) { using namespace bin; for (target* t: l.prerequisite_targets) { - if (t->is_a () || t->is_a () || t->is_a ()) - append_lib_options (args, *t, var); + if (lib* l = t->is_a ()) + t = &link_member (*l, lo); // Pick one of the members. + + if (t->is_a () || t->is_a ()) + append_lib_options (args, *t, var, lo); } append_options (args, l, var); } void - hash_lib_options (sha256& csum, target& l, const char* var) + hash_lib_options (sha256& csum, target& l, const char* var, lorder lo) { using namespace bin; for (target* t: l.prerequisite_targets) { - if (t->is_a () || t->is_a () || t->is_a ()) - hash_lib_options (csum, *t, var); + if (lib* l = t->is_a ()) + t = &link_member (*l, lo); // Pick one of the members. + + if (t->is_a () || t->is_a ()) + hash_lib_options (csum, *t, var, lo); } hash_options (csum, l, var); -- cgit v1.1