public inbox for isar-users@googlegroups.com
 help / color / mirror / Atom feed
* [PATCH] RFC: features.bbclass,bitbake.conf: use features lists
@ 2024-11-11 16:51 Christopher Larson
  2024-11-14 16:23 ` 'Jan Kiszka' via isar-users
  0 siblings, 1 reply; 3+ messages in thread
From: Christopher Larson @ 2024-11-11 16:51 UTC (permalink / raw)
  To: isar-users

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.

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2024-11-19 20:14 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-11-11 16:51 [PATCH] RFC: features.bbclass,bitbake.conf: use features lists Christopher Larson
2024-11-14 16:23 ` 'Jan Kiszka' via isar-users
2024-11-19 20:14   ` 'Larson, Chris' via isar-users

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox