From patchwork Sat Jan 10 20:08:14 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1439 Return-Path: X-Original-To: u-boot-concept@u-boot.org Delivered-To: u-boot-concept@u-boot.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1768075784; bh=1hCnVb8UBty/SuM0I6EucgWqAHL1aVwgD3DRXzVo1zI=; h=From:To:Date:In-Reply-To:References:CC:Subject:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=wmsEc7t4QXqmQkW9VJu1A6OUPNZagLLl5NiMe6sgTdqJBY5ivlbnc1bVog6Nh4sRq TehMucTx5DLZjjugGpilazrpy/Ejd/qIPoujCHuFOIDi+qBFHRsFUV8GBF+6aNBUD/ DQJzYM0vQANu5mlJXSr0wMTJe0T1JfUzrACPomG0eUwkDOSUWF6wwzM7JQsmepnu+F K3XRgqi9J2ieEXDL4PZHf8efZtRQje4zcKumXIOMI58iz9RL9bCvC/AaXKRK51efFe qK+BESNTwYRBdtSCtW+tQvO9jAFKgscP0c3I6MBVKWpa/PgklnhLb1rYJwseLFGO/k 3xV3KWA/P+J9A== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 301F7690E7 for ; Sat, 10 Jan 2026 13:09:44 -0700 (MST) X-Virus-Scanned: Debian amavis at Received: from mail.u-boot.org ([127.0.0.1]) by localhost (mail.u-boot.org [127.0.0.1]) (amavis, port 10024) with ESMTP id B1vhEteYo98W for ; Sat, 10 Jan 2026 13:09:44 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1768075784; bh=1hCnVb8UBty/SuM0I6EucgWqAHL1aVwgD3DRXzVo1zI=; h=From:To:Date:In-Reply-To:References:CC:Subject:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=wmsEc7t4QXqmQkW9VJu1A6OUPNZagLLl5NiMe6sgTdqJBY5ivlbnc1bVog6Nh4sRq TehMucTx5DLZjjugGpilazrpy/Ejd/qIPoujCHuFOIDi+qBFHRsFUV8GBF+6aNBUD/ DQJzYM0vQANu5mlJXSr0wMTJe0T1JfUzrACPomG0eUwkDOSUWF6wwzM7JQsmepnu+F K3XRgqi9J2ieEXDL4PZHf8efZtRQje4zcKumXIOMI58iz9RL9bCvC/AaXKRK51efFe qK+BESNTwYRBdtSCtW+tQvO9jAFKgscP0c3I6MBVKWpa/PgklnhLb1rYJwseLFGO/k 3xV3KWA/P+J9A== Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 0AF0669275 for ; Sat, 10 Jan 2026 13:09:44 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1768075781; bh=zV2WeHtJdTkoAioQXTbEBl9fvlPf7dUtrXmVjJYiqhU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=AO4MxrNvmn8VIghnnuCx+jQuju7AWSU5/hI3aNttD/RsaRnOvJxt7PD7lYEFuA3qP t3DievZyfFRZcin2m6AGJTMSlXCzK/0qZ/RYlUa7qu9eSeLZh/Qy0vHf+gdwIvUK7X wfM74Z65gQij3V9kiq8Vdf6WITvK0UaW0T+q/Zl53djLygPVMz256FdyELiM9FakBo sc6LkqFySh1NsFKqLF1Hqvj876v8SJEO0r9p9uLuDitcbwRYVOfnt6uOVb2AlzyO6k ibg42xfP9ljv20NzIwJI0kSax/6n7cKQ8OYE2eKXvZx/mLbDJd8kEaaCdDQEFmTBCE 4GH35QmCP4O7A== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id CDCEA69275; Sat, 10 Jan 2026 13:09:41 -0700 (MST) X-Virus-Scanned: Debian amavis at Received: from mail.u-boot.org ([127.0.0.1]) by localhost (mail.u-boot.org [127.0.0.1]) (amavis, port 10026) with ESMTP id oYDgS8JQGev9; Sat, 10 Jan 2026 13:09:41 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1768075775; bh=NDYHKHo7c/fBukMgQqmwn23JMkcdAgJDLatAZ7ufTEw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=i4OiQk6q3npNJpxMUX6trzJ4dZKuVQTr2bIcdfEyb5GrNYTMY368NYk2Ck60unb1O LV4jRrTpOi+FEUIwCnOMPsGHqSpO97uTbbicfttvG8gg1YD/SDEYY7XTJs6WYSz6Cy VvwBONsscdsUp3xe3pRKq3fALG996t9wnvTV9ThOcFhHBy3qdaSfXnZ6k0j5aZNZGb iK/OV5r66XzVdvber0ovWKauYCGFyl+sZabkk6kOLFuXwwYQgm8VgkzLKq+k02JSdg hVehSnk3Zj+26Hn7X1lC28fGI/a746LFVxMh91HoNbY/oGDe+OrcvZryZrzZwUfUsr 1arjbEUr3hnnA== Received: from u-boot.org (unknown [73.34.74.121]) by mail.u-boot.org (Postfix) with ESMTPSA id C6B4E690E7; Sat, 10 Jan 2026 13:09:34 -0700 (MST) From: Simon Glass To: U-Boot Concept Date: Sat, 10 Jan 2026 13:08:14 -0700 Message-ID: <20260110200828.168672-12-sjg@u-boot.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260110200828.168672-1-sjg@u-boot.org> References: <20260110200828.168672-1-sjg@u-boot.org> MIME-Version: 1.0 Message-ID-Hash: SQFXY2XAEINJFTWBJZL4HN4ZQADLFGY3 X-Message-ID-Hash: SQFXY2XAEINJFTWBJZL4HN4ZQADLFGY3 X-MailFrom: sjg@u-boot.org X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: Simon Glass , "Claude Opus 4 . 5" X-Mailman-Version: 3.3.10 Precedence: list Subject: [Concept] [PATCH 11/18] buildman: Move error/warning display methods to ResultHandler List-Id: Discussion and patches related to U-Boot Concept Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: Simon Glass Continue extracting display methods from builder.py to ResultHandler. Move the error and warning display methods: - add_outcome(): Format board status by architecture - output_err_lines(): Display formatted error/warning lines - display_arch_results(): Show board status by architecture - print_ide_output(): Output errors to stderr for IDE The methods now return an error line count instead of updating a Builder attribute directly, making them more pure and testable. Update print_result_summary() to use the ResultHandler methods and track the error_lines counter locally. Co-developed-by: Claude Opus 4.5 Signed-off-by: Simon Glass --- tools/buildman/builder.py | 120 ++------------------------------ tools/buildman/resulthandler.py | 118 +++++++++++++++++++++++++++++++ 2 files changed, 124 insertions(+), 114 deletions(-) diff --git a/tools/buildman/builder.py b/tools/buildman/builder.py index 4b6106b881b..4d3b96ab1a0 100644 --- a/tools/buildman/builder.py +++ b/tools/buildman/builder.py @@ -1011,36 +1011,6 @@ class Builder: return (board_dict, err_lines_summary, err_lines_boards, warn_lines_summary, warn_lines_boards, config, environment) - def add_outcome(self, board_dict, arch_list, changes, char, color): - """Add an output to our list of outcomes for each architecture - - This simple function adds failing boards (changes) to the - relevant architecture string, so we can print the results out - sorted by architecture. - - Args: - board_dict (dict): Dict containing all boards - arch_list (dict): Dict keyed by arch name. Value is a string - containing a list of board names which failed for that arch. - changes (list): List of boards to add to arch_list - char (str): Character to display for this board - color (int): terminal.Colour object - """ - done_arch = {} - for target in changes: - if target in board_dict: - arch = board_dict[target].arch - else: - arch = 'unknown' - text = self.col.build(color, ' ' + target) - if arch not in done_arch: - text = f' {self.col.build(color, char)} {text}' - done_arch[arch] = True - if arch not in arch_list: - arch_list[arch] = text - else: - arch_list[arch] += text - def reset_result_summary(self, board_selected): """Reset the results summary ready for use. @@ -1347,87 +1317,6 @@ class Builder: tprint(f"{' '.join(sorted(targets))} :") self._output_config_info(lines.split('\n')) - def _output_err_lines(self, err_lines, colour): - """Output the line of error/warning lines, if not empty - - Also increments self._error_lines if err_lines not empty - - Args: - err_lines: List of ErrLine objects, each an error or warning - line, possibly including a list of boards with that - error/warning - colour: Colour to use for output - """ - if err_lines: - out_list = [] - for line in err_lines: - names = [brd.target for brd in line.brds] - board_str = ' '.join(names) if names else '' - if board_str: - out = self.col.build(colour, line.char + '(') - out += self.col.build(self.col.MAGENTA, board_str, - bright=False) - out += self.col.build(colour, f') {line.errline}') - else: - out = self.col.build(colour, line.char + line.errline) - out_list.append(out) - tprint('\n'.join(out_list)) - self._error_lines += 1 - - def _display_arch_results(self, board_selected, brd_status, better_err, - worse_err, better_warn, worse_warn): - """Display results by architecture - - Args: - board_selected (dict): Dict containing boards to summarise - brd_status (BoardStatus): Named tuple with board classifications - better_err: List of ErrLine for fixed errors - worse_err: List of ErrLine for new errors - better_warn: List of ErrLine for fixed warnings - worse_warn: List of ErrLine for new warnings - """ - if self._opts.ide: - return - if not any((brd_status.ok, brd_status.warn, brd_status.err, - brd_status.unknown, brd_status.new, worse_err, better_err, - worse_warn, better_warn)): - return - arch_list = {} - self.add_outcome(board_selected, arch_list, brd_status.ok, '', - self.col.GREEN) - self.add_outcome(board_selected, arch_list, brd_status.warn, 'w+', - self.col.YELLOW) - self.add_outcome(board_selected, arch_list, brd_status.err, '+', - self.col.RED) - self.add_outcome(board_selected, arch_list, brd_status.new, '*', - self.col.BLUE) - if self._opts.show_unknown: - self.add_outcome(board_selected, arch_list, brd_status.unknown, - '?', self.col.MAGENTA) - for arch, target_list in arch_list.items(): - tprint(f'{arch:>10s}: {target_list}') - self._error_lines += 1 - self._output_err_lines(better_err, colour=self.col.GREEN) - self._output_err_lines(worse_err, colour=self.col.RED) - self._output_err_lines(better_warn, colour=self.col.CYAN) - self._output_err_lines(worse_warn, colour=self.col.YELLOW) - - def _print_ide_output(self, board_selected, board_dict): - """Print output for IDE mode - - Args: - board_selected (dict): Dict of selected boards, keyed by target - board_dict (dict): Dict of boards that were built, keyed by target - """ - if not self._opts.ide: - return - for target in board_dict: - if target not in board_selected: - continue - outcome = board_dict[target] - for line in outcome.err_lines: - sys.stderr.write(line) - def print_result_summary(self, board_selected, board_dict, err_lines, err_line_boards, warn_lines, warn_line_boards, config, environment, show_sizes, show_detail, @@ -1527,11 +1416,14 @@ class Builder: self._base_warn_line_boards, warn_lines, warn_line_boards, 'w') # For the IDE mode, print out all the output - self._print_ide_output(board_selected, board_dict) + if self._opts.ide: + self._result_handler.print_ide_output(board_selected, board_dict) # Display results by arch - self._display_arch_results(board_selected, brd_status, better_err, - worse_err, better_warn, worse_warn) + if not self._opts.ide: + self._error_lines += self._result_handler.display_arch_results( + board_selected, brd_status, better_err, worse_err, better_warn, + worse_warn, self._opts.show_unknown) if show_sizes: self._result_handler.print_size_summary( diff --git a/tools/buildman/resulthandler.py b/tools/buildman/resulthandler.py index 4c9b3c2f9cc..56973d801bb 100644 --- a/tools/buildman/resulthandler.py +++ b/tools/buildman/resulthandler.py @@ -6,6 +6,8 @@ """Result writer for buildman build results""" +import sys + from u_boot_pylib.terminal import tprint @@ -301,3 +303,119 @@ class ResultHandler: if show_detail: self.print_size_detail(target_list, base_board_dict, board_dict, show_bloat) + + def add_outcome(self, board_dict, arch_list, changes, char, color): + """Add an output to our list of outcomes for each architecture + + This simple function adds failing boards (changes) to the + relevant architecture string, so we can print the results out + sorted by architecture. + + Args: + board_dict (dict): Dict containing all boards + arch_list (dict): Dict keyed by arch name. Value is a string + containing a list of board names which failed for that arch. + changes (list): List of boards to add to arch_list + char (str): Character to display for this board + color (int): terminal.Colour object + """ + done_arch = {} + for target in changes: + if target in board_dict: + arch = board_dict[target].arch + else: + arch = 'unknown' + text = self._col.build(color, ' ' + target) + if arch not in done_arch: + text = f' {self._col.build(color, char)} {text}' + done_arch[arch] = True + if arch not in arch_list: + arch_list[arch] = text + else: + arch_list[arch] += text + + def output_err_lines(self, err_lines, colour): + """Output the line of error/warning lines, if not empty + + Args: + err_lines: List of ErrLine objects, each an error or warning + line, possibly including a list of boards with that + error/warning + colour: Colour to use for output + + Returns: + int: 1 if any lines were output, 0 otherwise + """ + if err_lines: + out_list = [] + for line in err_lines: + names = [brd.target for brd in line.brds] + board_str = ' '.join(names) if names else '' + if board_str: + out = self._col.build(colour, line.char + '(') + out += self._col.build(self._col.MAGENTA, board_str, + bright=False) + out += self._col.build(colour, f') {line.errline}') + else: + out = self._col.build(colour, line.char + line.errline) + out_list.append(out) + tprint('\n'.join(out_list)) + return 1 + return 0 + + def display_arch_results(self, board_selected, brd_status, better_err, + worse_err, better_warn, worse_warn, show_unknown): + """Display results by architecture + + Args: + board_selected (dict): Dict containing boards to summarise + brd_status (BoardStatus): Named tuple with board classifications + better_err: List of ErrLine for fixed errors + worse_err: List of ErrLine for new errors + better_warn: List of ErrLine for fixed warnings + worse_warn: List of ErrLine for new warnings + show_unknown (bool): Whether to show unknown boards + + Returns: + int: Number of error lines output + """ + error_lines = 0 + if not any((brd_status.ok, brd_status.warn, brd_status.err, + brd_status.unknown, brd_status.new, worse_err, better_err, + worse_warn, better_warn)): + return error_lines + arch_list = {} + self.add_outcome(board_selected, arch_list, brd_status.ok, '', + self._col.GREEN) + self.add_outcome(board_selected, arch_list, brd_status.warn, 'w+', + self._col.YELLOW) + self.add_outcome(board_selected, arch_list, brd_status.err, '+', + self._col.RED) + self.add_outcome(board_selected, arch_list, brd_status.new, '*', + self._col.BLUE) + if show_unknown: + self.add_outcome(board_selected, arch_list, brd_status.unknown, + '?', self._col.MAGENTA) + for arch, target_list in arch_list.items(): + tprint(f'{arch:>10s}: {target_list}') + error_lines += 1 + error_lines += self.output_err_lines(better_err, colour=self._col.GREEN) + error_lines += self.output_err_lines(worse_err, colour=self._col.RED) + error_lines += self.output_err_lines(better_warn, colour=self._col.CYAN) + error_lines += self.output_err_lines(worse_warn, colour=self._col.YELLOW) + return error_lines + + @staticmethod + def print_ide_output(board_selected, board_dict): + """Print output for IDE mode + + Args: + board_selected (dict): Dict of selected boards, keyed by target + board_dict (dict): Dict of boards that were built, keyed by target + """ + for target in board_dict: + if target not in board_selected: + continue + outcome = board_dict[target] + for line in outcome.err_lines: + sys.stderr.write(line)