aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build2/cxx/compile.cxx70
-rw-r--r--build2/cxx/link.cxx18
-rw-r--r--build2/cxx/utility6
-rw-r--r--build2/cxx/utility.cxx18
4 files changed, 73 insertions, 39 deletions
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<path_target&> (xt));
- scope& rs (t.root_scope ());
+ scope& bs (t.base_scope ());
+ scope& rs (*bs.root_scope ());
const string& cid (cast<string> (rs["cxx.id"]));
const string& tsys (cast<string> (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<lib> ())
+ pt = &link_member (*l, lo);
- if (pt.is_a<lib> () || pt.is_a<liba> () || pt.is_a<libs> ())
- hash_lib_options (cs, pt, "cxx.export.poptions");
+ if (pt->is_a<liba> () || pt->is_a<libs> ())
+ 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<lib> () || t->is_a<liba> () || t->is_a<libs> ())
- append_lib_prefixes (m, *t);
+ if (lib* l = t->is_a<lib> ())
+ t = &link_member (*l, lo); // Pick one of the members.
+
+ if (t->is_a<liba> () || t->is_a<libs> ())
+ 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<lib> ())
+ pt = &link_member (*l, lo); // Pick one of the members.
- if (pt.is_a<lib> () || pt.is_a<liba> () || pt.is_a<libs> ())
- append_lib_prefixes (m, pt);
+ if (pt->is_a<liba> () || pt->is_a<libs> ())
+ 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<path> (rs["config.cxx"]));
const string& tclass (cast<string> (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<lib> () || pt.is_a<liba> () || pt.is_a<libs> ())
- append_lib_options (args, pt, "cxx.export.poptions");
+ if (lib* l = pt->is_a<lib> ())
+ pt = &link_member (*l, lo);
+
+ if (pt->is_a<liba> () || pt->is_a<libs> ())
+ 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<path> (rs["config.cxx"]));
const string& cid (cast<string> (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<lib> ())
+ pt = &link_member (*l, lo);
- if (pt.is_a<lib> () || pt.is_a<liba> () || pt.is_a<libs> ())
- append_lib_options (args, pt, "cxx.export.poptions");
+ if (pt->is_a<liba> () || pt->is_a<libs> ())
+ 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 <build2/target>
+#include <build2/cxx/common>
+
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<lib> () || t->is_a<liba> () || t->is_a<libs> ())
- append_lib_options (args, *t, var);
+ if (lib* l = t->is_a<lib> ())
+ t = &link_member (*l, lo); // Pick one of the members.
+
+ if (t->is_a<liba> () || t->is_a<libs> ())
+ 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<lib> () || t->is_a<liba> () || t->is_a<libs> ())
- hash_lib_options (csum, *t, var);
+ if (lib* l = t->is_a<lib> ())
+ t = &link_member (*l, lo); // Pick one of the members.
+
+ if (t->is_a<liba> () || t->is_a<libs> ())
+ hash_lib_options (csum, *t, var, lo);
}
hash_options (csum, l, var);