aboutsummaryrefslogtreecommitdiff
path: root/libbuild2
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2022-04-06 11:26:52 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2022-04-06 13:51:56 +0200
commit76be0a35f6c37cda7ba65530330f1ac246fb52a8 (patch)
treef613ceafcf6c7208984d4536653061c4e0c23be7 /libbuild2
parent0a9dd0c7d31cbba2170fdfda4b747a1fe5ce665a (diff)
Add support for rule hints
A rule hint is a target attribute, for example: [rule_hint=cxx] exe{hello}: c{hello} Rule hints can be used to resolve ambiguity when multiple rules match the same target as well as to override an unambiguous match.
Diffstat (limited to 'libbuild2')
-rw-r--r--libbuild2/adhoc-rule-cxx.cxx2
-rw-r--r--libbuild2/adhoc-rule-cxx.hxx2
-rw-r--r--libbuild2/algorithm.cxx30
-rw-r--r--libbuild2/bash/init.cxx10
-rw-r--r--libbuild2/bash/rule.cxx7
-rw-r--r--libbuild2/bash/rule.hxx7
-rw-r--r--libbuild2/bash/target.cxx2
-rw-r--r--libbuild2/bin/def-rule.cxx2
-rw-r--r--libbuild2/bin/def-rule.hxx2
-rw-r--r--libbuild2/bin/init.cxx6
-rw-r--r--libbuild2/bin/rule.cxx6
-rw-r--r--libbuild2/bin/rule.hxx6
-rw-r--r--libbuild2/bin/target.cxx55
-rw-r--r--libbuild2/c/init.cxx1
-rw-r--r--libbuild2/cc/common.hxx9
-rw-r--r--libbuild2/cc/compile-rule.cxx2
-rw-r--r--libbuild2/cc/compile-rule.hxx2
-rw-r--r--libbuild2/cc/install-rule.cxx17
-rw-r--r--libbuild2/cc/install-rule.hxx8
-rw-r--r--libbuild2/cc/link-rule.cxx6
-rw-r--r--libbuild2/cc/link-rule.hxx8
-rw-r--r--libbuild2/cc/module.cxx24
-rw-r--r--libbuild2/cc/target.cxx12
-rw-r--r--libbuild2/config/init.cxx5
-rw-r--r--libbuild2/context.cxx11
-rw-r--r--libbuild2/cxx/init.cxx1
-rw-r--r--libbuild2/cxx/target.cxx10
-rw-r--r--libbuild2/dist/init.cxx2
-rw-r--r--libbuild2/dist/rule.cxx2
-rw-r--r--libbuild2/dist/rule.hxx2
-rw-r--r--libbuild2/dump.cxx33
-rw-r--r--libbuild2/in/rule.cxx2
-rw-r--r--libbuild2/in/rule.hxx2
-rw-r--r--libbuild2/in/target.cxx2
-rw-r--r--libbuild2/install/init.cxx13
-rw-r--r--libbuild2/install/rule.cxx12
-rw-r--r--libbuild2/install/rule.hxx12
-rw-r--r--libbuild2/parser.cxx129
-rw-r--r--libbuild2/parser.hxx15
-rw-r--r--libbuild2/rule-map.hxx56
-rw-r--r--libbuild2/rule.cxx29
-rw-r--r--libbuild2/rule.hxx50
-rw-r--r--libbuild2/scope.hxx6
-rw-r--r--libbuild2/scope.ixx6
-rw-r--r--libbuild2/target-type.hxx46
-rw-r--r--libbuild2/target.cxx28
-rw-r--r--libbuild2/target.hxx69
-rw-r--r--libbuild2/target.ixx87
-rw-r--r--libbuild2/test/rule.cxx4
-rw-r--r--libbuild2/test/rule.hxx8
-rw-r--r--libbuild2/test/target.cxx2
-rw-r--r--libbuild2/version/init.cxx2
-rw-r--r--libbuild2/version/rule.cxx6
-rw-r--r--libbuild2/version/rule.hxx4
54 files changed, 633 insertions, 249 deletions
diff --git a/libbuild2/adhoc-rule-cxx.cxx b/libbuild2/adhoc-rule-cxx.cxx
index 0cd2ca1..72387c1 100644
--- a/libbuild2/adhoc-rule-cxx.cxx
+++ b/libbuild2/adhoc-rule-cxx.cxx
@@ -20,7 +20,7 @@ namespace build2
// cxx_rule_v1
//
bool cxx_rule_v1::
- match (action, target&, const string&) const
+ match (action, target&) const
{
return true;
}
diff --git a/libbuild2/adhoc-rule-cxx.hxx b/libbuild2/adhoc-rule-cxx.hxx
index 466c0e5..29d8aa1 100644
--- a/libbuild2/adhoc-rule-cxx.hxx
+++ b/libbuild2/adhoc-rule-cxx.hxx
@@ -53,7 +53,7 @@ namespace build2
// Return true by default.
//
virtual bool
- match (action, target&, const string&) const override;
+ match (action, target&) const override;
};
// Note: not exported.
diff --git a/libbuild2/algorithm.cxx b/libbuild2/algorithm.cxx
index 217e7af..61ab92c 100644
--- a/libbuild2/algorithm.cxx
+++ b/libbuild2/algorithm.cxx
@@ -447,6 +447,8 @@ namespace build2
meta_operation_id mo (a.meta_operation ());
operation_id o (a.inner () ? a.operation () : a.outer_operation ());
+ const string& hint (t.find_hint (o)); // MT-safe (target locked).
+
for (auto tt (&t.type ()); tt != nullptr; tt = tt->base)
{
// Search scopes outwards, stopping at the project root.
@@ -478,23 +480,11 @@ namespace build2
if (i == ttm->end () || i->second.empty ())
continue; // No rules registered for this target type.
- const auto& rules (i->second); // Hint map.
+ const auto& rules (i->second); // Name map.
- // @@ TODO hint
- //
- // Different rules can be used for different operations (update vs
- // test is a good example). So, at some point, we will probably have
- // to support a list of hints or even an operation-hint map (e.g.,
- // 'hint=cxx test=foo' if cxx supports the test operation but we
- // want the foo rule instead). This is also the place where the
- // '{build clean}=cxx' construct (which we currently do not support)
- // can come handy.
- //
- // Also, ignore the hint (that is most likely ment for a different
- // operation) if this is a unique match.
+ // Filter against the hint, if any.
//
- string hint;
- auto rs (rules.size () == 1
+ auto rs (hint.empty ()
? make_pair (rules.begin (), rules.end ())
: rules.find_sub (hint));
@@ -622,8 +612,14 @@ namespace build2
if (!try_match)
{
- diag_record dr;
- dr << fail << "no rule to " << diag_do (a, t);
+ diag_record dr (fail);
+
+ if (hint.empty ())
+ dr << "no rule to ";
+ else
+ dr << "no rule with hint " << hint << " to ";
+
+ dr << diag_do (a, t);
// Try to give some hints of the common causes.
//
diff --git a/libbuild2/bash/init.cxx b/libbuild2/bash/init.cxx
index a1effa1..88c88ba 100644
--- a/libbuild2/bash/init.cxx
+++ b/libbuild2/bash/init.cxx
@@ -20,7 +20,7 @@ namespace build2
namespace bash
{
static const in_rule in_rule_;
- static const install_rule install_rule_ (in_rule_);
+ static const install_rule install_rule_ (in_rule_, "bash.in");
bool
init (scope& rs,
@@ -71,11 +71,11 @@ namespace build2
if (install_loaded)
{
- bs.insert_rule<exe> (perform_install_id, "bash.install", install_rule_);
- bs.insert_rule<exe> (perform_uninstall_id, "bash.uninstall", install_rule_);
+ bs.insert_rule<exe> (perform_install_id, "bash.install", install_rule_);
+ bs.insert_rule<exe> (perform_uninstall_id, "bash.install", install_rule_);
- bs.insert_rule<bash> (perform_install_id, "bash.install", install_rule_);
- bs.insert_rule<bash> (perform_uninstall_id, "bash.uninstall", install_rule_);
+ bs.insert_rule<bash> (perform_install_id, "bash.install", install_rule_);
+ bs.insert_rule<bash> (perform_uninstall_id, "bash.install", install_rule_);
}
return true;
diff --git a/libbuild2/bash/rule.cxx b/libbuild2/bash/rule.cxx
index ec24226..3048d3c 100644
--- a/libbuild2/bash/rule.cxx
+++ b/libbuild2/bash/rule.cxx
@@ -41,7 +41,7 @@ namespace build2
// in_rule
//
bool in_rule::
- match (action a, target& t, const string&) const
+ match (action a, target& t) const
{
tracer trace ("bash::in_rule::match");
@@ -424,12 +424,13 @@ namespace build2
// install_rule
//
bool install_rule::
- match (action a, target& t, const string& hint) const
+ match (action a, target& t) const
{
// We only want to handle installation if we are also the ones building
// this target. So first run in's match().
//
- return in_.match (a, t, hint) && file_rule::match (a, t, "");
+ return in_.sub_match (in_name_, update_id, a, t) &&
+ file_rule::match (a, t);
}
recipe install_rule::
diff --git a/libbuild2/bash/rule.hxx b/libbuild2/bash/rule.hxx
index f69ac3b..1a0cb36 100644
--- a/libbuild2/bash/rule.hxx
+++ b/libbuild2/bash/rule.hxx
@@ -32,7 +32,7 @@ namespace build2
in_rule (): rule ("bash.in 1", "bash.in", '@', false /* strict */) {}
virtual bool
- match (action, target&, const string&) const override;
+ match (action, target&) const override;
virtual recipe
apply (action, target&) const override;
@@ -68,16 +68,17 @@ namespace build2
class LIBBUILD2_BASH_SYMEXPORT install_rule: public install::file_rule
{
public:
- install_rule (const in_rule& in): in_ (in) {}
+ install_rule (const in_rule& r, const char* n): in_ (r), in_name_ (n) {}
virtual bool
- match (action, target&, const string&) const override;
+ match (action, target&) const override;
virtual recipe
apply (action, target&) const override;
protected:
const in_rule& in_;
+ const string in_name_;
};
}
}
diff --git a/libbuild2/bash/target.cxx b/libbuild2/bash/target.cxx
index 6fa7cf4..5240fed 100644
--- a/libbuild2/bash/target.cxx
+++ b/libbuild2/bash/target.cxx
@@ -23,7 +23,7 @@ namespace build2
&target_pattern_var<bash_ext_def>,
nullptr,
&file_search,
- false
+ target_type::flag::none
};
}
}
diff --git a/libbuild2/bin/def-rule.cxx b/libbuild2/bin/def-rule.cxx
index 63508c5..c0e82fb 100644
--- a/libbuild2/bin/def-rule.cxx
+++ b/libbuild2/bin/def-rule.cxx
@@ -449,7 +449,7 @@ namespace build2
}
bool def_rule::
- match (action a, target& t, const string&) const
+ match (action a, target& t) const
{
tracer trace ("bin::def_rule::match");
diff --git a/libbuild2/bin/def-rule.hxx b/libbuild2/bin/def-rule.hxx
index 32423a0..acdf841 100644
--- a/libbuild2/bin/def-rule.hxx
+++ b/libbuild2/bin/def-rule.hxx
@@ -24,7 +24,7 @@ namespace build2
def_rule () {}
virtual bool
- match (action, target&, const string&) const override;
+ match (action, target&) const override;
virtual recipe
apply (action, target&) const override;
diff --git a/libbuild2/bin/init.cxx b/libbuild2/bin/init.cxx
index ab3980a..2b1df97 100644
--- a/libbuild2/bin/init.cxx
+++ b/libbuild2/bin/init.cxx
@@ -547,7 +547,7 @@ namespace build2
&target_pattern_fix<wasm_ext>,
&target_print_0_ext_verb, // Fixed extension, no use printing.
&file_search,
- false /* see_through */}));
+ target_type::flag::none}));
if (install_loaded)
{
@@ -578,8 +578,6 @@ namespace build2
// Similar to alias.
//
-
- //@@ outer
r.insert<lib> (perform_id, 0, "bin.lib", lib_);
r.insert<lib> (configure_id, 0, "bin.lib", lib_);
@@ -927,7 +925,7 @@ namespace build2
&target_pattern_fix<pdb_ext>,
&target_print_0_ext_verb, // Fixed extension, no use printing.
&file_search,
- false /* see_through */}));
+ target_type::flag::none}));
if (cast_false<bool> (rs["install.loaded"]))
{
diff --git a/libbuild2/bin/rule.cxx b/libbuild2/bin/rule.cxx
index 021a768..85cc9de 100644
--- a/libbuild2/bin/rule.cxx
+++ b/libbuild2/bin/rule.cxx
@@ -20,7 +20,7 @@ namespace build2
// obj_rule
//
bool obj_rule::
- match (action a, target& t, const string&) const
+ match (action a, target& t) const
{
const char* n (t.dynamic_type ().name); // Ignore derived type.
@@ -35,7 +35,7 @@ namespace build2
// libul_rule
//
bool libul_rule::
- match (action a, target& t, const string&) const
+ match (action a, target& t) const
{
fail << diag_doing (a, t) << " target group" <<
info << "explicitly select libua{} or libus{} member" << endf;
@@ -50,7 +50,7 @@ namespace build2
// our prerequisites.
//
bool lib_rule::
- match (action a, target& xt, const string&) const
+ match (action a, target& xt) const
{
lib& t (xt.as<lib> ());
diff --git a/libbuild2/bin/rule.hxx b/libbuild2/bin/rule.hxx
index ffb975d..8bc30c7 100644
--- a/libbuild2/bin/rule.hxx
+++ b/libbuild2/bin/rule.hxx
@@ -24,7 +24,7 @@ namespace build2
obj_rule () {}
virtual bool
- match (action, target&, const string&) const override;
+ match (action, target&) const override;
virtual recipe
apply (action, target&) const override;
@@ -39,7 +39,7 @@ namespace build2
libul_rule () {}
virtual bool
- match (action, target&, const string&) const override;
+ match (action, target&) const override;
virtual recipe
apply (action, target&) const override;
@@ -53,7 +53,7 @@ namespace build2
lib_rule () {}
virtual bool
- match (action, target&, const string&) const override;
+ match (action, target&) const override;
virtual recipe
apply (action, target&) const override;
diff --git a/libbuild2/bin/target.cxx b/libbuild2/bin/target.cxx
index bf701c9..a8d015b 100644
--- a/libbuild2/bin/target.cxx
+++ b/libbuild2/bin/target.cxx
@@ -21,7 +21,7 @@ namespace build2
nullptr,
nullptr,
&target_search,
- false
+ target_type::flag::none
};
const target_type bmix::static_type
@@ -34,7 +34,7 @@ namespace build2
nullptr,
nullptr,
&target_search,
- false
+ target_type::flag::none
};
const target_type hbmix::static_type
@@ -47,7 +47,7 @@ namespace build2
nullptr,
nullptr,
&target_search,
- false
+ target_type::flag::none
};
const target_type libx::static_type
@@ -60,7 +60,7 @@ namespace build2
nullptr,
nullptr,
&target_search,
- false
+ target_type::flag::member_hint, // Use untyped hint for group members.
};
const target_type libux::static_type
@@ -73,7 +73,7 @@ namespace build2
nullptr,
nullptr,
&target_search,
- false
+ target_type::flag::none
};
// Note that we link groups during the load phase since this is often
@@ -108,7 +108,7 @@ namespace build2
&target_pattern_var<nullptr>,
nullptr,
&target_search, // Note: not _file(); don't look for an existing file.
- false
+ target_type::flag::none
};
const target_type bmie::static_type
@@ -121,7 +121,7 @@ namespace build2
&target_pattern_var<nullptr>,
nullptr,
&target_search, // Note: not _file(); don't look for an existing file.
- false
+ target_type::flag::none
};
const target_type hbmie::static_type
@@ -134,7 +134,7 @@ namespace build2
&target_pattern_var<nullptr>,
nullptr,
&target_search, // Note: not _file(); don't look for an existing file.
- false
+ target_type::flag::none
};
const target_type obja::static_type
@@ -147,7 +147,7 @@ namespace build2
&target_pattern_var<nullptr>,
nullptr,
&target_search, // Note: not _file(); don't look for an existing file.
- false
+ target_type::flag::none
};
const target_type bmia::static_type
@@ -160,7 +160,7 @@ namespace build2
&target_pattern_var<nullptr>,
nullptr,
&target_search, // Note: not _file(); don't look for an existing file.
- false
+ target_type::flag::none
};
const target_type hbmia::static_type
@@ -173,7 +173,7 @@ namespace build2
&target_pattern_var<nullptr>,
nullptr,
&target_search, // Note: not _file(); don't look for an existing file.
- false
+ target_type::flag::none
};
const target_type objs::static_type
@@ -186,7 +186,7 @@ namespace build2
&target_pattern_var<nullptr>,
nullptr,
&target_search, // Note: not _file(); don't look for an existing file.
- false
+ target_type::flag::none
};
const target_type bmis::static_type
@@ -199,7 +199,7 @@ namespace build2
&target_pattern_var<nullptr>,
nullptr,
&target_search, // Note: not _file(); don't look for an existing file.
- false
+ target_type::flag::none
};
const target_type hbmis::static_type
@@ -212,7 +212,7 @@ namespace build2
&target_pattern_var<nullptr>,
nullptr,
&target_search, // Note: not _file(); don't look for an existing file.
- false
+ target_type::flag::none
};
const target_type libue::static_type
@@ -225,7 +225,7 @@ namespace build2
&target_pattern_var<nullptr>,
nullptr,
&target_search, // Note: not _file(); don't look for an existing file.
- false
+ target_type::flag::none
};
const target_type libua::static_type
@@ -238,7 +238,7 @@ namespace build2
&target_pattern_var<nullptr>,
nullptr,
&target_search, // Note: not _file(); don't look for an existing file.
- false
+ target_type::flag::none
};
const target_type libus::static_type
@@ -251,7 +251,7 @@ namespace build2
&target_pattern_var<nullptr>,
nullptr,
&target_search, // Note: not _file(); don't look for an existing file.
- false
+ target_type::flag::none
};
// obj{}, [h]bmi{}, and libu{} group factory.
@@ -292,7 +292,7 @@ namespace build2
nullptr,
nullptr,
&target_search,
- false
+ target_type::flag::member_hint, // Use untyped hint for group members.
};
const target_type bmi::static_type
@@ -305,7 +305,7 @@ namespace build2
nullptr,
nullptr,
&target_search,
- false
+ target_type::flag::member_hint, // Use untyped hint for group members.
};
const target_type hbmi::static_type
@@ -318,7 +318,7 @@ namespace build2
nullptr,
nullptr,
&target_search,
- false
+ target_type::flag::member_hint, // Use untyped hint for group members.
};
// The same as g_factory() but without E.
@@ -352,7 +352,7 @@ namespace build2
nullptr,
nullptr,
&target_search,
- false
+ target_type::flag::member_hint, // Use untyped hint for group members.
};
// What extensions should we use? At the outset, this is platform-
@@ -375,7 +375,7 @@ namespace build2
&target_pattern_var<nullptr>,
nullptr,
&file_search,
- false
+ target_type::flag::none
};
const target_type libs::static_type
@@ -388,7 +388,7 @@ namespace build2
&target_pattern_var<nullptr>,
nullptr,
&file_search,
- false
+ target_type::flag::none
};
// lib
@@ -435,7 +435,10 @@ namespace build2
nullptr,
nullptr,
&target_search,
- false // Note: not see-through ("alternatives" group).
+
+ // Note: not see-through ("alternatives" group).
+ //
+ target_type::flag::member_hint, // Use untyped hint for group members.
};
// libi
@@ -450,7 +453,7 @@ namespace build2
&target_pattern_var<nullptr>,
nullptr,
&file_search,
- false
+ target_type::flag::none
};
// def
@@ -467,7 +470,7 @@ namespace build2
&target_pattern_fix<def_ext>,
nullptr,
&file_search,
- false
+ target_type::flag::none
};
}
}
diff --git a/libbuild2/c/init.cxx b/libbuild2/c/init.cxx
index 6725ca7..f39114c 100644
--- a/libbuild2/c/init.cxx
+++ b/libbuild2/c/init.cxx
@@ -352,7 +352,6 @@ namespace build2
"c.compile",
"c.link",
"c.install",
- "c.uninstall",
cm.x_info->id.type,
cm.x_info->id.variant,
diff --git a/libbuild2/cc/common.hxx b/libbuild2/cc/common.hxx
index 56cde19..017573d 100644
--- a/libbuild2/cc/common.hxx
+++ b/libbuild2/cc/common.hxx
@@ -156,10 +156,9 @@ namespace build2
struct data: config_data
{
- const char* x_compile; // Rule names.
- const char* x_link;
- const char* x_install;
- const char* x_uninstall;
+ string x_compile; // Rule names.
+ string x_link;
+ string x_install;
// Cached values for some commonly-used variables/values.
//
@@ -243,7 +242,6 @@ namespace build2
const char* compile,
const char* link,
const char* install,
- const char* uninstall,
compiler_type ct,
const string& cv,
compiler_class cl,
@@ -270,7 +268,6 @@ namespace build2
x_compile (compile),
x_link (link),
x_install (install),
- x_uninstall (uninstall),
ctype (ct), cvariant (cv), cclass (cl),
cmaj (mj), cmin (mi),
cvmaj (vmj), cvmin (vmi),
diff --git a/libbuild2/cc/compile-rule.cxx b/libbuild2/cc/compile-rule.cxx
index e7e90ad..24c9b2b 100644
--- a/libbuild2/cc/compile-rule.cxx
+++ b/libbuild2/cc/compile-rule.cxx
@@ -406,7 +406,7 @@ namespace build2
}
bool compile_rule::
- match (action a, target& t, const string&) const
+ match (action a, target& t) const
{
tracer trace (x, "compile_rule::match");
diff --git a/libbuild2/cc/compile-rule.hxx b/libbuild2/cc/compile-rule.hxx
index dbb2dd5..00965fc 100644
--- a/libbuild2/cc/compile-rule.hxx
+++ b/libbuild2/cc/compile-rule.hxx
@@ -45,7 +45,7 @@ namespace build2
compile_rule (data&&);
virtual bool
- match (action, target&, const string&) const override;
+ match (action, target&) const override;
virtual recipe
apply (action, target&) const override;
diff --git a/libbuild2/cc/install-rule.cxx b/libbuild2/cc/install-rule.cxx
index 560b8a7..e8c87ae 100644
--- a/libbuild2/cc/install-rule.cxx
+++ b/libbuild2/cc/install-rule.cxx
@@ -97,7 +97,7 @@ namespace build2
{
if (header_source (p))
pt = nullptr;
- else if (p.type.see_through)
+ else if (p.type.see_through ())
{
for (i.enter_group (); i.group (); )
{
@@ -151,15 +151,13 @@ namespace build2
}
bool install_rule::
- match (action a, target& t, const string& hint) const
+ match (action a, target& t, const string&, match_extra& me) const
{
- // @@ How do we split the hint between the two?
- //
-
// We only want to handle installation if we are also the ones building
// this target. So first run link's match().
//
- return link_.match (a, t, hint) && file_rule::match (a, t, "");
+ return link_.sub_match (x_link, update_id, a, t, me) &&
+ file_rule::match (a, t);
}
recipe install_rule::
@@ -332,7 +330,7 @@ namespace build2
{
if (header_source (p))
pt = nullptr;
- else if (p.type.see_through)
+ else if (p.type.see_through ())
{
for (i.enter_group (); i.group (); )
{
@@ -372,12 +370,13 @@ namespace build2
}
bool libux_install_rule::
- match (action a, target& t, const string& hint) const
+ match (action a, target& t, const string&, match_extra& me) const
{
// We only want to handle installation if we are also the ones building
// this target. So first run link's match().
//
- return link_.match (a, t, hint) && alias_rule::match (a, t, "");
+ return link_.sub_match (x_link, update_id, a, t, me) &&
+ alias_rule::match (a, t);
}
}
}
diff --git a/libbuild2/cc/install-rule.hxx b/libbuild2/cc/install-rule.hxx
index acd1bd8..70ee711 100644
--- a/libbuild2/cc/install-rule.hxx
+++ b/libbuild2/cc/install-rule.hxx
@@ -38,8 +38,10 @@ namespace build2
filter (const scope*,
action, const target&, prerequisite_iterator&) const override;
+ // Note: rule::match() override.
+ //
virtual bool
- match (action, target&, const string&) const override;
+ match (action, target&, const string&, match_extra&) const override;
virtual recipe
apply (action, target&) const override;
@@ -71,8 +73,10 @@ namespace build2
filter (const scope*,
action, const target&, prerequisite_iterator&) const override;
+ // Note: rule::match() override.
+ //
virtual bool
- match (action, target&, const string&) const override;
+ match (action, target&, const string&, match_extra&) const override;
private:
const link_rule& link_;
diff --git a/libbuild2/cc/link-rule.cxx b/libbuild2/cc/link-rule.cxx
index b5cc63b..30024ce 100644
--- a/libbuild2/cc/link-rule.cxx
+++ b/libbuild2/cc/link-rule.cxx
@@ -446,7 +446,7 @@ namespace build2
}
bool link_rule::
- match (action a, target& t, const string& hint) const
+ match (action a, target& t, const string& hint, match_extra&) const
{
// NOTE: may be called multiple times and for both inner and outer
// operations (see the install rules).
@@ -495,7 +495,7 @@ namespace build2
// We will only chain a C source if there is also an X source or we were
// explicitly told to.
//
- if (r.seen_c && !r.seen_x && hint < x)
+ if (r.seen_c && !r.seen_x && hint.empty ())
{
l4 ([&]{trace << "C prerequisite without " << x_lang << " or hint "
<< "for target " << t;});
@@ -850,7 +850,7 @@ namespace build2
};
recipe link_rule::
- apply (action a, target& xt) const
+ apply (action a, target& xt, match_extra&) const
{
tracer trace (x, "link_rule::apply");
diff --git a/libbuild2/cc/link-rule.hxx b/libbuild2/cc/link-rule.hxx
index c6d06d2..f0052e9 100644
--- a/libbuild2/cc/link-rule.hxx
+++ b/libbuild2/cc/link-rule.hxx
@@ -18,7 +18,7 @@ namespace build2
{
namespace cc
{
- class LIBBUILD2_CC_SYMEXPORT link_rule: public simple_rule, virtual common
+ class LIBBUILD2_CC_SYMEXPORT link_rule: public rule, virtual common
{
public:
link_rule (data&&);
@@ -46,10 +46,10 @@ namespace build2
match (action, const target&, const target*, otype, bool) const;
virtual bool
- match (action, target&, const string&) const override;
+ match (action, target&, const string&, match_extra&) const override;
virtual recipe
- apply (action, target&) const override;
+ apply (action, target&, match_extra&) const override;
target_state
perform_update (action, const target&) const;
@@ -57,8 +57,6 @@ namespace build2
target_state
perform_clean (action, const target&) const;
- using simple_rule::match; // To make Clang happy.
-
public:
// Library handling.
//
diff --git a/libbuild2/cc/module.cxx b/libbuild2/cc/module.cxx
index 871cfb6..c930d49 100644
--- a/libbuild2/cc/module.cxx
+++ b/libbuild2/cc/module.cxx
@@ -1083,30 +1083,30 @@ namespace build2
{
const install_rule& ir (*this);
- r.insert<exe> (perform_install_id, x_install, ir);
- r.insert<exe> (perform_uninstall_id, x_uninstall, ir);
+ r.insert<exe> (perform_install_id, x_install, ir);
+ r.insert<exe> (perform_uninstall_id, x_install, ir);
- r.insert<liba> (perform_install_id, x_install, ir);
- r.insert<liba> (perform_uninstall_id, x_uninstall, ir);
+ r.insert<liba> (perform_install_id, x_install, ir);
+ r.insert<liba> (perform_uninstall_id, x_install, ir);
if (s)
{
- r.insert<libs> (perform_install_id, x_install, ir);
- r.insert<libs> (perform_uninstall_id, x_uninstall, ir);
+ r.insert<libs> (perform_install_id, x_install, ir);
+ r.insert<libs> (perform_uninstall_id, x_install, ir);
}
const libux_install_rule& lr (*this);
- r.insert<libue> (perform_install_id, x_install, lr);
- r.insert<libue> (perform_uninstall_id, x_uninstall, lr);
+ r.insert<libue> (perform_install_id, x_install, lr);
+ r.insert<libue> (perform_uninstall_id, x_install, lr);
- r.insert<libua> (perform_install_id, x_install, lr);
- r.insert<libua> (perform_uninstall_id, x_uninstall, lr);
+ r.insert<libua> (perform_install_id, x_install, lr);
+ r.insert<libua> (perform_uninstall_id, x_install, lr);
if (s)
{
- r.insert<libus> (perform_install_id, x_install, lr);
- r.insert<libus> (perform_uninstall_id, x_uninstall, lr);
+ r.insert<libus> (perform_install_id, x_install, lr);
+ r.insert<libus> (perform_uninstall_id, x_install, lr);
}
}
}
diff --git a/libbuild2/cc/target.cxx b/libbuild2/cc/target.cxx
index b17e1ef..3f71eb1 100644
--- a/libbuild2/cc/target.cxx
+++ b/libbuild2/cc/target.cxx
@@ -21,7 +21,7 @@ namespace build2
nullptr,
nullptr,
&target_search,
- false
+ target_type::flag::none
};
extern const char h_ext_def[] = "h";
@@ -36,7 +36,7 @@ namespace build2
&target_pattern_var<h_ext_def>,
nullptr,
&file_search,
- false
+ target_type::flag::none
};
extern const char c_ext_def[] = "c";
@@ -51,7 +51,7 @@ namespace build2
&target_pattern_var<c_ext_def>,
nullptr,
&file_search,
- false
+ target_type::flag::none
};
extern const char pc_ext[] = "pc"; // VC14 rejects constexpr.
@@ -66,7 +66,7 @@ namespace build2
&target_pattern_fix<pc_ext>,
&target_print_0_ext_verb, // Fixed extension, no use printing.
&file_search,
- false
+ target_type::flag::none
};
extern const char pca_ext[] = "static.pc"; // VC14 rejects constexpr.
@@ -81,7 +81,7 @@ namespace build2
&target_pattern_fix<pca_ext>,
&target_print_0_ext_verb, // Fixed extension, no use printing.
&file_search,
- false
+ target_type::flag::none
};
extern const char pcs_ext[] = "shared.pc"; // VC14 rejects constexpr.
@@ -96,7 +96,7 @@ namespace build2
&target_pattern_fix<pcs_ext>,
&target_print_0_ext_verb, // Fixed extension, no use printing.
&file_search,
- false
+ target_type::flag::none
};
}
}
diff --git a/libbuild2/config/init.cxx b/libbuild2/config/init.cxx
index 5dd2789..774ffb8 100644
--- a/libbuild2/config/init.cxx
+++ b/libbuild2/config/init.cxx
@@ -571,13 +571,12 @@ namespace build2
rs.global_scope ().insert_rule<mtime_target> (
configure_id, 0, "config.file", file_rule::instance);
- //@@ outer
rs.insert_rule<alias> (configure_id, 0, "config.alias", alias_rule::instance);
// This allows a custom configure rule while doing nothing by default.
//
- rs.insert_rule<target> (configure_id, 0, "config", noop_rule::instance);
- rs.insert_rule<file> (configure_id, 0, "config.file", noop_rule::instance);
+ rs.insert_rule<target> (configure_id, 0, "config.noop", noop_rule::instance);
+ rs.insert_rule<file> (configure_id, 0, "config.noop", noop_rule::instance);
return true;
}
diff --git a/libbuild2/context.cxx b/libbuild2/context.cxx
index a052481..80343bd 100644
--- a/libbuild2/context.cxx
+++ b/libbuild2/context.cxx
@@ -601,14 +601,13 @@ namespace build2
{
rule_map& r (gs.rules); // Note: global scope!
- //@@ outer
- r.insert<alias> (perform_id, 0, "alias", alias_rule::instance);
+ r.insert<alias> (perform_id, 0, "build.alias", alias_rule::instance);
- r.insert<fsdir> (perform_update_id, "fsdir", fsdir_rule::instance);
- r.insert<fsdir> (perform_clean_id, "fsdir", fsdir_rule::instance);
+ r.insert<fsdir> (perform_update_id, "build.fsdir", fsdir_rule::instance);
+ r.insert<fsdir> (perform_clean_id, "build.fsdir", fsdir_rule::instance);
- r.insert<mtime_target> (perform_update_id, "file", file_rule::instance);
- r.insert<mtime_target> (perform_clean_id, "file", file_rule::instance);
+ r.insert<mtime_target> (perform_update_id, "build.file", file_rule::instance);
+ r.insert<mtime_target> (perform_clean_id, "build.file", file_rule::instance);
}
}
diff --git a/libbuild2/cxx/init.cxx b/libbuild2/cxx/init.cxx
index 106668a..0ebb424 100644
--- a/libbuild2/cxx/init.cxx
+++ b/libbuild2/cxx/init.cxx
@@ -829,7 +829,6 @@ namespace build2
"cxx.compile",
"cxx.link",
"cxx.install",
- "cxx.uninstall",
cm.x_info->id.type,
cm.x_info->id.variant,
diff --git a/libbuild2/cxx/target.cxx b/libbuild2/cxx/target.cxx
index 982dcb4..fc50f67 100644
--- a/libbuild2/cxx/target.cxx
+++ b/libbuild2/cxx/target.cxx
@@ -22,7 +22,7 @@ namespace build2
&target_pattern_var<hxx_ext_def>,
nullptr,
&file_search,
- false
+ target_type::flag::none
};
extern const char ixx_ext_def[] = "ixx";
@@ -36,7 +36,7 @@ namespace build2
&target_pattern_var<ixx_ext_def>,
nullptr,
&file_search,
- false
+ target_type::flag::none
};
extern const char txx_ext_def[] = "txx";
@@ -50,7 +50,7 @@ namespace build2
&target_pattern_var<txx_ext_def>,
nullptr,
&file_search,
- false
+ target_type::flag::none
};
extern const char cxx_ext_def[] = "cxx";
@@ -64,7 +64,7 @@ namespace build2
&target_pattern_var<cxx_ext_def>,
nullptr,
&file_search,
- false
+ target_type::flag::none
};
extern const char mxx_ext_def[] = "mxx";
@@ -78,7 +78,7 @@ namespace build2
&target_pattern_var<mxx_ext_def>,
nullptr,
&file_search,
- false
+ target_type::flag::none
};
}
}
diff --git a/libbuild2/dist/init.cxx b/libbuild2/dist/init.cxx
index 2be4c3f..8837f77 100644
--- a/libbuild2/dist/init.cxx
+++ b/libbuild2/dist/init.cxx
@@ -188,7 +188,7 @@ namespace build2
// something like insert<target>(dist_id, test_id) taking precedence.
//
rs.insert_rule<target> (dist_id, 0, "dist", rule_);
- rs.insert_rule<alias> (dist_id, 0, "dist.alias", rule_); //@@ outer?
+ rs.insert_rule<alias> (dist_id, 0, "dist.alias", rule_);
// Configuration.
//
diff --git a/libbuild2/dist/rule.cxx b/libbuild2/dist/rule.cxx
index ef144d0..76d11c9 100644
--- a/libbuild2/dist/rule.cxx
+++ b/libbuild2/dist/rule.cxx
@@ -15,7 +15,7 @@ namespace build2
namespace dist
{
bool rule::
- match (action, target&, const string&) const
+ match (action, target&) const
{
return true; // We always match.
}
diff --git a/libbuild2/dist/rule.hxx b/libbuild2/dist/rule.hxx
index e63016d..a864015 100644
--- a/libbuild2/dist/rule.hxx
+++ b/libbuild2/dist/rule.hxx
@@ -29,7 +29,7 @@ namespace build2
rule () {}
virtual bool
- match (action, target&, const string&) const override;
+ match (action, target&) const override;
virtual recipe
apply (action, target&) const override;
diff --git a/libbuild2/dump.cxx b/libbuild2/dump.cxx
index b1a16ba..befd86b 100644
--- a/libbuild2/dump.cxx
+++ b/libbuild2/dump.cxx
@@ -259,7 +259,38 @@ namespace build2
if (t.group != nullptr)
os << ind << t << " -> " << *t.group << endl;
- os << ind << t << ':';
+ os << ind;
+
+ // Target attributes.
+ //
+ if (!t.rule_hints.map.empty ())
+ {
+ os << '[';
+
+ bool f (true);
+ for (const rule_hints::value_type& v: t.rule_hints.map)
+ {
+ if (f)
+ f = false;
+ else
+ os << ", ";
+
+ if (v.type != nullptr)
+ os << v.type->name << '@';
+
+ os << "rule_hint=";
+
+ if (v.operation != default_id)
+ os << s.root_scope ()->root_extra->operations[v.operation]->name
+ << '@';
+
+ os << v.hint;
+ }
+
+ os << "] ";
+ }
+
+ os << t << ':';
// First check if this is the simple case where we can print everything
// as a single declaration.
diff --git a/libbuild2/in/rule.cxx b/libbuild2/in/rule.cxx
index dd39485..5a6db30 100644
--- a/libbuild2/in/rule.cxx
+++ b/libbuild2/in/rule.cxx
@@ -23,7 +23,7 @@ namespace build2
namespace in
{
bool rule::
- match (action a, target& xt, const string&) const
+ match (action a, target& xt) const
{
tracer trace ("in::rule::match");
diff --git a/libbuild2/in/rule.hxx b/libbuild2/in/rule.hxx
index 33caea4..98ab3b4 100644
--- a/libbuild2/in/rule.hxx
+++ b/libbuild2/in/rule.hxx
@@ -43,7 +43,7 @@ namespace build2
null_ (move (null)) {}
virtual bool
- match (action, target&, const string&) const override;
+ match (action, target&) const override;
virtual recipe
apply (action, target&) const override;
diff --git a/libbuild2/in/target.cxx b/libbuild2/in/target.cxx
index d9bc8a7..d548453 100644
--- a/libbuild2/in/target.cxx
+++ b/libbuild2/in/target.cxx
@@ -53,7 +53,7 @@ namespace build2
&in_pattern,
&target_print_1_ext_verb, // Same as file.
&in_search,
- false
+ target_type::flag::none
};
}
}
diff --git a/libbuild2/install/init.cxx b/libbuild2/install/init.cxx
index 1bf1623..ef9de05 100644
--- a/libbuild2/install/init.cxx
+++ b/libbuild2/install/init.cxx
@@ -372,19 +372,19 @@ namespace build2
const auto& gr (group_rule_);
bs.insert_rule<alias> (perform_install_id, "install.alias", ar);
- bs.insert_rule<alias> (perform_uninstall_id, "uninstall.alias", ar);
+ bs.insert_rule<alias> (perform_uninstall_id, "install.alias", ar);
bs.insert_rule<fsdir> (perform_install_id, "install.fsdir", dr);
bs.insert_rule<fsdir> (perform_uninstall_id, "install.fsdir", dr);
bs.insert_rule<file> (perform_install_id, "install.file", fr);
- bs.insert_rule<file> (perform_uninstall_id, "uninstall.file", fr);
+ bs.insert_rule<file> (perform_uninstall_id, "install.file", fr);
// Note: use mtime_target (instead of target) to take precedence over
// the fallback file rules below.
//
bs.insert_rule<mtime_target> (perform_install_id, "install.group", gr);
- bs.insert_rule<mtime_target> (perform_uninstall_id, "uninstall.group", gr);
+ bs.insert_rule<mtime_target> (perform_uninstall_id, "install.group", gr);
// Register the fallback file rule for the update-for-[un]install
// operation, similar to update.
@@ -392,11 +392,10 @@ namespace build2
// @@ Hm, it's a bit fuzzy why we would be updating-for-install
// something outside of any project..?
//
- rs.global_scope ().insert_rule<mtime_target> (
- perform_install_id, "install.file", fr);
+ scope& gs (rs.global_scope ());
- rs.global_scope ().insert_rule<mtime_target> (
- perform_uninstall_id, "uninstall.file", fr);
+ gs.insert_rule<mtime_target> (perform_install_id, "install.file", fr);
+ gs.insert_rule<mtime_target> (perform_uninstall_id, "install.file", fr);
}
// Configuration.
diff --git a/libbuild2/install/rule.cxx b/libbuild2/install/rule.cxx
index 468fcc3..0a1b994 100644
--- a/libbuild2/install/rule.cxx
+++ b/libbuild2/install/rule.cxx
@@ -53,7 +53,7 @@ namespace build2
const alias_rule alias_rule::instance;
bool alias_rule::
- match (action, target&, const string&) const
+ match (action, target&) const
{
// We always match.
//
@@ -168,7 +168,7 @@ namespace build2
const fsdir_rule fsdir_rule::instance;
bool fsdir_rule::
- match (action, target&, const string&) const
+ match (action, target&) const
{
// We always match.
//
@@ -203,10 +203,10 @@ namespace build2
const group_rule group_rule::instance (false /* see_through_only */);
bool group_rule::
- match (action a, target& t, const string& h) const
+ match (action a, target& t) const
{
- return (!see_through || t.type ().see_through) &&
- alias_rule::match (a, t, h);
+ return (!see_through_only || t.type ().see_through ()) &&
+ alias_rule::match (a, t);
}
const target* group_rule::
@@ -300,7 +300,7 @@ namespace build2
const file_rule file_rule::instance;
bool file_rule::
- match (action, target&, const string&) const
+ match (action, target&) const
{
// We always match, even if this target is not installable (so that we
// can ignore it; see apply()).
diff --git a/libbuild2/install/rule.hxx b/libbuild2/install/rule.hxx
index 79cef85..ad9d6e7 100644
--- a/libbuild2/install/rule.hxx
+++ b/libbuild2/install/rule.hxx
@@ -22,7 +22,7 @@ namespace build2
{
public:
virtual bool
- match (action, target&, const string&) const override;
+ match (action, target&) const override;
// Return NULL if this prerequisite should be ignored and pointer to its
// target otherwise.
@@ -54,7 +54,7 @@ namespace build2
{
public:
virtual bool
- match (action, target&, const string&) const override;
+ match (action, target&) const override;
virtual recipe
apply (action, target&) const override;
@@ -78,7 +78,7 @@ namespace build2
{
public:
virtual bool
- match (action, target&, const string&) const override;
+ match (action, target&) const override;
// Return NULL if this group member should be ignored and pointer to its
// target otherwise.
@@ -103,10 +103,10 @@ namespace build2
virtual recipe
apply (action, target&) const override;
- group_rule (bool see_through_only): see_through (see_through_only) {}
+ group_rule (bool sto): see_through_only (sto) {}
static const group_rule instance;
- bool see_through;
+ bool see_through_only;
};
struct install_dir;
@@ -115,7 +115,7 @@ namespace build2
{
public:
virtual bool
- match (action, target&, const string&) const override;
+ match (action, target&) const override;
// Return NULL if this prerequisite should be ignored and pointer to its
// target otherwise.
diff --git a/libbuild2/parser.cxx b/libbuild2/parser.cxx
index 1e8757a..f91e85e 100644
--- a/libbuild2/parser.cxx
+++ b/libbuild2/parser.cxx
@@ -674,10 +674,7 @@ namespace build2
if (ns.empty ())
fail (t) << "expected target before ':'";
- if (at.first)
- fail (at.second) << "attributes before target";
- else
- attributes_pop ();
+ attributes as (attributes_pop ());
// Call the specified parsing function (variable value/block) for
// one/each pattern/target. We handle multiple targets by replaying
@@ -790,7 +787,7 @@ namespace build2
};
auto for_each = [this, &trace, &for_one_pat,
- &t, &tt, &ns, &nloc, &ans] (auto&& f)
+ &t, &tt, &as, &ns, &nloc, &ans] (auto&& f)
{
// Note: watch out for an out-qualified single target (two names).
//
@@ -809,6 +806,9 @@ namespace build2
//
if (n.pattern)
{
+ if (!as.empty ())
+ fail (as.loc) << "attributes before target type/pattern";
+
if (n.pair)
fail (nloc) << "out-qualified target type/pattern";
@@ -831,6 +831,9 @@ namespace build2
nloc,
trace);
+ if (!as.empty ())
+ apply_target_attributes (*target_, as);
+
// Enter ad hoc members.
//
if (!ans.empty ())
@@ -865,6 +868,9 @@ namespace build2
//
if (ns[0].pattern && ns.size () == (ns[0].pair ? 2 : 1))
{
+ if (!as.empty ())
+ fail (as.loc) << "attributes before target type/pattern";
+
name& n (ns[0]);
if (n.qualified ())
@@ -1165,7 +1171,7 @@ namespace build2
for (action a: r.actions)
{
- // This covers both duplicate recipe actions withing the rule
+ // This covers both duplicate recipe actions within the rule
// pattern (similar to parse_recipe()) as well as conflicts
// with other rules (ad hoc or not).
//
@@ -1313,7 +1319,7 @@ namespace build2
// Note also that we treat this as an explicit dependency
// declaration (i.e., not implied).
//
- enter_targets (move (ns), nloc, move (ans), 0);
+ enter_targets (move (ns), nloc, move (ans), 0, as);
}
continue;
@@ -1390,7 +1396,8 @@ namespace build2
parse_dependency (t, tt,
move (ns), nloc,
move (ans),
- move (pns), ploc);
+ move (pns), ploc,
+ as);
}
continue;
@@ -1943,8 +1950,7 @@ namespace build2
//
// TODO: handle and erase common attributes if/when we have any.
//
- as = move (attributes_top ());
- attributes_pop ();
+ as = attributes_pop ();
// Handle the buildspec.
//
@@ -2134,7 +2140,8 @@ namespace build2
small_vector<reference_wrapper<target>, 1> parser::
enter_targets (names&& tns, const location& tloc, // Target names.
adhoc_names&& ans, // Ad hoc target names.
- size_t prereq_size)
+ size_t prereq_size,
+ const attributes& tas) // Target attributes.
{
// Enter all the targets (normally we will have just one) and their ad hoc
// groups.
@@ -2163,6 +2170,9 @@ namespace build2
false /* implied */,
tloc, trace);
+ if (!tas.empty ())
+ apply_target_attributes (*target_, tas);
+
// Enter ad hoc members.
//
if (!ans.empty ())
@@ -2184,10 +2194,90 @@ namespace build2
}
void parser::
+ apply_target_attributes (target& t, const attributes& as)
+ {
+ const location& l (as.loc);
+
+ for (auto& a: as)
+ {
+ const string& n (a.name);
+ const value& v (a.value);
+
+ // rule_hint=
+ // liba@rule_hint=
+ //
+ size_t p (string::npos);
+ if (n == "rule_hint" ||
+ ((p = n.find ('@')) != string::npos &&
+ n.compare (p + 1, string::npos, "rule_hint") == 0))
+ {
+ // Resolve target type, if specified.
+ //
+ const target_type* tt (nullptr);
+ if (p != string::npos)
+ {
+ string t (n, 0, p);
+ tt = scope_->find_target_type (t);
+
+ if (tt == nullptr)
+ fail (l) << "unknown target type " << t << " in rule_hint "
+ << "attribute";
+ }
+
+ // The rule hint value is vector<pair<optional<string>, string>> where
+ // the first half is the operation and the second half is the hint.
+ // Absent operation is used as a fallback for update/clean.
+ //
+ const names& ns (v.as<names> ());
+
+ for (auto i (ns.begin ()); i != ns.end (); ++i)
+ {
+ operation_id oi (default_id);
+ if (i->pair)
+ {
+ const name& n (*i++);
+
+ if (!n.simple ())
+ fail (l) << "expected operation name instead of " << n
+ << " in rule_hint attribute";
+
+ const string& v (n.value);
+
+ if (!v.empty ())
+ {
+ oi = ctx.operation_table.find (v);
+
+ if (oi == 0)
+ fail (l) << "unknown operation " << v << " in rule_hint "
+ << "attribute";
+
+ if (root_->root_extra->operations[oi] == nullptr)
+ fail (l) << "project " << *root_ << " does not support "
+ << "operation " << ctx.operation_table[oi]
+ << " specified in rule_hint attribute";
+ }
+ }
+
+ const name& n (*i);
+
+ if (!n.simple () || n.empty ())
+ fail (l) << "expected hint instead of " << n << " in rule_hint "
+ << "attribute";
+
+ t.rule_hints.insert (tt, oi, n.value);
+ }
+ }
+ else
+ fail (l) << "unknown target attribute " << a;
+ }
+ }
+
+ void parser::
parse_dependency (token& t, token_type& tt,
names&& tns, const location& tloc, // Target names.
adhoc_names&& ans, // Ad hoc target names.
- names&& pns, const location& ploc) // Prereq names.
+ names&& pns, const location& ploc, // Prereq names.
+ const attributes& tas) // Target attributes.
{
// Parse a dependency chain and/or a target/prerequisite-specific variable
// assignment/block and/or recipe block(s).
@@ -2200,7 +2290,7 @@ namespace build2
// First enter all the targets.
//
small_vector<reference_wrapper<target>, 1> tgs (
- enter_targets (move (tns), tloc, move (ans), pns.size ()));
+ enter_targets (move (tns), tloc, move (ans), pns.size (), tas));
// Now enter each prerequisite into each target.
//
@@ -2463,6 +2553,10 @@ namespace build2
//
else
{
+ // @@ This is actually ambiguous: prerequisite or target attributes
+ // (or both or neither)? Perhaps this should be prerequisites for
+ // the same reason as below (these are prerequsites first).
+ //
if (at.first)
fail (at.second) << "attributes before prerequisites";
else
@@ -2484,7 +2578,8 @@ namespace build2
parse_dependency (t, tt,
move (pns), ploc,
{} /* ad hoc target name */,
- move (ns), loc);
+ move (ns), loc,
+ attributes () /* target attributes */);
}
}
}
@@ -5144,6 +5239,10 @@ namespace build2
// Parse the attribute name with expansion (we rely on this in some
// old and hairy tests).
//
+ // Note that the attributes lexer mode does not recognize `{}@` as
+ // special and we rely on that in the rule hint attributes
+ // (libs@rule_hint=cxx).
+ //
const location l (get_location (t));
names ns (
@@ -5185,6 +5284,8 @@ namespace build2
}
while (tt != type::rsbrace);
}
+ else
+ has = false; // `[]` doesn't count.
if (tt != type::rsbrace)
fail (t) << "expected ']' instead of " << t;
diff --git a/libbuild2/parser.hxx b/libbuild2/parser.hxx
index 1474c5e..4f105e5 100644
--- a/libbuild2/parser.hxx
+++ b/libbuild2/parser.hxx
@@ -162,13 +162,20 @@ namespace build2
enter_adhoc_members (adhoc_names_loc&&, bool);
small_vector<reference_wrapper<target>, 1>
- enter_targets (names&&, const location&, adhoc_names&&, size_t);
+ enter_targets (names&&, const location&,
+ adhoc_names&&,
+ size_t,
+ const attributes&);
+
+ void
+ apply_target_attributes (target&, const attributes&);
void
parse_dependency (token&, token_type&,
names&&, const location&,
adhoc_names&&,
- names&&, const location&);
+ names&&, const location&,
+ const attributes&);
void
parse_assert (token&, token_type&);
@@ -305,8 +312,8 @@ namespace build2
// then parse the attribute sequence until ']' storing the result in the
// new stack entry. Then get the next token and, if standalone is false,
// verify it is not newline/eos (i.e., there is something after it).
- // Return the indication of whether we have seen `[` (even if it's the
- // `[]` empty list) and its location.
+ // Return the indication of whether we have seen any attributes (note
+ // that the `[]` empty list does not count) and the location of `[`.
//
// Note that during pre-parsing nothing is pushed into the stack.
//
diff --git a/libbuild2/rule-map.hxx b/libbuild2/rule-map.hxx
index d4a0f33..8f6f59f 100644
--- a/libbuild2/rule-map.hxx
+++ b/libbuild2/rule-map.hxx
@@ -14,10 +14,38 @@
namespace build2
{
- using hint_rule_map =
- butl::prefix_map<string, reference_wrapper<const rule>, '.'>;
+ // A rule name is used both for diagnostics as well as to match rule hints
+ // (see rule_hints). A rule hint is a potentially partial rule name.
+ //
+ // The recommended rule naming scheme is to start with the module name, for
+ // example: cxx.compile, cxx.link. This way a rule hint can be just the
+ // module name, for example [rule_hint=cxx]. If a module can only possibly
+ // have a single rule, then the rule name can be just the module name (e.g.,
+ // `in`; though make doubly sure there is unlikely to be a need for another
+ // rule, for example, for documentation generation, in the future).
+ //
+ // The two common choices of names for the second component in a rule name
+ // is an action (e.g., cxx.compile, cxx.link) or a target type (e.g.,
+ // bin.def, bin.lib). The latter is a good choice when the action is
+ // inherent to the target type (e.g., "generate def file", "see through lib
+ // group"). Also note that a rule for compensating operations (e.g.,
+ // update/clean, install/uninstall) is customarily registered with the same
+ // name.
+ //
+ struct name_rule_map: butl::prefix_map<string,
+ reference_wrapper<const rule>,
+ '.'>
+ {
+ // Return true if the rule name matches a rule hint.
+ //
+ static bool
+ sub (const string& hint, const string& name)
+ {
+ return compare_type ('.').prefix (hint, name);
+ }
+ };
- using target_type_rule_map = map<const target_type*, hint_rule_map>;
+ using target_type_rule_map = map<const target_type*, name_rule_map>;
// This is an "indexed map" with operation_id being the index. Entry
// with id 0 is a wildcard.
@@ -33,7 +61,7 @@ namespace build2
bool
insert (operation_id oid,
const target_type& tt,
- string hint,
+ string name,
const rule& r)
{
// 3 is the number of builtin operations.
@@ -41,7 +69,7 @@ namespace build2
if (oid >= map_.size ())
map_.resize ((oid < 3 ? 3 : oid) + 1);
- return map_[oid][&tt].emplace (move (hint), r).second;
+ return map_[oid][&tt].emplace (move (name), r).second;
}
// Return NULL if not found.
@@ -78,17 +106,17 @@ namespace build2
bool
insert (action_id a,
const target_type& tt,
- string hint,
+ string name,
const rule& r)
{
- return insert (a >> 4, a & 0x0F, tt, move (hint), r);
+ return insert (a >> 4, a & 0x0F, tt, move (name), r);
}
template <typename T>
bool
- insert (action_id a, string hint, const rule& r)
+ insert (action_id a, string name, const rule& r)
{
- return insert (a, T::static_type, move (hint), r);
+ return insert (a, T::static_type, move (name), r);
}
// 0 oid is a wildcard.
@@ -97,17 +125,17 @@ namespace build2
insert (meta_operation_id mid,
operation_id oid,
const target_type& tt,
- string hint,
+ string name,
const rule& r)
{
if (mid_ == mid)
- return map_.insert (oid, tt, move (hint), r);
+ return map_.insert (oid, tt, move (name), r);
else
{
if (next_ == nullptr)
next_.reset (new rule_map (mid));
- return next_->insert (mid, oid, tt, move (hint), r);
+ return next_->insert (mid, oid, tt, move (name), r);
}
}
@@ -115,10 +143,10 @@ namespace build2
bool
insert (meta_operation_id mid,
operation_id oid,
- string hint,
+ string name,
const rule& r)
{
- return insert (mid, oid, T::static_type, move (hint), r);
+ return insert (mid, oid, T::static_type, move (name), r);
}
// Return NULL if not found.
diff --git a/libbuild2/rule.cxx b/libbuild2/rule.cxx
index c573339..acb46e8 100644
--- a/libbuild2/rule.cxx
+++ b/libbuild2/rule.cxx
@@ -22,12 +22,20 @@ namespace build2
{
}
+ bool rule::
+ sub_match (const string& n, operation_id o,
+ action a, target& t, match_extra& me) const
+ {
+ const string& h (t.find_hint (o));
+ return name_rule_map::sub (h, n) && match (a, t, h, me);
+ }
+
// simple_rule
//
bool simple_rule::
- match (action a, target& t, const string& h, match_extra&) const
+ match (action a, target& t, const string&, match_extra&) const
{
- return match (a, t, h);
+ return match (a, t);
}
recipe simple_rule::
@@ -36,6 +44,13 @@ namespace build2
return apply (a, t);
}
+ bool simple_rule::
+ sub_match (const string& n, operation_id o,
+ action a, target& t) const
+ {
+ return name_rule_map::sub (t.find_hint (o), n) && match (a, t);
+ }
+
// file_rule
//
// Note that this rule is special. It is the last, fallback rule. If
@@ -46,7 +61,7 @@ namespace build2
// use it as a guide to implement your own, normal, rules.
//
bool file_rule::
- match (action a, target& t, const string&) const
+ match (action a, target& t, const string&, match_extra&) const
{
tracer trace ("file_rule::match");
@@ -124,7 +139,7 @@ namespace build2
}
recipe file_rule::
- apply (action a, target& t) const
+ apply (action a, target& t, match_extra&) const
{
// Update triggers the update of this target's prerequisites so it would
// seem natural that we should also trigger their cleanup. However, this
@@ -161,7 +176,7 @@ namespace build2
// alias_rule
//
bool alias_rule::
- match (action, target&, const string&) const
+ match (action, target&) const
{
return true;
}
@@ -183,7 +198,7 @@ namespace build2
// fsdir_rule
//
bool fsdir_rule::
- match (action, target&, const string&) const
+ match (action, target&) const
{
return true;
}
@@ -318,7 +333,7 @@ namespace build2
// noop_rule
//
bool noop_rule::
- match (action, target&, const string&) const
+ match (action, target&) const
{
return true;
}
diff --git a/libbuild2/rule.hxx b/libbuild2/rule.hxx
index 73492fe..1429ab2 100644
--- a/libbuild2/rule.hxx
+++ b/libbuild2/rule.hxx
@@ -24,6 +24,10 @@ namespace build2
//
// Note: match() is only called once but may not be followed by apply().
//
+ // The hint argument is the rule hint, if any, that was used to select this
+ // rule. While normally not factored into the match decision, a rule may
+ // "try harder" if a hint was specified (see cc::link_rule for an example).
+ //
// The match_extra argument (the type is defined in target.hxx) is used to
// pass additional information that is only needed by some rule
// implementations. It is also a way for us to later pass more information
@@ -47,15 +51,29 @@ namespace build2
rule (const rule&) = delete;
rule& operator= (const rule&) = delete;
+
+ // Sometimes we want to match only if another rule of ours would match
+ // another operation. For example, we would want our install rule to match
+ // only if our update rule also matches.
+ //
+ // Arranging this, however, is not a simple matter of calling the other
+ // rule's match(): we also have to take into account the rule hints for
+ // that operation. This helper performs all the necessary steps. Note:
+ // should only be called from match() (see target::find_hint() for
+ // details).
+ //
+ bool
+ sub_match (const string& rule_name, operation_id hint_op,
+ action, target&, match_extra&) const;
};
- // Simplified interface for rules that don't care about the extras.
+ // Simplified interface for rules that don't care about the hint or extras.
//
class LIBBUILD2_SYMEXPORT simple_rule: public rule
{
public:
virtual bool
- match (action, target&, const string& hint) const = 0;
+ match (action, target&) const = 0;
virtual recipe
apply (action, target&) const = 0;
@@ -65,19 +83,31 @@ namespace build2
virtual recipe
apply (action, target&, match_extra&) const override;
+
+ // The simplified version of sub_match() above.
+ //
+ // Note that it calls the simplified match() directly rather than going
+ // through the original.
+ //
+ bool
+ sub_match (const string& rule_name, operation_id hint_op,
+ action, target&) const;
};
// Fallback rule that only matches if the file exists. It will also match
// an mtime_target provided it has a set timestamp.
//
- class LIBBUILD2_SYMEXPORT file_rule: public simple_rule
+ // Note: this rule is "hot" because it matches every static source file and
+ // so we don't use simple_rule to avoid two extra virtual calls.
+ //
+ class LIBBUILD2_SYMEXPORT file_rule: public rule
{
public:
virtual bool
- match (action, target&, const string&) const override;
+ match (action, target&, const string&, match_extra&) const override;
virtual recipe
- apply (action, target&) const override;
+ apply (action, target&, match_extra&) const override;
file_rule () {}
@@ -89,7 +119,7 @@ namespace build2
{
public:
virtual bool
- match (action, target&, const string&) const override;
+ match (action, target&) const override;
virtual recipe
apply (action, target&) const override;
@@ -105,7 +135,7 @@ namespace build2
{
public:
virtual bool
- match (action, target&, const string&) const override;
+ match (action, target&) const override;
virtual recipe
apply (action, target&) const override;
@@ -132,7 +162,7 @@ namespace build2
{
public:
virtual bool
- match (action, target&, const string&) const override;
+ match (action, target&) const override;
virtual recipe
apply (action, target&) const override;
@@ -219,8 +249,8 @@ namespace build2
// Implementation details.
//
public:
- // The name in rule_match is used as a hint and as a name in diagnostics.
- // The former does not apply to ad hoc recipes (but does apply to ad hoc
+ // The name in rule_match is used to match hints and in diagnostics. The
+ // former does not apply to ad hoc recipes (but does apply to ad hoc
// rules).
//
const build2::rule_match rule_match;
diff --git a/libbuild2/scope.hxx b/libbuild2/scope.hxx
index 12fd22c..86f5e4b 100644
--- a/libbuild2/scope.hxx
+++ b/libbuild2/scope.hxx
@@ -422,9 +422,9 @@ namespace build2
template <typename T>
void
- insert_rule (action_id a, string hint, const rule& r)
+ insert_rule (action_id a, string name, const rule& r)
{
- rules.insert<T> (a, move (hint), r);
+ rules.insert<T> (a, move (name), r);
}
// 0 meta-operation id is treated as an (emulated) wildcard.
@@ -435,7 +435,7 @@ namespace build2
//
template <typename T>
void
- insert_rule (meta_operation_id, operation_id, string hint, const rule&);
+ insert_rule (meta_operation_id, operation_id, string name, const rule&);
// Operation callbacks.
//
diff --git a/libbuild2/scope.ixx b/libbuild2/scope.ixx
index d297720..5d76a7f 100644
--- a/libbuild2/scope.ixx
+++ b/libbuild2/scope.ixx
@@ -176,11 +176,11 @@ namespace build2
template <typename T>
inline void scope::
insert_rule (meta_operation_id mid, operation_id oid,
- string hint,
+ string name,
const rule& r)
{
if (mid != 0)
- rules.insert<T> (mid, oid, move (hint), r);
+ rules.insert<T> (mid, oid, move (name), r);
else
{
auto& ms (root_scope ()->root_extra->meta_operations);
@@ -198,7 +198,7 @@ namespace build2
mid != info_id &&
mid != create_id &&
mid != disfigure_id)
- rules.insert<T> (mid, oid, hint, r);
+ rules.insert<T> (mid, oid, name, r);
}
}
}
diff --git a/libbuild2/target-type.hxx b/libbuild2/target-type.hxx
index ef3a3ed..09bc316 100644
--- a/libbuild2/target-type.hxx
+++ b/libbuild2/target-type.hxx
@@ -93,7 +93,25 @@ namespace build2
const target* (*search) (const target&, const prerequisite_key&);
- bool see_through; // A group with the default "see through" semantics.
+ // Target type flags.
+ //
+ // Note that the member_hint flag should only be used on groups with
+ // link-up during load (see lib{}, for example). In particular, if the
+ // group link-up only happens during match, then the hint would be looked
+ // up before the group is known.
+ //
+ enum class flag: uint64_t
+ {
+ none = 0,
+ group = 0x01, // A (non-adhoc) group.
+ see_through = group | 0x02, // A group with "see through" semantics.
+ member_hint = group | 0x04 // Untyped rule hint applies to members.
+ };
+
+ flag flags;
+
+ bool
+ see_through () const;
template <typename T>
bool
@@ -125,6 +143,32 @@ namespace build2
inline ostream&
operator<< (ostream& os, const target_type& tt) {return os << tt.name;}
+ inline target_type::flag
+ operator&= (target_type::flag& x, target_type::flag y)
+ {
+ return x = static_cast<target_type::flag> (
+ static_cast<uint64_t> (x) & static_cast<uint64_t> (y));
+ }
+
+ inline target_type::flag
+ operator|= (target_type::flag& x, target_type::flag y)
+ {
+ return x = static_cast<target_type::flag> (
+ static_cast<uint64_t> (x) | static_cast<uint64_t> (y));
+ }
+
+ inline target_type::flag
+ operator& (target_type::flag x, target_type::flag y) {return x &= y;}
+
+ inline target_type::flag
+ operator| (target_type::flag x, target_type::flag y) {return x |= y;}
+
+ inline bool target_type::
+ see_through () const
+ {
+ return (flags & flag::see_through) == flag::see_through;
+ }
+
// Target type map.
//
class target_type_map
diff --git a/libbuild2/target.cxx b/libbuild2/target.cxx
index ba1454e..92db7e9 100644
--- a/libbuild2/target.cxx
+++ b/libbuild2/target.cxx
@@ -1092,7 +1092,7 @@ namespace build2
nullptr,
nullptr,
&target_search,
- false
+ target_type::flag::none,
};
const target_type mtime_target::static_type
@@ -1105,7 +1105,7 @@ namespace build2
nullptr,
nullptr,
&target_search,
- false
+ target_type::flag::none
};
const target_type path_target::static_type
@@ -1118,7 +1118,7 @@ namespace build2
nullptr,
nullptr,
&target_search,
- false
+ target_type::flag::none
};
const target_type file::static_type
@@ -1131,7 +1131,7 @@ namespace build2
nullptr, /* pattern */
&target_print_1_ext_verb, // Print extension even at verbosity level 0.
&file_search,
- false
+ target_type::flag::none
};
static const target*
@@ -1158,7 +1158,7 @@ namespace build2
nullptr,
nullptr,
&alias_search,
- false
+ target_type::flag::none
};
// dir
@@ -1374,7 +1374,7 @@ namespace build2
&dir_pattern,
nullptr,
&dir_search,
- false
+ target_type::flag::none
};
const target_type fsdir::static_type
@@ -1387,7 +1387,7 @@ namespace build2
&dir_pattern,
nullptr,
&target_search,
- false
+ target_type::flag::none
};
static optional<string>
@@ -1455,7 +1455,7 @@ namespace build2
#endif
nullptr,
&file_search,
- false
+ target_type::flag::none
};
static const char*
@@ -1541,7 +1541,7 @@ namespace build2
&buildfile_target_pattern,
nullptr,
&file_search,
- false
+ target_type::flag::none
};
const target_type doc::static_type
@@ -1554,7 +1554,7 @@ namespace build2
nullptr, /* pattern */ // Same as file.
&target_print_1_ext_verb, // Same as file.
&file_search,
- false
+ target_type::flag::none
};
const target_type legal::static_type
@@ -1567,7 +1567,7 @@ namespace build2
nullptr, /* pattern */ // Same as file.
&target_print_1_ext_verb, // Same as file.
&file_search,
- false
+ target_type::flag::none
};
const target_type man::static_type
@@ -1580,7 +1580,7 @@ namespace build2
nullptr,
&target_print_1_ext_verb, // Print extension even at verbosity level 0.
&file_search,
- false
+ target_type::flag::none
};
extern const char man1_ext[] = "1"; // VC14 rejects constexpr.
@@ -1595,7 +1595,7 @@ namespace build2
&target_pattern_fix<man1_ext>,
&target_print_0_ext_verb, // Fixed extension, no use printing.
&file_search,
- false
+ target_type::flag::none
};
static const char*
@@ -1644,6 +1644,6 @@ namespace build2
&manifest_target_pattern,
nullptr,
&file_search,
- false
+ target_type::flag::none
};
}
diff --git a/libbuild2/target.hxx b/libbuild2/target.hxx
index 2820aa7..4c51e2e 100644
--- a/libbuild2/target.hxx
+++ b/libbuild2/target.hxx
@@ -99,15 +99,53 @@ namespace build2
};
using prerequisite_targets = vector<prerequisite_target>;
- // A rule match is an element of hint_rule_map.
+ // A rule match is an element of name_rule_map.
//
using rule_match = pair<const string, reference_wrapper<const rule>>;
+ // A map of target type plus operation ids to rule hints (see name_rule_map
+ // for details on rule names and hints). The default_id serves as a fallback
+ // for update and clean operations.
+ //
+ // Note that for now hints are tried in the order specified and the first
+ // that matches, used.
+ //
+ struct rule_hints
+ {
+ // Return empty string if not found.
+ //
+ const string&
+ find (const target_type&, operation_id, bool untyped) const;
+
+ bool
+ empty () const {return map.empty ();}
+
+ // Note that insertion of an existing entry overrides the old value.
+ //
+ void
+ insert (const target_type*, operation_id, string);
+
+ struct value_type
+ {
+ const target_type* type;
+ operation_id operation;
+ string hint;
+ };
+
+ vector<value_type> map;
+ };
+
// Additional information about a rule match (see rule.hxx for details).
//
+ // Note that passing this information to a base rule's match() as-is may or
+ // may not be correct. If some changes must be made (for example, the
+ // fallback flag must be cleared), then that should be done by modifying
+ // (and restoring, if necessary) the passed instance rather than making a
+ // copy (which would not survive to apply()).
+ //
struct match_extra
{
- bool fallback; // True if matching a fallback rule.
+ bool fallback; // True if matching a fallback rule (see match_rule()).
string buffer; // Auxiliary buffer that's reused during match/apply.
// Implementation details.
@@ -211,15 +249,15 @@ namespace build2
// obj{}).
//
// In an all-group, when a group is updated, normally all its members are
- // updates (and usually with a single command), though there could be some
+ // updated (and usually with a single command), though there could be some
// members that are omitted, depending on the configuration (e.g., an
// inline file not/being generated). When an all-group is mentioned as a
// prerequisite, the rule is usually interested in the individual members
- // rather than the whole group. For example, a C++ compile rule would like
- // to "see" the ?xx{} members when it gets a cli.cxx{} group.
+ // rather than the group target. For example, a C++ compile rule would
+ // like to "see" the ?xx{} members when it gets a cli.cxx{} group.
//
// Which brings us to the group iteration mode. The target type contains a
- // member called see_through that indicates whether the default iteration
+ // flag called see_through that indicates whether the default iteration
// mode for the group should be "see through"; that is, whether we see the
// members or the group itself. For the iteration support itself, see the
// *_prerequisite_members() machinery below.
@@ -491,6 +529,19 @@ namespace build2
value&
append (const variable&);
+
+ // Rule hints.
+ //
+ public:
+ build2::rule_hints rule_hints;
+
+ // Find the rule hint for the specified operation taking into account the
+ // target type/group. Note: racy with regards to the group link-up and
+ // should only be called when safe.
+ //
+ const string&
+ find_hint (operation_id) const;
+
// Ad hoc recipes.
//
public:
@@ -545,7 +596,7 @@ namespace build2
//
build2::match_extra match_extra;
- // Matched rule (pointer to hint_rule_map element). Note that in case of
+ // Matched rule (pointer to name_rule_map element). Note that in case of
// a direct recipe assignment we may not have a rule (NULL).
//
const rule_match* rule;
@@ -1229,7 +1280,7 @@ namespace build2
{
if (r_->mode_ != members_mode::never &&
i_ != r_->e_ &&
- i_->type.see_through)
+ i_->type.see_through ())
switch_mode ();
}
@@ -1257,7 +1308,7 @@ namespace build2
//
// for (...; ++i)
// {
- // if (i->prerequisite.type.see_through)
+ // if (i->prerequisite.type.see_through ())
// {
// for (i.enter_group (); i.group (); )
// {
diff --git a/libbuild2/target.ixx b/libbuild2/target.ixx
index 8f0768e..af75cd1 100644
--- a/libbuild2/target.ixx
+++ b/libbuild2/target.ixx
@@ -53,6 +53,91 @@ namespace build2
return r;
}
+ // rule_hints
+ //
+ inline const string& rule_hints::
+ find (const target_type& tt, operation_id o, bool ut) const
+ {
+ // Look for fallback during the same iteration.
+ //
+ const value_type* f (nullptr);
+
+ for (const value_type& v: map)
+ {
+ if (!(v.type == nullptr ? ut : tt.is_a (*v.type)))
+ continue;
+
+ if (v.operation == o)
+ return v.hint;
+
+ if (f == nullptr &&
+ v.operation == default_id &&
+ (o == update_id || o == clean_id))
+ f = &v;
+ }
+
+ return f != nullptr ? f->hint : empty_string;
+ }
+
+ inline void rule_hints::
+ insert (const target_type* tt, operation_id o, string h)
+ {
+ auto i (find_if (map.begin (), map.end (),
+ [tt, o] (const value_type& v)
+ {
+ return v.operation == o && v.type == tt;
+ }));
+
+ if (i == map.end ())
+ map.push_back (value_type {tt, o, move (h)});
+ else
+ i->hint = move (h);
+ }
+
+ inline const string& target::
+ find_hint (operation_id o) const
+ {
+ using flag = target_type::flag;
+
+ const target_type* tt (nullptr); // Resolve lazily.
+
+ // First check the target itself.
+ //
+ if (!rule_hints.empty ())
+ {
+ // If this is a group that "gave" its untyped hints to the members, then
+ // ignore untyped entries.
+ //
+ tt = &type ();
+ bool ut ((tt->flags & flag::member_hint) != flag::member_hint);
+
+ const string& r (rule_hints.find (*tt, o, ut));
+ if (!r.empty ())
+ return r;
+ }
+
+ // Then check the group.
+ //
+ if (const target* g = group)
+ {
+ if (!g->rule_hints.empty ())
+ {
+ // If the group "gave" its untyped hints to the members, then don't
+ // ignore untyped entries.
+ //
+ const target_type& gt (g->type ());
+ bool ut ((gt.flags & flag::member_hint) == flag::member_hint);
+
+ if (tt == nullptr)
+ tt = &type ();
+
+ return g->rule_hints.find (*tt, o, ut);
+ }
+ }
+
+ return empty_string;
+ }
+
// match_extra
//
inline void match_extra::
@@ -524,7 +609,7 @@ namespace build2
if (r_->mode_ != members_mode::never &&
i_ != r_->e_ &&
- i_->type.see_through)
+ i_->type.see_through ())
switch_mode ();
}
diff --git a/libbuild2/test/rule.cxx b/libbuild2/test/rule.cxx
index 06fb12f..142bded 100644
--- a/libbuild2/test/rule.cxx
+++ b/libbuild2/test/rule.cxx
@@ -30,7 +30,7 @@ namespace build2
namespace test
{
bool rule::
- match (action, target&, const string&) const
+ match (action, target&) const
{
// We always match, even if this target is not testable (so that we can
// ignore it; see apply()).
@@ -66,7 +66,7 @@ namespace build2
// Resolve group members.
//
- if (!see_through || t.type ().see_through)
+ if (!see_through_only || t.type ().see_through ())
{
// Remember that we are called twice: first during update for test
// (pre-operation) and then during test. During the former, we rely on
diff --git a/libbuild2/test/rule.hxx b/libbuild2/test/rule.hxx
index e96b68b..6fcf208 100644
--- a/libbuild2/test/rule.hxx
+++ b/libbuild2/test/rule.hxx
@@ -20,7 +20,7 @@ namespace build2
{
public:
virtual bool
- match (action, target&, const string&) const override;
+ match (action, target&) const override;
virtual recipe
apply (action, target&) const override;
@@ -34,10 +34,10 @@ namespace build2
target_state
perform_script (action, const target&, size_t) const;
- rule (common_data&& d, bool see_through_only)
- : common (move (d)), see_through (see_through_only) {}
+ rule (common_data&& d, bool sto)
+ : common (move (d)), see_through_only (sto) {}
- bool see_through;
+ bool see_through_only;
};
class default_rule: public rule
diff --git a/libbuild2/test/target.cxx b/libbuild2/test/target.cxx
index ce88baa..852abdf 100644
--- a/libbuild2/test/target.cxx
+++ b/libbuild2/test/target.cxx
@@ -56,7 +56,7 @@ namespace build2
&testscript_target_pattern,
nullptr,
&file_search,
- false
+ target_type::flag::none
};
}
}
diff --git a/libbuild2/version/init.cxx b/libbuild2/version/init.cxx
index abcb728..b3657bc 100644
--- a/libbuild2/version/init.cxx
+++ b/libbuild2/version/init.cxx
@@ -390,7 +390,7 @@ namespace build2
if (cast_false<bool> (rs["install.booted"]))
{
rs.insert_rule<manifest> (
- perform_install_id, "version.manifest", manifest_install_rule_);
+ perform_install_id, "version.install", manifest_install_rule_);
}
return true;
diff --git a/libbuild2/version/rule.cxx b/libbuild2/version/rule.cxx
index 3da69cc..ad26da4 100644
--- a/libbuild2/version/rule.cxx
+++ b/libbuild2/version/rule.cxx
@@ -47,7 +47,7 @@ namespace build2
// in_rule
//
bool in_rule::
- match (action a, target& xt, const string&) const
+ match (action a, target& xt) const
{
tracer trace ("version::in_rule::match");
@@ -302,7 +302,7 @@ namespace build2
// manifest_install_rule
//
bool manifest_install_rule::
- match (action a, target& t, const string&) const
+ match (action a, target& t) const
{
// We only match project's manifest.
//
@@ -315,7 +315,7 @@ namespace build2
if (s.root_scope () != &s || s.src_path () != t.dir)
return false;
- return file_rule::match (a, t, "");
+ return file_rule::match (a, t);
}
auto_rmfile manifest_install_rule::
diff --git a/libbuild2/version/rule.hxx b/libbuild2/version/rule.hxx
index c174f40..55b4aee 100644
--- a/libbuild2/version/rule.hxx
+++ b/libbuild2/version/rule.hxx
@@ -23,7 +23,7 @@ namespace build2
in_rule (): rule ("version.in 2", "version.in") {}
virtual bool
- match (action, target&, const string&) const override;
+ match (action, target&) const override;
virtual string
lookup (const location&,
@@ -42,7 +42,7 @@ namespace build2
manifest_install_rule () {}
virtual bool
- match (action, target&, const string&) const override;
+ match (action, target&) const override;
virtual auto_rmfile
install_pre (const file&, const install_dir&) const override;