[PATCH v3 13/81] buildman: Detect boards with multiple CONFIG_TARGETs defined

Simon Glass sjg at chromium.org
Sun Jul 16 02:35:41 CEST 2023


The TARGET_xxx options are special in that they refer to a single target.
Exactly one should be enabled for each target, corresponding to a
defconfig file.

Detect configs which result in two TARGET_xxx options being set. For
example, at present, TARGET_POLEG and TARET_POLEG_EVB are enabled for the
same board.

Note: This warning is not displayed by default. An option will be added
to enable it.

Signed-off-by: Simon Glass <sjg at chromium.org>
---

Changes in v3:
- Add new patch to detect boards with multiple CONFIG_TARGETs defined

 tools/buildman/boards.py    | 73 +++++++++++++++++++++++++------------
 tools/buildman/func_test.py | 20 +++++++++-
 2 files changed, 68 insertions(+), 25 deletions(-)

diff --git a/tools/buildman/boards.py b/tools/buildman/boards.py
index 794e6fcf63bf..31831f383750 100644
--- a/tools/buildman/boards.py
+++ b/tools/buildman/boards.py
@@ -220,16 +220,17 @@ class KconfigScanner:
             defconfig (str): path to the defconfig file to be processed
 
         Returns:
-            A dictionary of board parameters.  It has a form of:
-            {
-                'arch': <arch_name>,
-                'cpu': <cpu_name>,
-                'soc': <soc_name>,
-                'vendor': <vendor_name>,
-                'board': <board_name>,
-                'target': <target_name>,
-                'config': <config_header_name>,
-            }
+            tuple: dictionary of board parameters.  It has a form of:
+                {
+                    'arch': <arch_name>,
+                    'cpu': <cpu_name>,
+                    'soc': <soc_name>,
+                    'vendor': <vendor_name>,
+                    'board': <board_name>,
+                    'target': <target_name>,
+                    'config': <config_header_name>,
+                }
+            warnings (list of str): list of warnings found
         """
         leaf = os.path.basename(defconfig)
         expect_target, match, rear = leaf.partition('_defconfig')
@@ -239,6 +240,7 @@ class KconfigScanner:
         self._tmpfile = None
 
         params = {}
+        warnings = []
 
         # Get the value of CONFIG_SYS_ARCH, CONFIG_SYS_CPU, ... etc.
         # Set '-' if the value is empty.
@@ -249,6 +251,17 @@ class KconfigScanner:
             else:
                 params[key] = '-'
 
+        # Check there is exactly one TARGET_xxx set
+        target = None
+        for name, sym in self._conf.syms.items():
+            if name.startswith('TARGET_') and sym.str_value == 'y':
+                tname = name[7:].lower()
+                if target:
+                    warnings.append(
+                        f'WARNING: {leaf}: Duplicate TARGET_xxx: {target} and {tname}')
+                else:
+                    target = tname
+
         params['target'] = expect_target
 
         # fix-up for aarch64
@@ -266,7 +279,7 @@ class KconfigScanner:
             else:
                 params['arch'] = 'riscv64'
 
-        return params
+        return params, warnings
 
 
 class MaintainersDatabase:
@@ -658,11 +671,19 @@ class Boards:
             queue.put(kconf_scanner.scan(defconfig))
 
     @classmethod
-    def read_queues(cls, queues, params_list):
-        """Read the queues and append the data to the paramers list"""
+    def read_queues(cls, queues, params_list, warnings):
+        """Read the queues and append the data to the paramers list
+
+        Args:
+            queues (list of multiprocessing.Queue): Queues to read
+            params_list (list of dict): List to add params too
+            warnings (set of str): Set to add warnings to
+        """
         for que in queues:
             while not que.empty():
-                params_list.append(que.get())
+                params, warn = que.get()
+                params_list.append(params)
+                warnings.update(warn)
 
     def scan_defconfigs(self, config_dir, srcdir, jobs=1):
         """Collect board parameters for all defconfig files.
@@ -675,9 +696,12 @@ class Boards:
             jobs (int): The number of jobs to run simultaneously
 
         Returns:
-            list of dict: List of board parameters, each a dict:
-                key: 'arch', 'cpu', 'soc', 'vendor', 'board', 'target', 'config'
-                value: string value of the key
+            tuple:
+                list of dict: List of board parameters, each a dict:
+                    key: 'arch', 'cpu', 'soc', 'vendor', 'board', 'target',
+                        'config'
+                    value: string value of the key
+                list of str: List of warnings recorded
         """
         all_defconfigs = []
         for (dirpath, _, filenames) in os.walk(config_dir):
@@ -700,13 +724,14 @@ class Boards:
             processes.append(proc)
             queues.append(que)
 
-        # The resulting data should be accumulated to this list
+        # The resulting data should be accumulated to these lists
         params_list = []
+        warnings = set()
 
         # Data in the queues should be retrieved preriodically.
         # Otherwise, the queues would become full and subprocesses would get stuck.
         while any(p.is_alive() for p in processes):
-            self.read_queues(queues, params_list)
+            self.read_queues(queues, params_list, warnings)
             # sleep for a while until the queues are filled
             time.sleep(SLEEP_TIME)
 
@@ -716,9 +741,9 @@ class Boards:
             proc.join()
 
         # retrieve leftover data
-        self.read_queues(queues, params_list)
+        self.read_queues(queues, params_list, warnings)
 
-        return params_list
+        return params_list, sorted(list(warnings))
 
     @classmethod
     def insert_maintainers_info(cls, srcdir, params_list):
@@ -797,9 +822,9 @@ class Boards:
                     value: string value of the key
                 list of str: Warnings that came up
         """
-        params_list = self.scan_defconfigs(config_dir, srcdir, jobs)
-        warnings = self.insert_maintainers_info(srcdir, params_list)
-        return params_list, warnings
+        params_list, warnings = self.scan_defconfigs(config_dir, srcdir, jobs)
+        m_warnings = self.insert_maintainers_info(srcdir, params_list)
+        return params_list, warnings + m_warnings
 
     def ensure_board_list(self, output, jobs=1, force=False, quiet=False):
         """Generate a board database file if needed.
diff --git a/tools/buildman/func_test.py b/tools/buildman/func_test.py
index 73abe16e1ca5..e7e22da62b15 100644
--- a/tools/buildman/func_test.py
+++ b/tools/buildman/func_test.py
@@ -794,10 +794,11 @@ CONFIG_LOCALVERSION=y
 
         # Scan the test directory which contains a Kconfig and some *_defconfig
         # files
-        params = self._boards.scan_defconfigs(src, src)
+        params, warnings = self._boards.scan_defconfigs(src, src)
 
         # We should get two boards
         self.assertEquals(2, len(params))
+        self.assertFalse(warnings)
         first = 0 if params[0]['target'] == 'board0' else 1
         board0 = params[first]
         board2 = params[1 - first]
@@ -882,6 +883,7 @@ Active  aarch64     armv8 - armltd total_compute board2
         src = self._git_dir
         main = os.path.join(src, 'boards', 'board0', 'MAINTAINERS')
         other = os.path.join(src, 'boards', 'board2', 'MAINTAINERS')
+        kc_file = os.path.join(src, 'Kconfig')
         config_dir = os.path.join(src, 'configs')
         params_list, warnings = self._boards.build_board_list(config_dir, src)
 
@@ -946,3 +948,19 @@ Active  aarch64     armv8 - armltd total_compute board2
         self.assertEquals(
             ['WARNING: boards/board0/MAINTAINERS: missing defconfig ending at line 16'],
              warnings)
+
+        # Add another TARGET to the Kconfig
+        tools.write_file(main, data, binary=False)
+        extra = (b'''
+if TARGET_BOARD2
+config TARGET_OTHER
+\tbool "other"
+\tdefault y
+endif
+''')
+        tools.write_file(kc_file, tools.read_file(kc_file) + extra)
+        params_list, warnings = self._boards.build_board_list(config_dir, src)
+        self.assertEquals(2, len(params_list))
+        self.assertEquals(
+            ['WARNING: board2_defconfig: Duplicate TARGET_xxx: board2 and other'],
+             warnings)
-- 
2.41.0.455.g037347b96a-goog



More information about the U-Boot mailing list