public inbox for isar-users@googlegroups.com
 help / color / mirror / Atom feed
From: Christopher Larson <kergoth@gmail.com>
To: isar-users@googlegroups.com
Subject: [PATCH] RFC: features.bbclass,bitbake.conf: use features lists
Date: Mon, 11 Nov 2024 16:51:47 +0000	[thread overview]
Message-ID: <CABcZANmMSpjZGqC4m=gVPQ-0QH88zVuXJmmvxpTx6brTvTfLDA@mail.gmail.com> (raw)

Any thoughts on something like this? Too much?

The intention is that downstreams would use standard bitbake functions
to check features, the same way they do in the Yocto Project, which
ensures that signatures and variable checksums never include the
entirety of the features variable, only the presence or absence of the
feature being checked.

This also adds bits to allow one to disable a feature without having
to use the problematic :remove mechanism, which can't be undone by
downstream layers easily. In this case, MY_FEATURES += "feature-a" and
then MY_FEATURES += "-feature-a" would result in removing it. Order
matters, so it can be re-added again later on without complication. It
also adds a minimal mechanism to let one feature pull in others
implicitly, which helps to avoid duplication when a feature is a
superset of another.
---

diff --git a/meta/classes/features.bbclass b/meta/classes/features.bbclass
new file mode 100644
index 00000000..32964c91
--- /dev/null
+++ b/meta/classes/features.bbclass
@@ -0,0 +1,91 @@
+# Functions to manipulate feature lists
+#
+# This class provides functions to manipulate feature lists. The functions
+# are intended to be used in :remove and :append handlers to remove or append
+# items to a variable. The remove will interpret items prefixed with a '-'
+# as items to be removed. The append function will rely on a mapping of
+# implied features to append the corresponding items. The intention is to
+# provide the ability for a feature to imply enabling of other features,
+# much like a dependency, but without the implication of order.
+#
+# Usage example:
+#
+#  IMAGE_FEATURES ??= ""
+#  IMAGE_FEATURES:remove = "${@remove_prefixed_features('IMAGE_FEATURES', d)}"
+#  IMAGE_FEATURES:prepend =
"${@add_implied_features('IMAGE_FEATURES', 'IMPLIED_IMAGE_FEATURES',
d)} "
+#  IMAGE_FEATURES_DISABLED = "${@' '.join(f for f in
remove_prefixed_features('IMAGE_FEATURES', d).split() if not
f.startswith('-'))}"
+#
+#  IMPLIED_IMAGE_FEATURES[alpha] = "beta"
+#
+#  IMAGE_FEATURES += "alpha theta -theta"
+#
+#  # SOME_VARIBLE="yes" if 'beta' is in IMAGE_FEATURES, "no" otherwise
+#  SOME_VARIABLE = "${@bb.utils.contains('IMAGE_FEATURES', 'beta',
'yes', 'no', d)}"
+#  # SOME_VARIBLE_TWO="yes" if 'beta' and 'alpha' are in
IMAGE_FEATURES, "no" otherwise
+#  SOME_VARIABLE_TWO = "${@bb.utils.contains('IMAGE_FEATURES',
['beta', 'alpha'], 'yes', 'no', d)}"
+#  # SOME_VARIBLE_THREE="yes" if 'beta' or 'theta' are in
IMAGE_FEATURES, "no" otherwise
+#  SOME_VARIABLE_THREE = "${@bb.utils.contains_any('IMAGE_FEATURES',
['beta', 'theta'], 'yes', 'no', d)}"
+
+
+def remove_prefixed_features(var, d):
+    """Return the items to be removed from var with :remove.
+
+    This function is intended to be used in a :remove handler to remove
+    items from a variable. It will interpret items prefixed with a '-' as
+    items to be removed.
+
+    As an internal note, the 'remove_prefixed_features_internal' flag
is used to
+    avoid infinite recursion.
+    """
+    if d.getVarFlag(var, 'remove_prefixed_features_internal') == '1':
+        return ''
+
+    from collections import Counter
+
+    d.setVarFlag(var, 'remove_prefixed_features_internal', '1')
+    try:
+        value = d.getVar(var)
+        counter = Counter()
+        for v in value.split():
+            if v.startswith('-'):
+                counter[v[1:]] -= 1
+                counter[v] -= 1
+            else:
+                counter[v] += 1
+        return ' '.join(v for v, c in counter.items() if c < 1)
+    finally:
+        d.delVarFlag(var, 'remove_prefixed_features_internal')
+
+def add_implied_features(var, implied_var, d):
+    """Return the items to be appended due to the presence of other
items in var.
+
+    This function is intended to be used in a :append handler to append
+    items from a variable. It will rely on the mapping of implied features
+    to append the corresponding items.
+
+    As an internal note, the 'add_implied_features_internal' flag is used to
+    avoid infinite recursion.
+    """
+    if d.getVarFlag(var, 'add_implied_features_internal') == '1':
+        return ''
+
+    def implied_features(feature, implied_mapping, d, seen=None):
+        """Return the implied features for a given feature."""
+        if seen is None:
+            seen = set()
+        if feature in seen:
+            return ''
+        seen.add(feature)
+        implied = implied_mapping.get(feature, '').split()
+        return ' '.join(implied + [implied_features(f,
implied_mapping, d, seen) for f in implied])
+
+    d.setVarFlag(var, 'add_implied_features_internal', '1')
+    try:
+        value = d.getVar(var)
+        implied_mapping = d.getVarFlags(implied_var)
+        if implied_mapping is None:
+            return ''
+
+        return ' '.join(implied_features(f, implied_mapping, d) for f
in value.split())
+    finally:
+        d.delVarFlag(var, 'add_implied_features_internal')
diff --git a/meta/conf/bitbake.conf b/meta/conf/bitbake.conf
index cda98035..4dedb081 100644
--- a/meta/conf/bitbake.conf
+++ b/meta/conf/bitbake.conf
@@ -172,6 +172,31 @@ BBINCLUDELOGS ??= "yes"
 # Add event handlers for bitbake
 INHERIT += "isar-events sstate"

+# Make features variables available
+INHERIT += "features"
+
+BASE_REPO_FEATURES ??= ""
+BASE_REPO_FEATURES[doc] = "Specifies the list of features for the
base-apt repository."
+BASE_REPO_FEATURES:remove =
"${@remove_prefixed_features('BASE_REPO_FEATURES', d)}"
+BASE_REPO_FEATURES:prepend =
"${@add_implied_features('BASE_REPO_FEATURES',
'IMPLIED_BASE_REPO_FEATURES', d)} "
+
+MACHINE_FEATURES ??= ""
+MACHINE_FEATURES[doc] = "Specifies the list of hardware features the
MACHINE is capable of supporting."
+MACHINE_FEATURES:remove = "${@remove_prefixed_features('MACHINE_FEATURES', d)}"
+MACHINE_FEATURES:prepend =
"${@add_implied_features('MACHINE_FEATURES',
'IMPLIED_MACHINE_FEATURES', d)} "
+
+DISTRO_FEATURES ??= ""
+DISTRO_FEATURES[doc] = "The software support you want in your
distribution for various features."
+DISTRO_FEATURES:remove = "${@remove_prefixed_features('DISTRO_FEATURES', d)}"
+DISTRO_FEATURES:prepend = "${@add_implied_features('DISTRO_FEATURES',
'IMPLIED_DISTRO_FEATURES', d)} "
+
+COMBINED_FEATURES = "${@oe.utils.set_intersect('DISTRO_FEATURES',
'MACHINE_FEATURES', d)}"
+
+ROOTFS_FEATURES ??= ""
+ROOTFS_FEATURES[doc] = "The list of features to be included in a root
filesystem. Typically, you configure this variable in an image recipe
or class."
+ROOTFS_FEATURES:remove = "${@remove_prefixed_features('ROOTFS_FEATURES', d)}"
+ROOTFS_FEATURES:prepend = "${@add_implied_features('ROOTFS_FEATURES',
'IMPLIED_ROOTFS_FEATURES', d)} "
+
 # Buildstats requires IMAGE_ROOTFS to be always defined
 IMAGE_ROOTFS ??= "${WORKDIR}/rootfs"
 INHERIT += "${@'buildstats' if
bb.utils.to_boolean(d.getVar('USE_BUILDSTATS')) else ''}"
--
2.45.2

-- 
You received this message because you are subscribed to the Google Groups "isar-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to isar-users+unsubscribe@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/isar-users/CABcZANmMSpjZGqC4m%3DgVPQ-0QH88zVuXJmmvxpTx6brTvTfLDA%40mail.gmail.com.

             reply	other threads:[~2024-11-11 16:52 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-11-11 16:51 Christopher Larson [this message]
2024-11-14 16:23 ` 'Jan Kiszka' via isar-users
2024-11-19 20:14   ` 'Larson, Chris' via isar-users

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CABcZANmMSpjZGqC4m=gVPQ-0QH88zVuXJmmvxpTx6brTvTfLDA@mail.gmail.com' \
    --to=kergoth@gmail.com \
    --cc=isar-users@googlegroups.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox