aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libbuild2/adhoc-rule-regex-pattern.cxx3
-rw-r--r--libbuild2/algorithm.hxx16
-rw-r--r--libbuild2/context.hxx12
-rw-r--r--libbuild2/operation.hxx4
-rw-r--r--libbuild2/target.cxx33
-rw-r--r--libbuild2/target.hxx8
-rw-r--r--libbuild2/target.ixx20
7 files changed, 59 insertions, 37 deletions
diff --git a/libbuild2/adhoc-rule-regex-pattern.cxx b/libbuild2/adhoc-rule-regex-pattern.cxx
index c621b67..9550527 100644
--- a/libbuild2/adhoc-rule-regex-pattern.cxx
+++ b/libbuild2/adhoc-rule-regex-pattern.cxx
@@ -405,7 +405,8 @@ namespace build2
continue;
// @@ TODO: it could be handy to mark a prerequisite (e.g., a tool)
- // ad hoc so that it doesn't interfere with the $< list.
+ // ad hoc so that it doesn't interfere with the $< list. Also
+ // clean=false.
//
pts.push_back (prerequisite_target (&pt, false /* adhoc */));
}
diff --git a/libbuild2/algorithm.hxx b/libbuild2/algorithm.hxx
index 984b786..73705d8 100644
--- a/libbuild2/algorithm.hxx
+++ b/libbuild2/algorithm.hxx
@@ -375,6 +375,18 @@ namespace build2
// the target is a member of a group, then first do this to the group's
// prerequisites.
//
+ // Regarding clean, it may seem more natural to only clean prerequisites
+ // that are in the same base rather than root scope. While it's often true
+ // for simple projects, in more complex cases it's not unusual to have
+ // common intermediate build results (object files, utility libraries, etc)
+ // reside in the parent and/or sibling directories. With such arrangements,
+ // cleaning only in base (even from the project root) may leave such
+ // intermediate build results laying around (since there is no reason to
+ // list them as prerequisites of any directory aliases). So we clean in the
+ // root scope by default but any target-prerequisite relationship can be
+ // marked not to trigger a clean with the clean=false prerequisite-specific
+ // value (see the include variable for details).
+ //
using match_search = function<
prerequisite_target (action,
const target&,
@@ -386,8 +398,8 @@ namespace build2
// As above but go into group members.
//
- // Note that if we cleaning, this function doesn't go into group members, as
- // an optimization (the group should clean everything up).
+ // Note that if we are cleaning, this function doesn't go into group
+ // members, as an optimization (the group should clean everything up).
//
using match_search_member = function<
prerequisite_target (action,
diff --git a/libbuild2/context.hxx b/libbuild2/context.hxx
index c93c1c9..7ac4af4 100644
--- a/libbuild2/context.hxx
+++ b/libbuild2/context.hxx
@@ -411,6 +411,9 @@ namespace build2
//
const variable* var_extension;
+ // Note that this variable can also be specified as prerequisite-specific
+ // (see the `include` variable for details).
+ //
// [bool] target visibility
//
const variable* var_clean;
@@ -450,6 +453,15 @@ namespace build2
// A rule with the "pass-through" semantics should treat the adhoc value
// the same as true.
//
+ // Sometimes it may be desirable to apply exclusions only to specific
+ // operations. The initial idea was to extend this value to allow
+ // specifying the operation (e.g., clean@false). However, later we
+ // realized that we could reuse the "operation variables" (clean, install,
+ // test) with a more natural-looking result. Note that currently we only
+ // recognize the built-in clean variable (for other variables we will need
+ // some kind of registration in an operation-to-variable map, probably in
+ // root scope).
+ //
// To query this value in rule implementations use the include() helpers
// from <libbuild2/prerequisites.hxx>.
//
diff --git a/libbuild2/operation.hxx b/libbuild2/operation.hxx
index de3ae7c..e115ac0 100644
--- a/libbuild2/operation.hxx
+++ b/libbuild2/operation.hxx
@@ -124,8 +124,8 @@ namespace build2
void (*operation_post) (const values&, operation_id);
void (*meta_operation_post) (const values&);
- // Optional prerequisite inclusion/exclusion override callback. See
- // include() for details.
+ // Optional prerequisite exclusion override callback. See include() for
+ // details. Note that it's not called for include_type::normal;
//
include_type (*include) (action,
const target&,
diff --git a/libbuild2/target.cxx b/libbuild2/target.cxx
index 7db5c66..bc5dbba 100644
--- a/libbuild2/target.cxx
+++ b/libbuild2/target.cxx
@@ -544,25 +544,38 @@ namespace build2
include_type
include_impl (action a,
const target& t,
- const string& v,
const prerequisite& p,
const target* m)
{
context& ctx (t.ctx);
- include_type r (false);
+ include_type r (include_type::normal);
- if (v == "false") r = include_type::excluded;
- else if (v == "adhoc") r = include_type::adhoc;
- else if (v == "true") r = include_type::normal;
- else
- fail << "invalid " << ctx.var_include->name << " variable value "
- << "'" << v << "' specified for prerequisite " << p;
+ // If var_clean is defined, then it takes precedence over include for
+ // the clean operation.
+ //
+ lookup l;
+ if (a.operation () == clean_id && (l = p.vars[ctx.var_clean]))
+ {
+ r = cast<bool> (l) ? include_type::normal : include_type::excluded;
+ }
+ else if (const string* v = cast_null<string> (p.vars[ctx.var_include]))
+ {
+ if (*v == "false") r = include_type::excluded;
+ else if (*v == "adhoc") r = include_type::adhoc;
+ else if (*v == "true") r = include_type::normal;
+ else
+ fail << "invalid " << ctx.var_include->name << " variable value "
+ << "'" << *v << "' specified for prerequisite " << p;
+ }
// Call the meta-operation override, if any (currently used by dist).
//
- if (auto f = ctx.current_mif->include)
- r = f (a, t, prerequisite_member {p, m}, r);
+ if (r != include_type::normal)
+ {
+ if (auto f = ctx.current_mif->include)
+ r = f (a, t, prerequisite_member {p, m}, r);
+ }
return r;
}
diff --git a/libbuild2/target.hxx b/libbuild2/target.hxx
index 8193f35..a5940ab 100644
--- a/libbuild2/target.hxx
+++ b/libbuild2/target.hxx
@@ -874,15 +874,11 @@ namespace build2
uint8_t
unmark (const target*&);
- // Helper for dealing with the prerequisite inclusion/exclusion (the
- // 'include' buildfile variable, see var_include in context.hxx).
+ // Helper for dealing with the prerequisite inclusion/exclusion (see
+ // var_include in context.hxx).
//
// Note that the include(prerequisite_member) overload is also provided.
//
- // @@ Maybe this filtering should be incorporated into *_prerequisites() and
- // *_prerequisite_members() logic? Could make normal > adhoc > excluded and
- // then pass the "threshold".
- //
include_type
include (action,
const target&,
diff --git a/libbuild2/target.ixx b/libbuild2/target.ixx
index 1c8dd8d..50750ca 100644
--- a/libbuild2/target.ixx
+++ b/libbuild2/target.ixx
@@ -287,27 +287,15 @@ namespace build2
// include()
//
LIBBUILD2_SYMEXPORT include_type
- include_impl (action,
- const target&,
- const string&,
- const prerequisite&,
- const target*);
+ include_impl (action, const target&, const prerequisite&, const target*);
inline include_type
include (action a, const target& t, const prerequisite& p, const target* m)
{
- // Most of the time this variable will not be specified, so let's optimize
- // for that.
+ // Most of the time no prerequisite-specific variables will be specified,
+ // so let's optimize for that.
//
- if (p.vars.empty ())
- return true;
-
- const string* v (cast_null<string> (p.vars[t.ctx.var_include]));
-
- if (v == nullptr)
- return true;
-
- return include_impl (a, t, *v, p, m);
+ return p.vars.empty () ? include_type (true) : include_impl (a, t, p, m);
}
// group_prerequisites