#!/usr/bin/python import argparse import pathlib import re import subprocess import sys import termcolor parser = argparse.ArgumentParser() parser.add_argument("-q", "--quick", action="store_true", dest="quick", help="Only compile the subdirectory containing the Kconfig file") parser.add_argument("kconfig", metavar="Kconfig", nargs=1, help="Path to Kconfig file") parser.add_argument("makeargs", metavar="Make Arguments", nargs="*", help="Options to pass to make") Args = parser.parse_args() Kconfig = pathlib.Path(Args.kconfig[0]) Config = pathlib.Path("scripts/config").absolute() Make = pathlib.Path("~/bin/makelinux.zsh").expanduser() MakeArg = Args.makeargs + ([ f"{str(Kconfig)}/" ] if Args.quick else [ ]) Options = dict() Colors = { "n" : "grey", "y" : "green", "m" : "cyan" } Attrs = { "y" : [ "bold" ], "m" : [ "bold" ] } NameLen = 0 if Kconfig.is_dir(): Kconfig = Kconfig / "Kconfig" def assert_exists(path): if not path.exists(): print(f"Error: {path} does not exist!") sys.exit(1) assert_exists(Kconfig) assert_exists(Make) assert_exists(Config) class Option: def __init__(self, opt): lines = opt.splitlines() self.name = lines[0].strip() self.type = lines[1].strip().split()[0] self.state = "y" self.res = None if search := re.search("\sdepends on (.*?)\n", opt): depends = search.group(1).strip() depends = [ d.strip() for d in re.split("[&&|=m|=y|=n]", depends) ] self.depends = set([ d for d in depends if len(d) > 0 ]) else: self.depends = set() def __repr__(self): return f"{self.name}:{self.type}" def __lt__(self, rhs): if self.name.endswith("DEBUG"): return False if rhs.name.endswith("DEBUG"): return True return self.name in rhs.dependencies() def dependencies(self): ret = self.depends.copy() for dep in self.depends: if (opt := Options.get(dep)) is not None: ret.update(opt.dependencies()) return ret def disable(self): subprocess.run([ Config ] + [ "--disable", self.name ]).check_returncode() self.state = "n" def enable(self): how = "--module" if self.type == "tristate" else "--enable" subprocess.run([ Config ] + [ how, self.name ]).check_returncode() self.state = "m" if self.type == "tristate" else "y" def print(self): print(" ", end="") termcolor.cprint(self.name, Colors.get(self.state), attrs=["bold", "dark"], end="") termcolor.cprint("=", "white", attrs=["bold"], end="") termcolor.cprint(self.state, Colors.get(self.state), attrs=["bold", "dark"]) def print_result(self): match self.res: case True: result = ("Success", "green") case False: result = ("Failed", "red") case _: result = ("Not Run", "yellow") termcolor.cprint(" " + self.name + " ", Colors.get(self.state), attrs=["bold", "dark"], end="") termcolor.cprint(" " * (NameLen - len(self.name)), "grey", attrs=["underline"], end="") termcolor.cprint(" " + result[0], result[1], attrs=["bold", "dark"]) with open(Kconfig) as f: regex = re.compile("\nconfig") opts = [ Option(opt) for opt in regex.split(f.read()) if opt[0] != "#" ] Options = { opt.name:opt for opt in opts if opt.type in [ "bool", "tristate" ]} options = list(Options.values()) options.sort() def make_opt(option): option.enable() print() for o in options: o.print() option.res = False subprocess.run([ Make ] + [ "olddefconfig" ]).check_returncode() subprocess.run([ Make ] + MakeArg).check_returncode() option.res = True try: for opt in options: NameLen = max(NameLen, len(opt.name) + 2) for opt in options: opt.disable() for opt in options: make_opt(opt) except Exception as e: print(str(e)) finally: termcolor.cprint(f"\nKconfig Results:", "yellow", attrs=["bold", "underline"]) for opt in options: opt.print_result() if False in [ opt.res for opt in options ]: sys.exit(1)