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

Simon Glass sjg at chromium.org
Tue Oct 9 16:20:27 UTC 2018


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?

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