aboutsummaryrefslogtreecommitdiff
path: root/mod/build-config.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'mod/build-config.cxx')
-rw-r--r--mod/build-config.cxx122
1 files changed, 109 insertions, 13 deletions
diff --git a/mod/build-config.cxx b/mod/build-config.cxx
index e838a59..5d3f46b 100644
--- a/mod/build-config.cxx
+++ b/mod/build-config.cxx
@@ -6,9 +6,10 @@
#include <map>
#include <sstream>
+#include <algorithm> // find()
#include <libbutl/sha256.mxx>
-#include <libbutl/utility.mxx> // throw_generic_error()
+#include <libbutl/utility.mxx> // throw_generic_error(), alpha(), etc.
#include <libbutl/openssl.mxx>
#include <libbutl/filesystem.mxx>
@@ -150,21 +151,116 @@ namespace brep
}
bool
- match (const string& config_pattern,
- const optional<string>& target_pattern,
- const build_config& c)
+ exclude (const build_class_exprs& exprs,
+ const build_constraints& constrs,
+ const build_config& cfg,
+ string* reason)
{
- return path_match (config_pattern, c.name) &&
- (!target_pattern || path_match (*target_pattern, c.target.string ()));
- }
+ // Save the first sentence of the reason, lower-case the first letter if
+ // the beginning looks like a word (the second character is the
+ // lower-case letter or space).
+ //
+ auto sanitize = [] (const string& reason)
+ {
+ string r (reason.substr (0, reason.find ('.')));
- bool
- exclude (const build_package& p, const build_config& c)
- {
- for (const auto& bc: p.constraints)
+ char c;
+ size_t n (r.size ());
+
+ if (n > 0 &&
+ alpha (c = r[0]) &&
+ c == ucase (c) &&
+ (n == 1 || (alpha (c = r[1]) && c == lcase (c)) || c == ' '))
+ r[0] = lcase (r[0]);
+
+ return r;
+ };
+
+ bool r (false);
+
+ // First, match the configuration against the package underlying build
+ // class set and expressions.
+ //
+ // Determine the underlying class set. Note that in the future we can
+ // potentially extend the underlying set with the special classes.
+ //
+ build_class_expr ucs (
+ !exprs.empty () && !exprs.front ().underlying_classes.empty ()
+ ? exprs.front ()
+ : build_class_expr ("default", "Default"));
+
+ // Transform the combined package build configuration class expression,
+ // making the underlying class set a starting set for the original
+ // expression and a restricting set, simultaneously. For example, for the
+ // expression:
+ //
+ // default legacy : -msvc
+ //
+ // the resulting expression will be:
+ //
+ // +default +legacy -msvc &( +default +legacy )
+ //
+ //
+ build_class_exprs es;
+ es.emplace_back (ucs.underlying_classes, '+', ucs.comment);
+ es.insert (es.end (), exprs.begin (), exprs.end ());
+ es.emplace_back (ucs.underlying_classes, '&', ucs.comment);
+
+ // We will use a comment of the first encountered excluding expression
+ // (changing the result from true to false) or non-including one (leaving
+ // the false result) as an exclusion reason.
+ //
+ for (const build_class_expr& e: es)
+ {
+ bool pr (r);
+ e.match (cfg.classes, r);
+
+ if (reason != nullptr)
+ {
+ // Reset the reason which, if saved, makes no sense anymore.
+ //
+ if (r)
+ {
+ reason->clear ();
+ }
+ else if (reason->empty () &&
+ //
+ // Exclusion.
+ //
+ (pr ||
+ //
+ // Non-inclusion. Make sure that the build class expression
+ // is empty or starts with an addition (+...).
+ //
+ e.expr.empty () ||
+ e.expr.front ().operation == '+'))
+ {
+ *reason = sanitize (e.comment);
+ }
+ }
+ }
+
+ if (!r)
+ return true;
+
+ // Now check if the configuration is excluded/included via the patterns.
+ //
+ const string& cn (cfg.name);
+ string tg (cfg.target.string ());
+
+ for (const build_constraint& c: constrs)
{
- if (match (bc.config, bc.target, c))
- return bc.exclusion;
+ if (path_match (c.config, cn) &&
+ (!c.target || path_match (*c.target, tg)))
+ {
+ if (!c.exclusion)
+ return false;
+
+ if (reason != nullptr)
+ *reason = sanitize (c.comment);
+
+ return true;
+ }
}
return false;