From mboxrd@z Thu Jan 1 00:00:00 1970 From: Jean-Jacques Hiblot Date: Fri, 26 Oct 2018 13:14:16 +0200 Subject: [U-Boot] [RFC PATCH v3 2/3] tools: Add a tool to get a list of defconfigs based on filters In-Reply-To: <1540552457-27467-1-git-send-email-jjhiblot@ti.com> References: <1540552457-27467-1-git-send-email-jjhiblot@ti.com> Message-ID: <1540552457-27467-3-git-send-email-jjhiblot@ti.com> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de 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 v3: - Add more comments to describe the classes and functions - Capitalize the Class names Changes in v2: New tools/find_defconfigs.py | 204 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 204 insertions(+) create mode 100755 tools/find_defconfigs.py diff --git a/tools/find_defconfigs.py b/tools/find_defconfigs.py new file mode 100755 index 0000000..aac5212 --- /dev/null +++ b/tools/find_defconfigs.py @@ -0,0 +1,204 @@ +#!/usr/bin/env python +# SPDX-License-Identifier: GPL-2.0+ +# +# Author: JJ Hiblot +# + +""" +Output a list of defconfig-matching criteria. + +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 argparse +import os +import re + + +class Board: + + """A placeholder for properties read from boards.cfg""" + + 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): + """Show the properties of a board + + Args: + sep: a separator insertyed between the properties for readability + props: the list of properties we want to display + """ + 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([getattr(self, prop) for prop in props])) + + def match(self, rules): + """ match a board against a set of rules + + Args: + rules: a set of rules. a rule is an object that offers a 'match(str)' + method, usually a compiled regexp. + Returns: + True if the board matches all of the rules, False otherwise + """ + 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' + If boards.cfg does not exit, it is generated with tools/genboardscfg.py + boards.cfg is parsed to create a list of Board objects + + Returns: + A list of Board objects that have been created based on the information + found in 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): + """ Augment a command line parser with a list of options commonly used to + filter the targets (vendor, arch, cpu, soc, board, target) + + Args: + parser: The parser to augment + """ + 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()): + """ Construct a list of boards matching criteria defined in args and + listed in fields + + Args: + args: an object that has some members such as 'soc','cpu' etc. + The values of those members are strings that will be used to compile + a regexp object. It must have a boolean member named "ignore_case". + fields: a list of names of the members we are interested in. + + Returns: + A list of Board objects matching the given criteria + """ + + # 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 = ["defconfig"] + [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