From 48ae412424ddfda64f45a9d679a960357e57433e Mon Sep 17 00:00:00 2001 From: Alex Kiernan Date: Thu, 31 May 2018 04:48:34 +0000 Subject: [PATCH] buildman: Add support for environment delta in summary When summarising the builds, add the -U option to emit delta lines for the default environment built into U-Boot at each commit. Signed-off-by: Alex Kiernan Reviewed-by: Simon Glass --- tools/buildman/README | 28 +++++++++ tools/buildman/builder.py | 128 +++++++++++++++++++++++++++++++++----- tools/buildman/cmdline.py | 2 + tools/buildman/control.py | 3 +- 4 files changed, 145 insertions(+), 16 deletions(-) diff --git a/tools/buildman/README b/tools/buildman/README index 6c43c546f8..76601902cb 100644 --- a/tools/buildman/README +++ b/tools/buildman/README @@ -1008,6 +1008,34 @@ variables. This avoids lots of useless output when converting a CONFIG option to Kconfig. To disable this behaviour, use --squash-config-y. +Checking the environment +======================== + +When converting CONFIG options which manipulate the default environment, +a common requirement is to check that the default environment has not +changed due to the conversion. Buildman supports this with the -U option, +used after a build. This shows differences in the default environment +between one commit and the next. + +For example: + +$ buildman -b squash brppt1 -sU +boards.cfg is up to date. Nothing to do. +Summary of 2 commits for 3 boards (3 threads, 3 jobs per thread) +01: Migrate bootlimit to Kconfig +02: Squashed commit of the following: + c brppt1_mmc: altbootcmd=mmc dev 1; run mmcboot0; -> mmc dev 1; run mmcboot0 + c brppt1_spi: altbootcmd=mmc dev 1; run mmcboot0; -> mmc dev 1; run mmcboot0 + + brppt1_nand: altbootcmd=run usbscript + - brppt1_nand: altbootcmd=run usbscript +(no errors to report) + +This shows that commit 2 modified the value of 'altbootcmd' for 'brppt1_mmc' +and 'brppt1_spi', removing a trailing semicolon. 'brppt1_nand' gained an a +value for 'altbootcmd', but lost one for ' altbootcmd'. + +The -U option uses the u-boot.env files which are produced by a build. + Other options ============= diff --git a/tools/buildman/builder.py b/tools/buildman/builder.py index 2ccdee02a3..a5a2ffdfdf 100644 --- a/tools/buildman/builder.py +++ b/tools/buildman/builder.py @@ -127,6 +127,15 @@ class Config: val = val ^ hash(key) & hash(value) return val +class Environment: + """Holds information about environment variables for a board.""" + def __init__(self, target): + self.target = target + self.environment = {} + + def Add(self, key, value): + self.environment[key] = value + class Builder: """Class for building U-Boot for a particular commit. @@ -199,13 +208,17 @@ class Builder: value is itself a dictionary: key: config name value: config value + environment: Dictionary keyed by environment variable, Each + value is the value of environment variable. """ - def __init__(self, rc, err_lines, sizes, func_sizes, config): + def __init__(self, rc, err_lines, sizes, func_sizes, config, + environment): self.rc = rc self.err_lines = err_lines self.sizes = sizes self.func_sizes = func_sizes self.config = config + self.environment = environment def __init__(self, toolchains, base_dir, git_dir, num_threads, num_jobs, gnu_make='make', checkout=True, show_unknown=True, step=1, @@ -310,7 +323,8 @@ class Builder: def SetDisplayOptions(self, show_errors=False, show_sizes=False, show_detail=False, show_bloat=False, - list_error_boards=False, show_config=False): + list_error_boards=False, show_config=False, + show_environment=False): """Setup display options for the builder. show_errors: True to show summarised error/warning info @@ -319,6 +333,7 @@ class Builder: show_bloat: Show detail for each function list_error_boards: Show the boards which caused each error/warning show_config: Show config deltas + show_environment: Show environment deltas """ self._show_errors = show_errors self._show_sizes = show_sizes @@ -326,6 +341,7 @@ class Builder: self._show_bloat = show_bloat self._list_error_boards = list_error_boards self._show_config = show_config + self._show_environment = show_environment def _AddTimestamp(self): """Add a new timestamp to the list and record the build period. @@ -609,8 +625,33 @@ class Builder: config[key] = value return config + def _ProcessEnvironment(self, fname): + """Read in a uboot.env file + + This function reads in environment variables from a file. + + Args: + fname: Filename to read + + Returns: + Dictionary: + key: environment variable (e.g. bootlimit) + value: value of environment variable (e.g. 1) + """ + environment = {} + if os.path.exists(fname): + with open(fname) as fd: + for line in fd.read().split('\0'): + try: + key, value = line.split('=', 1) + environment[key] = value + except ValueError: + # ignore lines we can't parse + pass + return environment + def GetBuildOutcome(self, commit_upto, target, read_func_sizes, - read_config): + read_config, read_environment): """Work out the outcome of a build. Args: @@ -618,6 +659,7 @@ class Builder: target: Target board to check read_func_sizes: True to read function size information read_config: True to read .config and autoconf.h files + read_environment: True to read uboot.env files Returns: Outcome object @@ -627,6 +669,7 @@ class Builder: sizes = {} func_sizes = {} config = {} + environment = {} if os.path.exists(done_file): with open(done_file, 'r') as fd: return_code = int(fd.readline()) @@ -676,12 +719,18 @@ class Builder: fname = os.path.join(output_dir, name) config[name] = self._ProcessConfig(fname) - return Builder.Outcome(rc, err_lines, sizes, func_sizes, config) + if read_environment: + output_dir = self.GetBuildDir(commit_upto, target) + fname = os.path.join(output_dir, 'uboot.env') + environment = self._ProcessEnvironment(fname) + + return Builder.Outcome(rc, err_lines, sizes, func_sizes, config, + environment) - return Builder.Outcome(OUTCOME_UNKNOWN, [], {}, {}, {}) + return Builder.Outcome(OUTCOME_UNKNOWN, [], {}, {}, {}, {}) def GetResultSummary(self, boards_selected, commit_upto, read_func_sizes, - read_config): + read_config, read_environment): """Calculate a summary of the results of building a commit. Args: @@ -689,6 +738,7 @@ class Builder: commit_upto: Commit number to summarize (0..self.count-1) read_func_sizes: True to read function size information read_config: True to read .config and autoconf.h files + read_environment: True to read uboot.env files Returns: Tuple: @@ -705,6 +755,9 @@ class Builder: value is itself a dictionary: key: config name value: config value + Dictionary keyed by board.target. Each value is a dictionary: + key: environment variable + value: value of environment variable """ def AddLine(lines_summary, lines_boards, line, board): line = line.rstrip() @@ -720,10 +773,12 @@ class Builder: warn_lines_summary = [] warn_lines_boards = {} config = {} + environment = {} for board in boards_selected.itervalues(): outcome = self.GetBuildOutcome(commit_upto, board.target, - read_func_sizes, read_config) + read_func_sizes, read_config, + read_environment) board_dict[board.target] = outcome last_func = None last_was_warning = False @@ -756,8 +811,14 @@ class Builder: tconfig.Add(fname, key, value) config[board.target] = tconfig + tenvironment = Environment(board.target) + if outcome.environment: + for key, value in outcome.environment.iteritems(): + tenvironment.Add(key, value) + environment[board.target] = tenvironment + return (board_dict, err_lines_summary, err_lines_boards, - warn_lines_summary, warn_lines_boards, config) + warn_lines_summary, warn_lines_boards, config, environment) def AddOutcome(self, board_dict, arch_list, changes, char, color): """Add an output to our list of outcomes for each architecture @@ -810,12 +871,14 @@ class Builder: """ self._base_board_dict = {} for board in board_selected: - self._base_board_dict[board] = Builder.Outcome(0, [], [], {}, {}) + self._base_board_dict[board] = Builder.Outcome(0, [], [], {}, {}, + {}) self._base_err_lines = [] self._base_warn_lines = [] self._base_err_line_boards = {} self._base_warn_line_boards = {} self._base_config = None + self._base_environment = None def PrintFuncSizeDetail(self, fname, old, new): grow, shrink, add, remove, up, down = 0, 0, 0, 0, 0, 0 @@ -1010,8 +1073,8 @@ class Builder: def PrintResultSummary(self, board_selected, board_dict, err_lines, err_line_boards, warn_lines, warn_line_boards, - config, show_sizes, show_detail, show_bloat, - show_config): + config, environment, show_sizes, show_detail, + show_bloat, show_config, show_environment): """Compare results with the base results and display delta. Only boards mentioned in board_selected will be considered. This @@ -1036,10 +1099,13 @@ class Builder: value is itself a dictionary: key: config name value: config value + environment: Dictionary keyed by environment variable, Each + value is the value of environment variable. show_sizes: Show image size deltas show_detail: Show detail for each board show_bloat: Show detail for each function show_config: Show config changes + show_environment: Show environment changes """ def _BoardList(line, line_boards): """Helper function to get a line of boards containing a line @@ -1188,6 +1254,36 @@ class Builder: self.PrintSizeSummary(board_selected, board_dict, show_detail, show_bloat) + if show_environment and self._base_environment: + lines = [] + + for target in board_dict: + if target not in board_selected: + continue + + tbase = self._base_environment[target] + tenvironment = environment[target] + environment_plus = {} + environment_minus = {} + environment_change = {} + base = tbase.environment + for key, value in tenvironment.environment.iteritems(): + if key not in base: + environment_plus[key] = value + for key, value in base.iteritems(): + if key not in tenvironment.environment: + environment_minus[key] = value + for key, value in base.iteritems(): + new_value = tenvironment.environment.get(key) + if new_value and value != new_value: + desc = '%s -> %s' % (value, new_value) + environment_change[key] = desc + + _AddConfig(lines, target, environment_plus, environment_minus, + environment_change) + + _OutputConfigInfo(lines) + if show_config and self._base_config: summary = {} arch_config_plus = {} @@ -1294,6 +1390,7 @@ class Builder: self._base_err_line_boards = err_line_boards self._base_warn_line_boards = warn_line_boards self._base_config = config + self._base_environment = environment # Get a list of boards that did not get built, if needed not_built = [] @@ -1306,10 +1403,11 @@ class Builder: def ProduceResultSummary(self, commit_upto, commits, board_selected): (board_dict, err_lines, err_line_boards, warn_lines, - warn_line_boards, config) = self.GetResultSummary( + warn_line_boards, config, environment) = self.GetResultSummary( board_selected, commit_upto, read_func_sizes=self._show_bloat, - read_config=self._show_config) + read_config=self._show_config, + read_environment=self._show_environment) if commits: msg = '%02d: %s' % (commit_upto + 1, commits[commit_upto].subject) @@ -1317,8 +1415,8 @@ class Builder: self.PrintResultSummary(board_selected, board_dict, err_lines if self._show_errors else [], err_line_boards, warn_lines if self._show_errors else [], warn_line_boards, - config, self._show_sizes, self._show_detail, - self._show_bloat, self._show_config) + config, environment, self._show_sizes, self._show_detail, + self._show_bloat, self._show_config, self._show_environment) def ShowSummary(self, commits, board_selected): """Show a build summary for U-Boot for a given board list. diff --git a/tools/buildman/cmdline.py b/tools/buildman/cmdline.py index b8ddd4795c..e493b1ac4a 100644 --- a/tools/buildman/cmdline.py +++ b/tools/buildman/cmdline.py @@ -92,6 +92,8 @@ def ParseArgs(): default=None, help='Number of builder threads to use') parser.add_option('-u', '--show_unknown', action='store_true', default=False, help='Show boards with unknown build result') + parser.add_option('-U', '--show-environment', action='store_true', + default=False, help='Show environment changes in summary') parser.add_option('-v', '--verbose', action='store_true', default=False, help='Show build results while the build progresses') parser.add_option('-V', '--verbose-build', action='store_true', diff --git a/tools/buildman/control.py b/tools/buildman/control.py index 4ac4386db6..bc0819784f 100644 --- a/tools/buildman/control.py +++ b/tools/buildman/control.py @@ -319,7 +319,8 @@ def DoBuildman(options, args, toolchains=None, make_func=None, boards=None, builder.SetDisplayOptions(options.show_errors, options.show_sizes, options.show_detail, options.show_bloat, options.list_error_boards, - options.show_config) + options.show_config, + options.show_environment) if options.summary: builder.ShowSummary(commits, board_selected) else: -- 2.25.1