Message ID | 20221228214732.758882-1-jebr@google.com |
---|---|
State | New |
Headers | show |
Series | [V2] kernel_dep_check.bbclass: help track kernel depend | expand |
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 --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"