[Concept,04/11] buildman: Add RunRequest named tuple for run_commit() parameters

Message ID 20260105183030.1487468-5-sjg@u-boot.org
State New
Headers
Series buildman: Refactor control and builderthread |

Commit Message

Simon Glass Jan. 5, 2026, 6:30 p.m. UTC
  From: Simon Glass <simon.glass@canonical.com>

Introduce a RunRequest named tuple to group the parameters that don't
change during a job's for loop in run_job()

This includes:
- brd: Board to build
- work_dir: Directory for source checkout
- work_in_output: Whether to use output directory as work directory
- adjust_cfg: Config adjustments
- fragments: Config fragments

This reduces the run_commit() signature from 11 parameters to 7, and
simplifies passing these values through to _decide_dirs() and
_config_and_build()

Co-developed-by: Claude Opus 4.5 <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
---

 tools/buildman/builderthread.py | 158 ++++++++++++++++----------------
 1 file changed, 79 insertions(+), 79 deletions(-)
  

Patch

diff --git a/tools/buildman/builderthread.py b/tools/buildman/builderthread.py
index c480f4888a1..eda2b0083d4 100644
--- a/tools/buildman/builderthread.py
+++ b/tools/buildman/builderthread.py
@@ -8,6 +8,7 @@  This module provides the BuilderThread class, which handles calling the builder
 based on the jobs provided.
 """
 
+from collections import namedtuple
 import errno
 import glob
 import io
@@ -20,6 +21,23 @@  from u_boot_pylib import command
 from u_boot_pylib import gitutil
 from u_boot_pylib import tools
 
+# Named tuple for run_commit() options that don't change during a job
+#
+# Members:
+#     brd (Board): Board to build
+#     work_dir (str): Directory to which the source will be checked out
+#     work_in_output (bool): Use the output directory as the work directory and
+#         don't write to a separate output directory
+#     adjust_cfg (list of str): List of changes to make to .config file before
+#         building. Each is one of (where C is either CONFIG_xxx or just xxx):
+#             C to enable C
+#             ~C to disable C
+#             C=val to set the value of C (val must have quotes if C is a
+#                 string Kconfig
+#     fragments (str): Config fragments added to defconfig
+RunRequest = namedtuple('RunRequest', ['brd', 'work_dir', 'work_in_output',
+                                       'adjust_cfg', 'fragments'])
+
 RETURN_CODE_RETRY = -1
 BASE_ELF_FILENAMES = ['u-boot', 'spl/u-boot-spl', 'tpl/u-boot-tpl']
 
@@ -384,28 +402,26 @@  class BuilderThread(threading.Thread):
 
         return will_build, result
 
-    def _decide_dirs(self, brd, work_dir, work_in_output):
+    def _decide_dirs(self, req):
         """Decide the output directory to use
 
         Args:
-            work_dir (str): Directory to which the source will be checked out
-            work_in_output (bool): Use the output directory as the work
-                directory and don't write to a separate output directory.
+            req (RunRequest): Run request (see RunRequest for details)
 
         Returns:
             tuple:
                 out_dir (str): Output directory for the build
-                out_rel_dir (str): Output directory relatie to the current dir
+                out_rel_dir (str): Output directory relative to the current dir
         """
-        if work_in_output or self.builder.in_tree:
+        if req.work_in_output or self.builder.in_tree:
             out_rel_dir = None
-            out_dir = work_dir
+            out_dir = req.work_dir
         else:
             if self.per_board_out_dir:
-                out_rel_dir = os.path.join('..', brd.target)
+                out_rel_dir = os.path.join('..', req.brd.target)
             else:
                 out_rel_dir = 'build'
-            out_dir = os.path.join(work_dir, out_rel_dir)
+            out_dir = os.path.join(req.work_dir, out_rel_dir)
         return out_dir, out_rel_dir
 
     def _checkout(self, commit_upto, work_dir):
@@ -427,24 +443,20 @@  class BuilderThread(threading.Thread):
             commit = 'current'
         return commit
 
-    def _config_and_build(self, commit_upto, brd, work_dir, do_config, mrproper,
-                          config_only, adjust_cfg, commit, out_dir, out_rel_dir,
-                          fragments, result):
+    def _config_and_build(self, req, commit_upto, do_config, mrproper,
+                          config_only, commit, out_dir, out_rel_dir, result):
         """Do the build, configuring first if necessary
 
         Args:
+            req (RunRequest): Run request (see RunRequest for details)
             commit_upto (int): Commit number to build (0...n-1)
-            brd (Board): Board to create arguments for
-            work_dir (str): Directory to which the source will be checked out
             do_config (bool): True to run a make <board>_defconfig on the source
             mrproper (bool): True to run mrproper first
             config_only (bool): Only configure the source, do not build it
-            adjust_cfg (list of str): See the cfgutil module and run_commit()
-            commit (Commit): Commit only being built
+            commit (Commit): Commit being built
             out_dir (str): Output directory for the build, or None to use
                current
-            out_rel_dir (str): Output directory relatie to the current dir
-            fragments (str): config fragments added to defconfig
+            out_rel_dir (str): Output directory relative to the current dir
             result (CommandResult): Previous result
 
         Returns:
@@ -458,17 +470,17 @@  class BuilderThread(threading.Thread):
         if out_dir and not os.path.exists(out_dir):
             mkdir(out_dir)
 
-        args, cwd, src_dir = self._build_args(brd, out_dir, out_rel_dir,
-                                              work_dir, commit_upto)
-        if brd.extended:
-            config_args = [f'{brd.orig_target}_defconfig']
-            for frag in brd.extended.fragments:
+        args, cwd, src_dir = self._build_args(req.brd, out_dir, out_rel_dir,
+                                              req.work_dir, commit_upto)
+        if req.brd.extended:
+            config_args = [f'{req.brd.orig_target}_defconfig']
+            for frag in req.brd.extended.fragments:
                 fname = os.path.join(f'{frag}.config')
                 config_args.append(fname)
         else:
-            config_args = [f'{brd.target}_defconfig']
-        if fragments is not None:
-            config_args.extend(fragments.split(','))
+            config_args = [f'{req.brd.target}_defconfig']
+        if req.fragments is not None:
+            config_args.extend(req.fragments.split(','))
         config_out = io.StringIO()
 
         _remove_old_outputs(out_dir)
@@ -476,26 +488,26 @@  class BuilderThread(threading.Thread):
         # If we need to reconfigure, do that now
         cfg_file = os.path.join(out_dir or '', '.config')
         cmd_list = []
-        if do_config or adjust_cfg:
+        if do_config or req.adjust_cfg:
             result = self._reconfigure(
-                commit, brd, cwd, args, env, config_args, config_out, cmd_list,
-                mrproper)
+                commit, req.brd, cwd, args, env, config_args, config_out,
+                cmd_list, mrproper)
             do_config = False   # No need to configure next time
-            if adjust_cfg:
-                cfgutil.adjust_cfg_file(cfg_file, adjust_cfg)
+            if req.adjust_cfg:
+                cfgutil.adjust_cfg_file(cfg_file, req.adjust_cfg)
 
         # Now do the build, if everything looks OK
         if result.return_code == 0:
-            if adjust_cfg:
+            if req.adjust_cfg:
                 oldc_args = list(args) + ['oldconfig']
-                oldc_result = self.make(commit, brd, 'oldconfig', cwd,
+                oldc_result = self.make(commit, req.brd, 'oldconfig', cwd,
                                         *oldc_args, env=env)
                 if oldc_result.return_code:
                     return oldc_result
-            result = self._build(commit, brd, cwd, args, env, cmd_list,
+            result = self._build(commit, req.brd, cwd, args, env, cmd_list,
                                  config_only)
-            if adjust_cfg:
-                errs = cfgutil.check_cfg_file(cfg_file, adjust_cfg)
+            if req.adjust_cfg:
+                errs = cfgutil.check_cfg_file(cfg_file, req.adjust_cfg)
                 if errs:
                     result.stderr += errs
                     result.return_code = 1
@@ -505,34 +517,22 @@  class BuilderThread(threading.Thread):
         result.cmd_list = cmd_list
         return result, do_config
 
-    def run_commit(self, commit_upto, brd, work_dir, do_config, mrproper,
-                   config_only, force_build, force_build_failures,
-                   work_in_output, adjust_cfg, fragments):
+    def run_commit(self, req, commit_upto, do_config, mrproper, config_only,
+                   force_build, force_build_failures):
         """Build a particular commit.
 
         If the build is already done, and we are not forcing a build, we skip
         the build and just return the previously-saved results.
 
         Args:
+            req (RunRequest): Run request (see RunRequest for details)
             commit_upto (int): Commit number to build (0...n-1)
-            brd (Board): Board to build
-            work_dir (str): Directory to which the source will be checked out
             do_config (bool): True to run a make <board>_defconfig on the source
             mrproper (bool): True to run mrproper first
             config_only (bool): Only configure the source, do not build it
             force_build (bool): Force a build even if one was previously done
-            force_build_failures (bool): Force a bulid if the previous result
+            force_build_failures (bool): Force a build if the previous result
                 showed failure
-            work_in_output (bool) : Use the output directory as the work
-                directory and don't write to a separate output directory.
-            adjust_cfg (list of str): List of changes to make to .config file
-                before building. Each is one of (where C is either CONFIG_xxx
-                or just xxx):
-                     C to enable C
-                     ~C to disable C
-                     C=val to set the value of C (val must have quotes if C is
-                         a string Kconfig
-            fragments (str): config fragments added to defconfig
 
         Returns:
             tuple containing:
@@ -541,10 +541,11 @@  class BuilderThread(threading.Thread):
         """
         # Create a default result - it will be overwritte by the call to
         # self.make() below, in the event that we do a build.
-        out_dir, out_rel_dir = self._decide_dirs(brd, work_dir, work_in_output)
+        out_dir, out_rel_dir = self._decide_dirs(req)
 
         # Check if the job was already completed last time
-        will_build, result = self._read_done_file(commit_upto, brd, force_build,
+        will_build, result = self._read_done_file(commit_upto, req.brd,
+                                                  force_build,
                                                   force_build_failures)
 
         kconfig_reconfig = False
@@ -552,33 +553,33 @@  class BuilderThread(threading.Thread):
             # We are going to have to build it. First, get a toolchain
             if not self.toolchain:
                 try:
-                    self.toolchain = self.builder.toolchains.select(brd.arch)
+                    self.toolchain = self.builder.toolchains.select(
+                        req.brd.arch)
                 except ValueError as err:
                     result.return_code = 10
                     result.stdout = ''
-                    result.stderr = (f'Tool chain error for {brd.arch}: '
+                    result.stderr = (f'Tool chain error for {req.brd.arch}: '
                                      f'{str(err)}')
 
             if self.toolchain:
-                commit = self._checkout(commit_upto, work_dir)
+                commit = self._checkout(commit_upto, req.work_dir)
 
                 # Check if Kconfig files have changed since last config
                 if self.builder.kconfig_check:
                     config_file = os.path.join(out_dir, '.config')
-                    if kconfig_changed_since(config_file, work_dir,
-                                             brd.target):
+                    if kconfig_changed_since(config_file, req.work_dir,
+                                             req.brd.target):
                         kconfig_reconfig = True
                         do_config = True
 
                 result, do_config = self._config_and_build(
-                    commit_upto, brd, work_dir, do_config, mrproper,
-                    config_only, adjust_cfg, commit, out_dir, out_rel_dir,
-                    fragments, result)
+                    req, commit_upto, do_config, mrproper, config_only,
+                    commit, out_dir, out_rel_dir, result)
             result.already_done = False
             result.kconfig_reconfig = kconfig_reconfig
 
         result.toolchain = self.toolchain
-        result.brd = brd
+        result.brd = req.brd
         result.commit_upto = commit_upto
         result.out_dir = out_dir
         return result, do_config
@@ -761,29 +762,29 @@  class BuilderThread(threading.Thread):
         brd = job.brd
         work_dir = self.builder.get_thread_dir(self.thread_num)
         self.toolchain = None
+        req = RunRequest(brd, work_dir, job.work_in_output, job.adjust_cfg,
+                         job.fragments)
         if job.commits:
             # Run 'make board_defconfig' on the first commit
             do_config = True
             commit_upto  = 0
             force_build = False
             for commit_upto in range(0, len(job.commits), job.step):
-                result, request_config = self.run_commit(commit_upto, brd,
-                        work_dir, do_config, self.mrproper,
+                result, request_config = self.run_commit(
+                        req, commit_upto, do_config, self.mrproper,
                         self.builder.config_only,
                         force_build or self.builder.force_build,
-                        self.builder.force_build_failures,
-                        job.work_in_output, job.adjust_cfg, job.fragments)
+                        self.builder.force_build_failures)
                 failed = result.return_code
                 did_config = do_config
                 if failed and not do_config and not self.mrproper:
                     # If our incremental build failed, try building again
                     # with a reconfig.
                     if self.builder.force_config_on_failure:
-                        result, request_config = self.run_commit(commit_upto,
-                            brd, work_dir, True,
+                        result, request_config = self.run_commit(
+                            req, commit_upto, True,
                             self.mrproper or self.builder.fallback_mrproper,
-                            False, True, False, job.work_in_output,
-                            job.adjust_cfg, job.fragments)
+                            False, True, False)
                         did_config = True
                 if not self.builder.force_reconfig:
                     do_config = request_config
@@ -826,17 +827,16 @@  class BuilderThread(threading.Thread):
                 self._send_result(result)
         else:
             # Just build the currently checked-out build
-            result, request_config = self.run_commit(None, brd, work_dir, True,
-                        self.mrproper, self.builder.config_only, True,
-                        self.builder.force_build_failures, job.work_in_output,
-                        job.adjust_cfg, job.fragments)
+            result, request_config = self.run_commit(
+                        req, None, True, self.mrproper,
+                        self.builder.config_only, True,
+                        self.builder.force_build_failures)
             failed = result.return_code
             if failed and not self.mrproper:
-                result, request_config = self.run_commit(None, brd, work_dir,
-                            True, self.builder.fallback_mrproper,
+                result, request_config = self.run_commit(
+                            req, None, True, self.builder.fallback_mrproper,
                             self.builder.config_only, True,
-                            self.builder.force_build_failures,
-                            job.work_in_output, job.adjust_cfg, job.fragments)
+                            self.builder.force_build_failures)
 
             result.commit_upto = 0
             self._write_result(result, job.keep_outputs, job.work_in_output)