aboutsummaryrefslogtreecommitdiff
path: root/build
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2015-08-03 13:10:28 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2015-08-03 13:10:28 +0200
commit0db17bfec8b3b6c436f3c9c346d17d98458c3654 (patch)
treec9dcd1d7678972b0a40450b21a7d23dd6ec1121b /build
parent3a2efbc3d33c70aa5d0a87c9a1d16b458541bdde (diff)
match_only and dependents count rework, part 1
Diffstat (limited to 'build')
-rw-r--r--build/algorithm16
-rw-r--r--build/algorithm.ixx7
-rw-r--r--build/bin/rule.cxx48
-rw-r--r--build/cli/rule.cxx2
-rw-r--r--build/cxx/compile.cxx25
-rw-r--r--build/install/rule.cxx4
6 files changed, 73 insertions, 29 deletions
diff --git a/build/algorithm b/build/algorithm
index 1171f9d..99e6c2b 100644
--- a/build/algorithm
+++ b/build/algorithm
@@ -64,11 +64,23 @@ namespace build
target&
search (name, scope&);
- // Match a rule to the action/target with ambiguity detection.
+ // Match and apply a rule to the action/target with ambiguity
+ // detection. Increment the target's dependents count, which
+ // means that you should call this function with the intent
+ // to also call execute(). In case of optimizations that
+ // would avoid calling execute(), decrement the dependents
+ // cound manually to compensate.
//
void
match (action, target&);
+ // Match (but do not apply) a rule to the action/target with
+ // ambiguity detection. Note that this function does not touch
+ // the dependents count.
+ //
+ void
+ match_only (action, target&);
+
// Match a "delegate rule" from withing another rules' apply()
// function. Return recipe and recipe action (if any). Note
// that unlike match(), this call doesn't increment the
@@ -120,7 +132,7 @@ namespace build
// Execute the action on target, assuming a rule has been matched
// and the recipe for this action has been set. This is the default
- // executor implementation.
+ // executor implementation. Decrements the dependents count.
//
target_state
execute (action, target&);
diff --git a/build/algorithm.ixx b/build/algorithm.ixx
index 26761bf..ce581c5 100644
--- a/build/algorithm.ixx
+++ b/build/algorithm.ixx
@@ -62,6 +62,13 @@ namespace build
t.dependents++;
}
+ inline void
+ match_only (action a, target& t)
+ {
+ if (!t.recipe (a))
+ match_impl (a, t, false);
+ }
+
inline std::pair<recipe, action>
match_delegate (action a, target& t)
{
diff --git a/build/bin/rule.cxx b/build/bin/rule.cxx
index 0845627..8df1ee0 100644
--- a/build/bin/rule.cxx
+++ b/build/bin/rule.cxx
@@ -37,8 +37,36 @@ namespace build
// members as our prerequisites.
//
match_result lib_rule::
- match (action, target& t, const std::string&) const
+ match (action a, target& t, const std::string&) const
{
+ // Search and match prerequisite libraries and add them to the
+ // prerequisite targets. While we never execute this list
+ // ourselves (see perform() below), this is necessary to make
+ // the exported options machinery work for the library chains
+ // (chaining is the reason why we have to do match, recursively).
+ // See the cxx.export.*-related code in cxx/compile.cxx for
+ // details.
+ //
+ for (prerequisite& p: group_prerequisites (t))
+ {
+ if (p.is_a<lib> ())
+ {
+ target& pt (search (p));
+ match_only (a, pt);
+ t.prerequisite_targets.push_back (&pt);
+ }
+ else if (p.is_a<liba> () || p.is_a<libso> ())
+ {
+ //@@ TMP: C++ link rule hasn't been converted to support
+ // match_only().
+ //
+ target& pt (search (p));
+ build::match (a, pt);
+ t.prerequisite_targets.push_back (&pt);
+ pt.dependents--; // No intent to execute.
+ }
+ }
+
return t;
}
@@ -75,24 +103,6 @@ namespace build
build::match (a, *t.so);
}
- // Search and match prerequisite libraries and add them to the
- // prerequisite targets. While we never execute this list
- // ourselves (see perform() below), this is necessary to make
- // the exported options machinery work for the library chains.
- // See cxx.export.*-related code in cxx/compile.cxx for details.
- //
- // @@ Messes up dependents count.
- //
- for (prerequisite& p: group_prerequisites (t))
- {
- if (p.is_a<lib> () || p.is_a<liba> () || p.is_a<libso> ())
- {
- target& pt (search (p));
- build::match (a, pt);
- t.prerequisite_targets.push_back (&pt);
- }
- }
-
return &perform;
}
diff --git a/build/cli/rule.cxx b/build/cli/rule.cxx
index d1cb616..247b5b4 100644
--- a/build/cli/rule.cxx
+++ b/build/cli/rule.cxx
@@ -179,7 +179,7 @@ namespace build
{
cli_cxx& g (*static_cast<cli_cxx*> (mr.target));
build::match (a, g);
- return group_recipe;
+ return group_recipe; // Execute the group's recipe.
}
}
diff --git a/build/cxx/compile.cxx b/build/cxx/compile.cxx
index d89aaac..48d2240 100644
--- a/build/cxx/compile.cxx
+++ b/build/cxx/compile.cxx
@@ -113,17 +113,32 @@ namespace build
// 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 ());
- // @@ The fact that we match but never execute messes up
- // the dependents count. This is a workaround, not a
- // solution.
- //
- build::match (a, pt);
+ if (p.is_a<lib> ()) //@@ TMP
+ build::match_only (a, pt);
+ else
+ {
+ build::match (a, pt);
+ pt.dependents--;
+ }
}
continue;
diff --git a/build/install/rule.cxx b/build/install/rule.cxx
index 5642388..890228c 100644
--- a/build/install/rule.cxx
+++ b/build/install/rule.cxx
@@ -127,10 +127,10 @@ namespace build
// will help a lot in case of any static installable content
// (headers, documentation, etc).
//
- // @@ This messes up the dependents count logic.
- //
if (pt.state () != target_state::unchanged)
t.prerequisite_targets.push_back (&pt);
+ else
+ pt.dependents--; // No intent to execute, so compensate.
}
// This is where we diverge depending on the operation. In the