From mboxrd@z Thu Jan 1 00:00:00 1970 From: Simon Glass Date: Tue, 9 Oct 2018 10:20:27 -0600 Subject: [U-Boot] [RFC PATCH v2 2/3] tools: Add a tool to get a list of defconfigs based on filters In-Reply-To: <1538574832-21910-3-git-send-email-jjhiblot@ti.com> References: <1538574832-21910-1-git-send-email-jjhiblot@ti.com> <1538574832-21910-3-git-send-email-jjhiblot@ti.com> Message-ID: List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de Hi Jean-Jacques, On 3 October 2018 at 07:53, Jean-Jacques Hiblot wrote: > The possible filters are "arch", "vendor", "soc", "cpu" and "arch". > > The list of all the defconfigs is read from boards.cfg. If this file > doesn't exist, then tools/genboardscfg.py is called to generate it. > > Signed-off-by: Jean-Jacques Hiblot > --- > > Changes in v2: None > > tools/find_defconfigs.py | 167 +++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 167 insertions(+) > create mode 100755 tools/find_defconfigs.py This looks good, but I have some style comments below. Also it seems to do a similar thing to tools/buildman/board.py. Should we replace that impl with what you have here? It looks more flexible that what buildman currently provides. > > diff --git a/tools/find_defconfigs.py b/tools/find_defconfigs.py > new file mode 100755 > index 0000000..9d68cef > --- /dev/null > +++ b/tools/find_defconfigs.py > @@ -0,0 +1,167 @@ > +#!/usr/bin/env python > +# SPDX-License-Identifier: GPL-2.0+ > +# > +# Author: JJ Hiblot > +# > + > +""" > +Output a list of defconfig matching criteria. I think you mean defconfig-matching? > + > +The possible criteria are soc, vendor, arch, cpu, board and defconfig name. > +The criteria are expressed as regexp, allowing for complex selection. > + > +How does it work? > +----------------- > + > +This tools uses the boards.cfg file produced by tools/genboardscfg.py > +It reads the file to get a list of all the defconfigs and the information > +about the soc, vendor etc. for each of them. > +Then it walks this list and outputs the defconfigs for which the info match > +the regexp passed to the program. > + > +examples: > +--------- > + > +1) Get the list of defconfigs for boards built around omap5, omap4 and k3, not built by TI > + > +$ tools/find_defconfigs.py --soc 'omap[45]|k3' --vendor '(?!ti)' > +kc1_defconfig > +duovero_defconfig > +cl-som-am57x_defconfig > +cm_t54_defconfig > + > +2) Same list but iwth more details on the items that were used as filters > + > +$ tools/find_defconfigs.py --soc 'omap[45]|k3' --vendor '(?!ti)' --show-details > +kc1_defconfig | omap4 | amazon > +duovero_defconfig | omap4 | gumstix > +cl-som-am57x_defconfig | omap5 | compulab > +cm_t54_defconfig | omap5 | compulab > + > + > +""" > + > +import re > +import os > +import argparse Please sort these > + > + > +class board: > + Need a class comment here, also use Board since it is a class name > + def __init__(self, status, arch, cpu, soc, > + vendor, board, target, options, maintainer): > + self.status = status > + self.arch = arch > + self.cpu = cpu > + self.soc = soc > + self.vendor = vendor > + self.board = board > + self.target = target > + self.defconfig = "{}_defconfig".format(target) > + self.options = options > + self.maintainer = maintainer > + > + def show(self, sep=' | ', props=None): Function comment (see other tools for style). Need to document args and any return value. > + if not props: > + print( > + sep.join([self.defconfig, > + self.vendor, > + self.arch, > + self.cpu, > + self.soc, > + self.board, > + self.status, > + self.maintainer])) > + else: > + print(sep.join([self.defconfig] + [getattr(self, prop) for prop in props])) Does this need to import print_function from __future__ for Python 2? > + > + def cleanup(self): > + """ remove the directory in which the cfg files have been built """ Please use comment style from other tools. Same below. > + shutil.rmtree(self.temp_dir) > + > + def match(self, rules): > + """ return True if the board match all the criteria """ > + for prop, r in rules: > + val = getattr(self, prop) > + if not val or val == "-": > + return False > + if not r.match(val): > + return False > + return True > + > + > +def get_all_boards(): > + """ extract a list of boards from 'boards.cfg' """ > + result = [] > + if not os.path.isfile("boards.cfg"): > + os.system('tools/genboardscfg.py') > + > + with open('boards.cfg', 'r') as f: > + for l in f.readlines(): > + if not l or l[0] == "#": > + continue > + props = l.strip().split(None, 8) > + if not props: > + continue > + if len(props) < 9: > + props.extend(["-"] * (9 - len(props))) > + result.append(board(*props)) > + return result > + > + > +def get_default_options(): > + return ["board", "soc", "vendor", "arch", "cpu", "target"] > + > + > +def update_parser_with_default_options(parser): > + parser.add_argument('-i', '--ignore-case', action="store_true") > + parser.add_argument("--soc", > + help="regexp to filter on SoC. ex: 'omap[45]' to inspect omap5 and omap5 targets") > + parser.add_argument("--vendor", help="regexp to filter on Vendor.") > + parser.add_argument("--arch", help="regexp to filter on Arch") > + parser.add_argument("--cpu", help="regexp to filter on CPU") > + parser.add_argument("--board", help="regexp to filter on Board") > + parser.add_argument("--target", > + help="regexp to filter on Target (defconfig filename without the '_defconfig' suffix)") > + > + > +def get_matching_boards(args, fields=get_default_options()): > + # compile a list of regexp used to filter the targets > + boards = [] > + rules = [] > + for f in fields: > + arg = getattr(args, f) > + if arg: > + rules.append((f, re.compile("\\b{}\\b".format(arg), > + re.IGNORECASE if args.ignore_case else 0))) > + > + # get a list of boards matching the rules > + for b in get_all_boards(): > + if b.match(rules): > + boards.append(b) > + return boards > + > + > +def main(): > + parser = argparse.ArgumentParser(description="Show CONFIG options usage") > + update_parser_with_default_options(parser) > + parser.add_argument("--maintainer", help="regexp to filter on maintainer.") > + parser.add_argument("--status", help="regexp to filter on status.") > + parser.add_argument("--show-details", help="show fields used as filter", > + action="store_true") > + parser.add_argument("--show-all", help="show all fields", > + action="store_true") > + args = parser.parse_args() > + fields = get_default_options() + ["status", "maintainer"] > + > + for b in get_matching_boards(args, fields): > + if args.show_details: > + props = [f for f in fields if getattr(args, f)] > + b.show(props=props) > + elif args.show_all: > + b.show() > + else: > + print(b.defconfig) > + > +if __name__ == '__main__': > + main() > -- > 2.7.4 > Regards, Simon