[U-Boot] [RFC PATCH v2 2/3] tools: Add a tool to get a list of defconfigs based on filters

Jean-Jacques Hiblot jjhiblot at ti.com
Thu Oct 18 14:36:45 UTC 2018



On 09/10/2018 18:20, Simon Glass wrote:
> Hi Jean-Jacques,
>
> On 3 October 2018 at 07:53, Jean-Jacques Hiblot <jjhiblot at ti.com> 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 <jjhiblot at ti.com>
>> ---
>>
>> 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 <jjhiblot at ti.com>
>> +#
>> +
>> +"""
>> +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?
No it doesn't. You can run this program as-is with python2 or python3.

>
>> +
>> +    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
>



More information about the U-Boot mailing list