diff mbox series

[V2] kernel_dep_check.bbclass: help track kernel depend

Message ID 20221228214732.758882-1-jebr@google.com
State New
Headers show
Series [V2] kernel_dep_check.bbclass: help track kernel depend | expand

Commit Message

John Broadbent Dec. 28, 2022, 9:47 p.m. UTC
From: John Edward Broadbent <jebr@google.com>

This recipe can be used to identify kernel dependencies, and
immediately throw build errors if those dependencies are not met.

Signed-off-by: John Edward Broadbent <jebr@google.com>
---
 meta/classes-recipe/kernel_dep_check.bbclass | 81 ++++++++++++++++++++
 1 file changed, 81 insertions(+)
 create mode 100644 meta/classes-recipe/kernel_dep_check.bbclass

Comments

Richard Purdie Jan. 16, 2023, 4:53 p.m. UTC | #1
On Wed, 2022-12-28 at 13:47 -0800, John Broadbent via
lists.openembedded.org wrote:
> From: John Edward Broadbent <jebr@google.com>
> 
> This recipe can be used to identify kernel dependencies, and
> immediately throw build errors if those dependencies are not met.
> 
> Signed-off-by: John Edward Broadbent <jebr@google.com>
> ---
>  meta/classes-recipe/kernel_dep_check.bbclass | 81 ++++++++++++++++++++
>  1 file changed, 81 insertions(+)
>  create mode 100644 meta/classes-recipe/kernel_dep_check.bbclass
> 
> diff --git a/meta/classes-recipe/kernel_dep_check.bbclass b/meta/classes-recipe/kernel_dep_check.bbclass
> new file mode 100644
> index 0000000000..25bef1533c
> --- /dev/null
> +++ b/meta/classes-recipe/kernel_dep_check.bbclass
> @@ -0,0 +1,81 @@
> +# This class is meant to help in tracking recipe's dependencies
> +# on certain Linux Kernel's compile time options, by making them
> +# explicit.
> +#
> +# Usage.
> +# 1. Inherit this class.
> +# 2. If the Linux Kernel MUST have certain compile time options
> +#       enabled, add them to KERNEL_OPTIONS_REQUIRED variable.
> +#       Multiple options can be added, separated by whitespace.
> +#       If the kernel built with the image does not have these
> +#       options enabled, the build will fail.
> +# 3. If some options are simply recommended, but not mandatory,
> +#       they can be added to KERNEL_OPTIONS_RECOMMENDED variable.
> +#       If the kernel built with the image does not have these
> +#       options enabled, warning will be produced, but the build
> +#       will succeed.
> +# 4. If some options has alternatives, i.e. if only one of the
> +#       options has to be enabled to pass the check, separate
> +#       the alternatives with '|' with no spaces, like so:
> +#           DECOMPRESS_GZIP|DECOMPRESS_BZIP2
> +
> +
> +KERNEL_OPTIONS_REQUIRED ??= ""
> +KERNEL_OPTIONS_RECOMMENDED ??= ""
> +
> +def report_opt_warn(pn, opt):
> +    if len(opt_alt_list) > 1:
> +        bb.warn("%s recommends one of the following Linux Kernel"
> +                " options to be enabled: %s"
> +                % (pn, ",".join(opt_alt_list)))
> +    else:
> +        bb.warn("%s recommends Linux Kernel option %s to be enabled"
> +                % (pn, opt_alt_list[0]))
> +
> +
> +def report_opt_fatal(pn, opt_alt_list):
> +    if len(opt_alt_list) > 1:
> +        bb.fatal("%s requires one of the following Linux Kernel"
> +                " options to be enabled: %s"
> +                % (pn, ",".join(opt_alt_list)))
> +    else:
> +        bb.fatal("%s requires Linux Kernel option %s to be enabled"
> +                % (pn, opt_alt_list[0]))
> +
> +
> +def check_kernel_option(pn, opt_expr, opt_map, report_f):
> +    alt_list = opt_expr.split("|")
> +    alt_list_full = []
> +    for opt in alt_list:
> +        if not opt.startswith("CONFIG_"):
> +            alt_list_full.append("CONFIG_" + opt)
> +        else:
> +            alt_list_full.append(opt)
> +
> +    if not any(opt_map.get(o) == "y" for o in alt_list_full):
> +        report_f(pn, alt_list_full)
> +
> +
> +python do_package:qa:append () {
> +    kconfig_path = os.path.join(d.getVar("STAGING_KERNEL_BUILDDIR"), ".config")
> +
> +    kconfig_map = dict()
> +    with open(kconfig_path, "r") as kconfig:
> +        for line in kconfig:
> +            if not line.startswith("CONFIG"):
> +                continue
> +
> +            cfg_chunks = line.strip().split("=")
> +            kconfig_map[cfg_chunks[0]] = cfg_chunks[1]
> +
> +    pn = d.getVar("PN")
> +    for opt in d.getVar("KERNEL_OPTIONS_REQUIRED", "").split():
> +        check_kernel_option(pn, opt, kconfig_map, report_opt_fatal)
> +
> +    for opt in d.getVar("KERNEL_OPTIONS_RECOMMENDED", "").split():
> +        check_kernel_option(pn, opt, kconfig_map, report_opt_warn)
> +}
> +
> +# do_shared_workdir moves kernel's .config to STAGING_KERNEL_BUILDDIR,
> +# so it must complete before we can run the qa checks above.
> +do_package:qa[depends] = "virtual/kernel:do_shared_workdir"

Thanks for updating the patch. I am a little curious on the
background/context for this code, not sure if there are any details you
can share?

I did talk with our kernel developers about this and there is a worry
that in doing this, we'd start duplicating functionality that we
already have in the kernel tools and kernel cache work that linux-yocto
supports. Did you look at the support there and is that something you
could use instead?

Worst case this can be used within your own layers, in core we'd
probably want to try and standardise around on set of kernel tooling.

Cheers,

Richard
diff mbox series

Patch

diff --git a/meta/classes-recipe/kernel_dep_check.bbclass b/meta/classes-recipe/kernel_dep_check.bbclass
new file mode 100644
index 0000000000..25bef1533c
--- /dev/null
+++ b/meta/classes-recipe/kernel_dep_check.bbclass
@@ -0,0 +1,81 @@ 
+# This class is meant to help in tracking recipe's dependencies
+# on certain Linux Kernel's compile time options, by making them
+# explicit.
+#
+# Usage.
+# 1. Inherit this class.
+# 2. If the Linux Kernel MUST have certain compile time options
+#       enabled, add them to KERNEL_OPTIONS_REQUIRED variable.
+#       Multiple options can be added, separated by whitespace.
+#       If the kernel built with the image does not have these
+#       options enabled, the build will fail.
+# 3. If some options are simply recommended, but not mandatory,
+#       they can be added to KERNEL_OPTIONS_RECOMMENDED variable.
+#       If the kernel built with the image does not have these
+#       options enabled, warning will be produced, but the build
+#       will succeed.
+# 4. If some options has alternatives, i.e. if only one of the
+#       options has to be enabled to pass the check, separate
+#       the alternatives with '|' with no spaces, like so:
+#           DECOMPRESS_GZIP|DECOMPRESS_BZIP2
+
+
+KERNEL_OPTIONS_REQUIRED ??= ""
+KERNEL_OPTIONS_RECOMMENDED ??= ""
+
+def report_opt_warn(pn, opt):
+    if len(opt_alt_list) > 1:
+        bb.warn("%s recommends one of the following Linux Kernel"
+                " options to be enabled: %s"
+                % (pn, ",".join(opt_alt_list)))
+    else:
+        bb.warn("%s recommends Linux Kernel option %s to be enabled"
+                % (pn, opt_alt_list[0]))
+
+
+def report_opt_fatal(pn, opt_alt_list):
+    if len(opt_alt_list) > 1:
+        bb.fatal("%s requires one of the following Linux Kernel"
+                " options to be enabled: %s"
+                % (pn, ",".join(opt_alt_list)))
+    else:
+        bb.fatal("%s requires Linux Kernel option %s to be enabled"
+                % (pn, opt_alt_list[0]))
+
+
+def check_kernel_option(pn, opt_expr, opt_map, report_f):
+    alt_list = opt_expr.split("|")
+    alt_list_full = []
+    for opt in alt_list:
+        if not opt.startswith("CONFIG_"):
+            alt_list_full.append("CONFIG_" + opt)
+        else:
+            alt_list_full.append(opt)
+
+    if not any(opt_map.get(o) == "y" for o in alt_list_full):
+        report_f(pn, alt_list_full)
+
+
+python do_package:qa:append () {
+    kconfig_path = os.path.join(d.getVar("STAGING_KERNEL_BUILDDIR"), ".config")
+
+    kconfig_map = dict()
+    with open(kconfig_path, "r") as kconfig:
+        for line in kconfig:
+            if not line.startswith("CONFIG"):
+                continue
+
+            cfg_chunks = line.strip().split("=")
+            kconfig_map[cfg_chunks[0]] = cfg_chunks[1]
+
+    pn = d.getVar("PN")
+    for opt in d.getVar("KERNEL_OPTIONS_REQUIRED", "").split():
+        check_kernel_option(pn, opt, kconfig_map, report_opt_fatal)
+
+    for opt in d.getVar("KERNEL_OPTIONS_RECOMMENDED", "").split():
+        check_kernel_option(pn, opt, kconfig_map, report_opt_warn)
+}
+
+# do_shared_workdir moves kernel's .config to STAGING_KERNEL_BUILDDIR,
+# so it must complete before we can run the qa checks above.
+do_package:qa[depends] = "virtual/kernel:do_shared_workdir"