aboutsummaryrefslogtreecommitdiff
path: root/build/cxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2015-08-03 15:47:35 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2015-08-03 15:47:35 +0200
commitabb7bf1045fde14f6ef87c8941ee22af233af397 (patch)
tree734b8e605c00f79e00687ec4912366b88fbbb050 /build/cxx
parent0db17bfec8b3b6c436f3c9c346d17d98458c3654 (diff)
match_only rework, part 2
Diffstat (limited to 'build/cxx')
-rw-r--r--build/cxx/compile.cxx43
-rw-r--r--build/cxx/link.cxx64
2 files changed, 56 insertions, 51 deletions
diff --git a/build/cxx/compile.cxx b/build/cxx/compile.cxx
index 48d2240..8dcad1e 100644
--- a/build/cxx/compile.cxx
+++ b/build/cxx/compile.cxx
@@ -98,46 +98,23 @@ namespace build
// A dependency on a library is there so that we can get its
// cxx.export.poptions. In particular, making sure it is
// executed before us will only restrict parallelism. But we
- // do need to match it in order to get its prerequisite_targets
- // populated; see append_lib_options() above.
+ // do need to pre-match it in order to get its
+ // prerequisite_targets populated. This is the "library
+ // meta-information protocol". See also append_lib_options()
+ // above.
//
if (p.is_a<lib> () || p.is_a<liba> () || p.is_a<libso> ())
{
if (a.operation () == update_id)
{
- // Handle imported libraries.
+ // Handle imported libraries. We know that for such libraries
+ // we don't need to do match() in order to get options (if
+ // any, they would be set by search_library()).
//
- if (p.proj () != nullptr)
+ if (p.proj () == nullptr ||
+ link::search_library (lib_paths, p.prerequisite) == nullptr)
{
- // We know that for such libraries we don't need to do
- // match() in order to get options (if any, they would
- // be set by search_library()).
- //
- // @@ What if this is an installed import with an export
- // stub? How will such a stub capture prerequsite libs?
- // Probably as imported prerequisites, e.g., %lib{z}, not
- // as -lz in .libs variable.
- //
- // In fact, even if we tried match() on lib{}, nothing
- // would have matched since that lib{} is out of any
- // project and is not a file (which is the case for
- // liba/libso). So probably the importing code would
- // have to take care of importing all the prerequisite
- // libraries. It does make sense since we don't really
- // want to match a rule to an installed library.
- //
- if (link::search_library (lib_paths, p.prerequisite) != nullptr)
- continue;
- }
-
- target& pt (p.search ());
-
- if (p.is_a<lib> ()) //@@ TMP
- build::match_only (a, pt);
- else
- {
- build::match (a, pt);
- pt.dependents--;
+ match_only (a, p.search ());
}
}
diff --git a/build/cxx/link.cxx b/build/cxx/link.cxx
index 5c3a515..97c9696 100644
--- a/build/cxx/link.cxx
+++ b/build/cxx/link.cxx
@@ -365,7 +365,7 @@ namespace build
// (i.e., a utility library).
//
- bool so (t.is_a<libso> ());
+ type lt (link_type (t));
// Scan prerequisites and see if we can work with what we've got.
//
@@ -384,7 +384,7 @@ namespace build
}
else if (p.is_a<obja> ())
{
- if (so)
+ if (lt == type::so)
fail << "shared library " << t << " prerequisite " << p
<< " is static object";
@@ -423,6 +423,45 @@ namespace build
return nullptr;
}
+ // If we have any prerequisite libraries (which also means that
+ // we match), search/import and pre-match them to implement the
+ // "library meta-information protocol".
+ //
+ if (seen_lib && lt != type::e)
+ {
+ if (t.group != nullptr)
+ t.group->prerequisite_targets.clear (); // lib{}'s
+
+ search_paths_cache lib_paths; // Extract lazily.
+
+ for (prerequisite_member p: group_prerequisite_members (a, t))
+ {
+ if (p.is_a<lib> () || p.is_a<liba> () || p.is_a<libso> ())
+ {
+ target* pt (nullptr);
+
+ // Handle imported libraries.
+ //
+ if (p.proj () != nullptr)
+ pt = search_library (lib_paths, p.prerequisite);
+
+ if (pt == nullptr)
+ {
+ pt = &p.search ();
+ match_only (a, *pt);
+ }
+
+ // If the prerequisite came from the lib{} group, then also
+ // add it to lib's prerequisite_targets.
+ //
+ if (!p.prerequisite.belongs (t))
+ t.group->prerequisite_targets.push_back (pt);
+
+ t.prerequisite_targets.push_back (pt);
+ }
+ }
+ }
+
return seen_cxx || seen_c || seen_obj || seen_lib ? &t : nullptr;
}
@@ -449,6 +488,8 @@ namespace build
}
}
+ t.prerequisite_targets.clear (); // See lib pre-match in match() above.
+
// Inject dependency on the output directory.
//
inject_parent_fsdir (a, t);
@@ -480,27 +521,14 @@ namespace build
if (!p.is_a<c> () && !p.is_a<cxx> ())
{
- // Handle imported libraries. Essentially, we want to replicate
- // the -lfoo functionality but as part of our import support.
+ // Handle imported libraries.
//
- if (p.proj () != nullptr &&
- (p.is_a<lib> () || p.is_a<liba> () || p.is_a<libso> ()))
- {
+ if (p.proj () != nullptr)
pt = search_library (lib_paths, p.prerequisite);
- // We only need this target if we are updating (remember, like
- // -lfoo). The question is why search in the first place? The
- // reason is the "not found" situation, in which someone else
- // (i.e., the import phase 2) could resolve it to something
- // that, who knows, might need cleaning, for example.
- //
- if (pt != nullptr && a.operation () != update_id)
- continue; // Skip.
- }
-
// The rest is the same basic logic as in search_and_match().
//
- if (pt == nullptr) // Could've been resolved by search_library().
+ if (pt == nullptr)
pt = &p.search ();
if (a.operation () == clean_id && !pt->dir.sub (*amlg))