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

Jean-Jacques Hiblot jjhiblot at ti.com
Fri Oct 26 11:14:16 UTC 2018


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 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 <jjhiblot at ti.com>
+#
+
+"""
+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



More information about the U-Boot mailing list