diff --git a/pmb/build/menuconfig.py b/pmb/build/menuconfig.py index 7b5a6313..ba7e0392 100644 --- a/pmb/build/menuconfig.py +++ b/pmb/build/menuconfig.py @@ -153,12 +153,4 @@ def menuconfig(args, pkgname, use_oldconfig): pmb.build.checksum.update(args, pkgname) # Check config - pmb.parse.kconfig.check(args, apkbuild["_flavor"], - force_waydroid_check=False, - force_nftables_check=False, - force_containers_check=False, - force_zram_check=False, - force_netboot_check=False, - force_community_check=False, - force_uefi_check=False, - details=True) + pmb.parse.kconfig.check(args, apkbuild["_flavor"], details=True) diff --git a/pmb/helpers/frontend.py b/pmb/helpers/frontend.py index d569abea..24f0c351 100644 --- a/pmb/helpers/frontend.py +++ b/pmb/helpers/frontend.py @@ -377,16 +377,15 @@ def newapkbuild(args): def kconfig(args): if args.action_kconfig == "check": + # Build the components list from cli arguments (--waydroid etc.) + components_list = [] + for name in pmb.parse.kconfig.get_all_component_names(): + if getattr(args, f"kconfig_check_{name}"): + components_list += [name] + # Handle passing a file directly if args.file: - if pmb.parse.kconfig.check_file(args.package, - waydroid=args.waydroid, - nftables=args.nftables, - containers=args.containers, - zram=args.zram, - netboot=args.netboot, - community=args.community, - uefi=args.uefi, + if pmb.parse.kconfig.check_file(args.package, components_list, details=True): logging.info("kconfig check succeeded!") return @@ -414,17 +413,8 @@ def kconfig(args): if "!pmb:kconfigcheck" in apkbuild["options"]: skipped += 1 continue - if not pmb.parse.kconfig.check( - args, package, - force_waydroid_check=args.waydroid, - force_iwd_check=args.iwd, - force_nftables_check=args.nftables, - force_containers_check=args.containers, - force_zram_check=args.zram, - force_netboot_check=args.netboot, - force_community_check=args.community, - force_uefi_check=args.uefi, - details=True): + if not pmb.parse.kconfig.check(args, package, components_list, + details=True): error = True # At least one failure diff --git a/pmb/parse/arguments.py b/pmb/parse/arguments.py index 15c6c4df..1bf79623 100644 --- a/pmb/parse/arguments.py +++ b/pmb/parse/arguments.py @@ -464,23 +464,10 @@ def arguments_kconfig(subparser): check.add_argument("--arch", choices=arch_choices, dest="arch") check.add_argument("--file", action="store_true", help="check a file" " directly instead of a config in a package") - check.add_argument("--waydroid", action="store_true", help="check" - " options needed for waydroid too") - check.add_argument("--iwd", action="store_true", help="check" - " options needed for iwd too") - check.add_argument("--nftables", action="store_true", help="check" - " options needed for nftables too") - check.add_argument("--containers", action="store_true", - help="check options needed for containers too") - check.add_argument("--zram", action="store_true", help="check" - " options needed for zram support too") - check.add_argument("--netboot", action="store_true", help="check" - " options needed for netbooting too") - check.add_argument("--community", action="store_true", help="check" - " options needed for various features, required for" - " community/main devices") - check.add_argument("--uefi", action="store_true", help="check" - " options needed for uefi too") + for name in pmb.parse.kconfig.get_all_component_names(): + check.add_argument(f"--{name}", action="store_true", + dest=f"kconfig_check_{name}", + help=f"check options needed for {name} too") add_kernel_arg(check) # "pmbootstrap kconfig edit" diff --git a/pmb/parse/kconfig.py b/pmb/parse/kconfig.py index f066936f..3b5c15e4 100644 --- a/pmb/parse/kconfig.py +++ b/pmb/parse/kconfig.py @@ -11,6 +11,23 @@ import pmb.parse import pmb.helpers.pmaports +def get_all_component_names(): + """ + Get the component names from kconfig_options variables in + pmb/config/__init__.py. This does not include the base options. + + :returns: a list of component names, e.g. ["waydroid", "iwd", "nftables"] + """ + prefix = "necessary_kconfig_options_" + ret = [] + + for key in pmb.config.__dict__.keys(): + if key.startswith(prefix): + ret += [key.split(prefix, 1)[1]] + + return ret + + def is_set(config, option): """ Check, whether a boolean or tristate option is enabled @@ -74,48 +91,49 @@ def check_option(component, details, config, config_path, option, return True -def check_config(config_path, config_arch, pkgver, - waydroid=False, - iwd=False, - nftables=False, - containers=False, - zram=False, - netboot=False, - community=False, - uefi=False, - details=False, - enforce_check=True): +def check_config(config_path, config_arch, pkgver, components_list=[], + details=False, enforce_check=True): + """ + :param config_path: full path to kernel config file + :param config_arch: architecture name (alpine format, e.g. aarch64, x86_64) + :param pkgver: kernel version + :param components_list: what to check for, e.g. ["waydroid", "iwd"] + :param details: print all warnings if True, otherwise one generic warning + :param enforce_check: set to False to not fail kconfig check as long as + everything in necessary_kconfig_options is set + correctly, even if additional components are checked + :returns: True if the check passed, False otherwise + """ logging.debug(f"Check kconfig: {config_path}") with open(config_path) as handle: config = handle.read() - components = {"postmarketOS": pmb.config.necessary_kconfig_options} - if waydroid: - components["waydroid"] = pmb.config.necessary_kconfig_options_waydroid - if iwd: - components["iwd"] = pmb.config.necessary_kconfig_options_iwd - if nftables: - components["nftables"] = pmb.config.necessary_kconfig_options_nftables - if containers: - components["containers"] = \ - pmb.config.necessary_kconfig_options_containers - if zram: - components["zram"] = pmb.config.necessary_kconfig_options_zram - if netboot: - components["netboot"] = pmb.config.necessary_kconfig_options_netboot - if community: - components["waydroid"] = pmb.config.necessary_kconfig_options_waydroid - components["iwd"] = pmb.config.necessary_kconfig_options_iwd - components["nftables"] = pmb.config.necessary_kconfig_options_nftables - components["containers"] = \ - pmb.config.necessary_kconfig_options_containers - components["zram"] = pmb.config.necessary_kconfig_options_zram - components["netboot"] = pmb.config.necessary_kconfig_options_netboot - components["wireguard"] = pmb.config.necessary_kconfig_options_wireguard - components["filesystems"] = pmb.config.necessary_kconfig_options_filesystems - components["community"] = pmb.config.necessary_kconfig_options_community - if uefi: - components["uefi"] = pmb.config.necessary_kconfig_options_uefi + # Devices in all categories need basic options + # https://wiki.postmarketos.org/wiki/Device_categorization + components_list = ["postmarketOS"] + components_list + + # Devices in "community" or "main" need additional options + if "community" in components_list: + components_list += [ + "containers", + "filesystems", + "iwd", + "netboot", + "nftables", + "waydroid", + "wireguard", + "zram", + ] + + components = {} + for name in components_list: + if name == "postmarketOS": + pmb_config_var = "necessary_kconfig_options" + else: + pmb_config_var = f"necessary_kconfig_options_{name}" + + components[name] = getattr(pmb.config, pmb_config_var, None) + assert components[name], f"invalid kconfig component name: {name}" results = [] for component, options in components.items(): @@ -163,20 +181,14 @@ def check_config_options_set(config, config_path, config_arch, options, return ret -def check(args, pkgname, - force_waydroid_check=False, - force_iwd_check=False, - force_nftables_check=False, - force_containers_check=False, - force_zram_check=False, - force_netboot_check=False, - force_community_check=False, - force_uefi_check=False, - details=False, - must_exist=True): +def check(args, pkgname, components_list=[], details=False, must_exist=True): """ Check for necessary kernel config options in a package. + :param pkgname: the package to check for, optionally without "linux-" + :param components_list: what to check for, e.g. ["waydroid", "iwd"] + :param details: print all warnings if True, otherwise one generic warning + :param must_exist: if False, just return if the package does not exist :returns: True when the check was successful, False otherwise None if the aport cannot be found (only if must_exist=False) """ @@ -197,22 +209,11 @@ def check(args, pkgname, # We only enforce optional checks for community & main devices enforce_check = aport.split("/")[-2] in ["community", "main"] - check_waydroid = force_waydroid_check or ( - "pmb:kconfigcheck-waydroid" in apkbuild["options"]) - check_iwd = force_iwd_check or ( - "pmb:kconfigcheck-iwd" in apkbuild["options"]) - check_nftables = force_nftables_check or ( - "pmb:kconfigcheck-nftables" in apkbuild["options"]) - check_containers = force_containers_check or ( - "pmb:kconfigcheck-containers" in apkbuild["options"]) - check_zram = force_zram_check or ( - "pmb:kconfigcheck-zram" in apkbuild["options"]) - check_netboot = force_netboot_check or ( - "pmb:kconfigcheck-netboot" in apkbuild["options"]) - check_community = force_community_check or ( - "pmb:kconfigcheck-community" in apkbuild["options"]) - check_uefi = force_uefi_check or ( - "pmb:kconfigcheck-uefi" in apkbuild["options"]) + for name in get_all_component_names(): + if f"pmb:kconfigcheck-{name}" in apkbuild["options"] and \ + name not in components_list: + components_list += [name] + for config_path in glob.glob(aport + "/config-*"): # The architecture of the config is in the name, so it just needs to be # extracted @@ -228,18 +229,8 @@ def check(args, pkgname, "elsewhere in the name.") config_arch = config_name_split[1] - ret &= check_config(config_path, config_arch, - pkgver, - waydroid=check_waydroid, - iwd=check_iwd, - nftables=check_nftables, - containers=check_containers, - zram=check_zram, - netboot=check_netboot, - community=check_community, - uefi=check_uefi, - details=details, - enforce_check=enforce_check) + ret &= check_config(config_path, config_arch, pkgver, components_list, + details=details, enforce_check=enforce_check) return ret @@ -275,24 +266,18 @@ def extract_version(config_file): return "unknown" -def check_file(config_file, waydroid=False, nftables=False, - containers=False, zram=False, netboot=False, - community=False, uefi=False, details=False): +def check_file(config_file, components_list=[], details=False): """ Check for necessary kernel config options in a kconfig file. + :param config_file: full path to kernel config file + :param components_list: what to check for, e.g. ["waydroid", "iwd"] + :param details: print all warnings if True, otherwise one generic warning :returns: True when the check was successful, False otherwise """ arch = extract_arch(config_file) version = extract_version(config_file) logging.debug(f"Check kconfig: parsed arch={arch}, version={version} from " f"file: {config_file}") - return check_config(config_file, arch, version, - waydroid=waydroid, - nftables=nftables, - containers=containers, - zram=zram, - netboot=netboot, - community=community, - uefi=uefi, + return check_config(config_file, arch, version, components_list, details=details) diff --git a/test/test_kconfig_check.py b/test/test_kconfig_check.py index 839c2f02..ca2cf98f 100644 --- a/test/test_kconfig_check.py +++ b/test/test_kconfig_check.py @@ -31,21 +31,14 @@ def test_kconfig_check(args): "bad-missing-required-option") assert pmb.parse.kconfig.check_file(dir + "good") assert not pmb.parse.kconfig.check_file(dir + "bad-wrong-option-set") - assert pmb.parse.kconfig.check_file(dir + "good-waydroid", - waydroid=True) - assert not pmb.parse.kconfig.check_file(dir + - "bad-array-missing-some-options", - waydroid=True) - assert pmb.parse.kconfig.check_file(dir + "good-nftables", - nftables=True) - assert not pmb.parse.kconfig.check_file(dir + "bad-nftables", - nftables=True) - assert pmb.parse.kconfig.check_file(dir + "good-zram", - zram=True) - assert pmb.parse.kconfig.check_file(dir + "good-uefi", - uefi=True) - assert not pmb.parse.kconfig.check_file(dir + "bad-uefi", - uefi=True) + assert pmb.parse.kconfig.check_file(dir + "good-waydroid", ["waydroid"]) + assert not pmb.parse.kconfig.check_file(f"{dir}/bad-array-missing-some-options", + ["waydroid"]) + assert pmb.parse.kconfig.check_file(dir + "good-nftables", ["nftables"]) + assert not pmb.parse.kconfig.check_file(dir + "bad-nftables", ["nftables"]) + assert pmb.parse.kconfig.check_file(dir + "good-zram", ["zram"]) + assert pmb.parse.kconfig.check_file(dir + "good-uefi", ["uefi"]) + assert not pmb.parse.kconfig.check_file(dir + "bad-uefi", ["uefi"]) # tests on real devices # *** do not add more of these! *** @@ -60,8 +53,7 @@ def test_kconfig_check(args): assert pmb.parse.kconfig.check(args, "postmarketos-allwinner") # testing the force param: nokia-n900 will never need the uefi options - assert not pmb.parse.kconfig.check(args, "nokia-n900", - force_uefi_check=True) + assert not pmb.parse.kconfig.check(args, "nokia-n900", ["uefi"]) # supports zram (with pmb:kconfigcheck-zram), nftables assert pmb.parse.kconfig.check(args, "linux-purism-librem5")