diff mbox series

[RFC] bbfileconfig: Add class support

Message ID 20220927191606.748540-1-daniel@qtec.com
State New
Headers show
Series [RFC] bbfileconfig: Add class support | expand

Commit Message

Daniel Gomez Sept. 27, 2022, 7:16 p.m. UTC
Add support for the class 'BBFILECONFIG' which allows to select
the recipes for a given layer.

Example: 'Enable' python3-colorlog recipe from meta-python.

INHERIT += "bbfileconfig"
BBFILECONFIG_meta-python += "python3-colorlog"

Signed-off-by: Daniel Gomez <daniel@qtec.com>
---

Hi,

We have developed the 'BBFILECONFIG' class in order to be able to select
the recipes we want to parse in an allow list manner. Its meant to
control whether a recipe (bb) file from a specic layer is picked to be
parsed or not. Similar to the PACKAGECONFIG for packages inside recipes
(hence the BBFILECONFIG name).

When handling multiple metadata sources it easily becomes huge to build a
full distro ('world'). Current methods (AFAIK) only allows to
block/disallow recipe files with BBMASK.

Note: BBFILES_DYNAMIC does part of the job but different use-case.

Could this make sense to upstream? Perhaps there is a better/cleaner way
of doing this?

We are currently using this with a reduction of 40k -> 20k packages (per
machine). Of course, the class only parses the bb files (and therfore the number
of packages to be created) for the recipes we don't want them to be part of
our custom distro. This helps us to reduce build times while using directly
upstream layers without the need of copying/forking the recipes files
in internal layers.

Few extra notes:

1. The class does not handle depencencies. If a recipe is added to the
list, the developer should also add manually its depencencies in
their respective BBFILECONFIG_<layer>.

2. When multiple recipe files share a common name, some 'unclaimed' recipes
will be added too. Example: In meta-openembedded/meta-python we have:
python3-pybind11_2.10.0.bb and python3-pybind11-json_0.2.11.bb. If one
wants to add only the first one, the recipe name should be suffixed with
'_': BBFILECONFIG_meta-python = "python3-pybind11_"

Unfortunately, if the recipe does not follow <recipe>_<version/git>.bb
filename pattern but instead uses <recipe>.bb there would be no way to
filter out a second recipe sharing the same recipe name. However, this
is perhaps not the recommended way to name a recipe. Is it correct?

3. This class would require the following bitbake patch. Embedding
it here as part of the RFC for reference.

--
2.35.1
diff mbox series

Patch

diff --git a/lib/bb/cooker.py b/lib/bb/cooker.py
index 32a529f0..645c59f7 100644
--- a/lib/bb/cooker.py
+++ b/lib/bb/cooker.py
@@ -1796,6 +1796,15 @@  class CookerExit(bb.event.Event):
         bb.event.Event.__init__(self)


+class CookerStarted(bb.event.Event):
+    """
+    Notify clients of the Cooker started
+    """
+
+    def __init__(self):
+        bb.event.Event.__init__(self)
+
+
 class CookerCollectFiles(object):
     def __init__(self, priorities, mc=''):
         self.mc = mc
@@ -1834,6 +1843,7 @@  class CookerCollectFiles(object):

     def collect_bbfiles(self, config, eventdata):
         """Collect all available .bb build files"""
+        bb.event.fire(CookerStarted(), eventdata)
         masked = 0

         collectlog.debug("collecting .bb files")


 meta/classes/bbfileconfig.bbclass | 73 +++++++++++++++++++++++++++++++
 1 file changed, 73 insertions(+)
 create mode 100644 meta/classes/bbfileconfig.bbclass

diff --git a/meta/classes/bbfileconfig.bbclass b/meta/classes/bbfileconfig.bbclass
new file mode 100644
index 0000000000..4582fd6eb8
--- /dev/null
+++ b/meta/classes/bbfileconfig.bbclass
@@ -0,0 +1,73 @@ 
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Author: Daniel Gomez <daniel@qtec.com>
+#
+# This class allows to select recipe files on a per-layer basis for global
+# parsing and world target.
+#
+# It adds the ability to parse individual recipes from a specific layer from the
+# a configuration file.
+#
+# Usage: add INHERIT += "bbfileconfig" to the local.conf configuration file
+# and add BBFILECONFIG variable to a configuration file (e.g. conf/layer.conf)
+# to be able to perform individual recipe file selection. Must be suffixed with
+# the name of the layer (e.g. BBFILECONFIG_core).
+#
+# Example: Assuming meta-skeleton is part of the BBLAYERS, enable the bbfileconfig
+# to parse only the libxpm recipe
+# (meta-skeleton/recipes-skeleton/libxpm/libxpm_3.5.6.bb).
+#
+# INHERIT += "bbfileconfig"
+# BBFILECONFIG_skeleton = "libxpm"
+
+# Default space-separated list of recipe files to be removed from BBFILES
+BBFILECONFIG_REMOVE_DIRS ?= "\
+    recipes*/*/*.bb \
+    recipes*/*/*.bbappend \
+    recipes-*/*/*.bb \
+    recipes-*/*/*.bbappend \
+"
+
+# Default space-separated list of recipe files dirnames prefixes to be appended
+# to the selected layer
+BBFILECONFIG_BBFILES_DIRS ?= "recipes-*/*"
+
+# BBFILE selector handler executed at CookerStarted event:
+# 1. Get layer collections from BBFILE_COLLECTIONS.
+# 2. For each active collection (BBFILECONFIG_<layer> is initialized), removed
+#    dirs listed in BBFILECONFIG_REMOVE_DIRS from the BBFILES variable.
+# 3. For each collection, get the recipe name files from BBFILECONFIG and
+#    append them to the BBFILES as bb and bbappend files.
+python bbsel_handler () {
+    import bb.cooker
+    if isinstance(e, bb.cooker.CookerStarted):
+        collections = d.getVar('BBFILE_COLLECTIONS').split()
+        # For each collection layer with BBFILECONFIG enabled, remove the
+        # BBFILES layer directory and add only the selected recipes.
+        for c in collections:
+            cdir = d.getVar('BBFILE_PATTERN_%s' % c).replace("^/", "/")
+            cbb = d.getVar('BBFILECONFIG_%s' % c)
+            # If BBFILECONFIG_<layer> is initialized but empty, LAYERDIR
+            # will be removed from BBFILES and no recipe will be added.
+            rdirs = None
+            if cbb is not None:
+                rdirs = d.getVar('BBFILECONFIG_REMOVE_DIRS_%s' % c)
+                if not rdirs:
+                  rdirs = d.getVar('BBFILECONFIG_REMOVE_DIRS')
+                adirs = d.getVar('BBFILECONFIG_REMOVE_BBFILES_%s' % c)
+                if not adirs:
+                  adirs = d.getVar('BBFILECONFIG_BBFILES_DIRS')
+                for r in rdirs.split():
+                    rbbdir = cdir + r
+                    d.setVar('BBFILES:remove', "%s" % (rbbdir))
+                    bb.debug(1, "Layer %s directory '%s' added to the BBFILES removal list." % (c, rbbdir))
+                for s in cbb.split():
+                    for adir in adirs.split():
+                        bbdir = cdir + adir + "/" + s
+                        d.appendVar('BBFILES', " %s*.bb %s*.bbappend " % (bbdir, bbdir))
+                        bb.debug(1, "Recipe file '%s' directories '%s*.bb' and '%s*.bbappend' added to the BBFILES list." % (s, bbdir, bbdir))
+}
+
+addhandler bbsel_handler
+bbsel_handler[eventmask] = "bb.cooker.CookerStarted"