From 2b4806e481026df7364cb9ed53ffc577e3dc59bb Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 22 Jan 2022 05:07:33 -0700 Subject: [PATCH] buildman: Allow adjusting board config on the fly Add a -a option to specify changes to the config before the build commences. For example buildman -a ~CONFIG_CMDLINE disables CONFIG_CMDLINE before doing the build. This makes it easier to try things out as well as to write tests without creating a new board or manually manging the .config file. Signed-off-by: Simon Glass --- tools/buildman/README | 49 +++++++++++++++++++++++++++++++++ tools/buildman/builder.py | 14 +++++++++- tools/buildman/builderthread.py | 30 ++++++++++++++++---- tools/buildman/cmdline.py | 2 ++ tools/buildman/control.py | 6 +++- 5 files changed, 93 insertions(+), 8 deletions(-) diff --git a/tools/buildman/README b/tools/buildman/README index ce27788432..bafb3b065c 100644 --- a/tools/buildman/README +++ b/tools/buildman/README @@ -1095,6 +1095,55 @@ This will write the full build into /tmp/build including object files. You must specify the output directory with -o when using -w. +Changing the configuration +========================== + +Sometimes it is useful to change the CONFIG options for a build on the fly. This +can be used to build a board (or multiple) with a few changes to see the impact. +The -a option supports this: + + -a + +where is a CONFIG option (with or without the CONFIG_ prefix) to enable. +For example: + + buildman -a CMD_SETEXPR_FMT + +will build with CONFIG_CMD_SETEXPR_FMT enabled. + +You can disable options by preceding them with tilde (~). You can specify the +-a option multiple times: + + buildman -a CMD_SETEXPR_FMT -a ~CMDLINE + +Some options have values, in which case you can change them: + + buildman -a 'BOOTCOMMAND="echo hello"' CONFIG_SYS_LOAD_ADDR=0x1000 + +Note that you must put quotes around string options and the whole thing must be +in single quotes, to make sure the shell leave it alone. + +If you try to set an option that does not exist, or that cannot be changed for +some other reason (e.g. it is 'selected' by another option), then buildman +shows an error: + + buildman --board sandbox -a FRED + Building current source for 1 boards (1 thread, 32 jobs per thread) + 0 0 0 /1 -1 (starting)errs + Some CONFIG adjustments did not take effect. This may be because + the request CONFIGs do not exist or conflict with others. + + Failed adjustments: + + FRED Missing expected line: CONFIG_FRED=y + + +One major caveat with this feature with branches (-b) is that buildman does not +name the output directories differently when you change the configuration, so +doing the same build again with different configuration will not trigger a +rebuild. You can use -f to work around that. + + Other options ============= diff --git a/tools/buildman/builder.py b/tools/buildman/builder.py index 122f0d1406..720bbb2cf4 100644 --- a/tools/buildman/builder.py +++ b/tools/buildman/builder.py @@ -250,7 +250,7 @@ class Builder: mrproper=False, per_board_out_dir=False, config_only=False, squash_config_y=False, warnings_as_errors=False, work_in_output=False, - test_thread_exceptions=False): + test_thread_exceptions=False, adjust_cfg=None): """Create a new Builder object Args: @@ -280,6 +280,15 @@ class Builder: test_thread_exceptions: Uses for tests only, True to make the threads raise an exception instead of reporting their result. This simulates a failure in the code somewhere + adjust_cfg_list (list of str): List of changes to make to .config + file before building. Each is one of (where C is the config + option with or without the CONFIG_ prefix) + + 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 + """ self.toolchains = toolchains self.base_dir = base_dir @@ -315,6 +324,8 @@ class Builder: self.squash_config_y = squash_config_y self.config_filenames = BASE_CONFIG_FILENAMES self.work_in_output = work_in_output + self.adjust_cfg = adjust_cfg + if not self.squash_config_y: self.config_filenames += EXTRA_CONFIG_FILENAMES self._terminated = False @@ -1747,6 +1758,7 @@ class Builder: job.commits = commits job.keep_outputs = keep_outputs job.work_in_output = self.work_in_output + job.adjust_cfg = self.adjust_cfg job.step = self._step if self.num_threads: self.queue.put(job) diff --git a/tools/buildman/builderthread.py b/tools/buildman/builderthread.py index 0faa3ac938..ecb285c0bf 100644 --- a/tools/buildman/builderthread.py +++ b/tools/buildman/builderthread.py @@ -9,6 +9,7 @@ import shutil import sys import threading +from buildman import cfgutil from patman import command from patman import gitutil @@ -130,7 +131,8 @@ class BuilderThread(threading.Thread): **kwargs) def RunCommit(self, commit_upto, brd, work_dir, do_config, config_only, - force_build, force_build_failures, work_in_output): + force_build, force_build_failures, work_in_output, + adjust_cfg): """Build a particular commit. If the build is already done, and we are not forcing a build, we skip @@ -147,6 +149,13 @@ class BuilderThread(threading.Thread): failure work_in_output: 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 Returns: tuple containing: @@ -261,7 +270,8 @@ class BuilderThread(threading.Thread): os.remove(fname) # If we need to reconfigure, do that now - if do_config: + cfg_file = os.path.join(out_dir, '.config') + if do_config or adjust_cfg: config_out = '' if self.mrproper: result = self.Make(commit, brd, 'mrproper', cwd, @@ -271,11 +281,19 @@ class BuilderThread(threading.Thread): *(args + config_args), env=env) config_out += result.combined do_config = False # No need to configure next time + if adjust_cfg: + cfgutil.adjust_cfg_file(cfg_file, adjust_cfg) if result.return_code == 0: if config_only: args.append('cfg') result = self.Make(commit, brd, 'build', cwd, *args, env=env) + if adjust_cfg: + errs = cfgutil.check_cfg_file(cfg_file, adjust_cfg) + if errs: + print('errs', errs) + result.stderr += errs + result.return_code = 1 result.stderr = result.stderr.replace(src_dir + '/', '') if self.builder.verbose_build: result.stdout = config_out + result.stdout @@ -486,7 +504,7 @@ class BuilderThread(threading.Thread): work_dir, do_config, self.builder.config_only, force_build or self.builder.force_build, self.builder.force_build_failures, - work_in_output=job.work_in_output) + job.work_in_output, job.adjust_cfg) failed = result.return_code or result.stderr did_config = do_config if failed and not do_config: @@ -495,7 +513,7 @@ class BuilderThread(threading.Thread): if self.builder.force_config_on_failure: result, request_config = self.RunCommit(commit_upto, brd, work_dir, True, False, True, False, - work_in_output=job.work_in_output) + job.work_in_output, job.adjust_cfg) did_config = True if not self.builder.force_reconfig: do_config = request_config @@ -540,8 +558,8 @@ class BuilderThread(threading.Thread): # Just build the currently checked-out build result, request_config = self.RunCommit(None, brd, work_dir, True, self.builder.config_only, True, - self.builder.force_build_failures, - work_in_output=job.work_in_output) + self.builder.force_build_failures, job.work_in_output, + job.adjust_cfg) result.commit_upto = 0 self._WriteResult(result, job.keep_outputs, job.work_in_output) self._SendResult(result) diff --git a/tools/buildman/cmdline.py b/tools/buildman/cmdline.py index 092a82f4e9..8586bdf3b5 100644 --- a/tools/buildman/cmdline.py +++ b/tools/buildman/cmdline.py @@ -13,6 +13,8 @@ def ParseArgs(): args: command lin arguments """ parser = OptionParser() + parser.add_option('-a', '--adjust-cfg', type=str, action='append', + help='Adjust the Kconfig settings in .config before building') parser.add_option('-A', '--print-prefix', action='store_true', help='Print the tool-chain prefix for a board (CROSS_COMPILE=)') parser.add_option('-b', '--branch', type='string', diff --git a/tools/buildman/control.py b/tools/buildman/control.py index fd9664c85d..eee8113066 100644 --- a/tools/buildman/control.py +++ b/tools/buildman/control.py @@ -10,6 +10,7 @@ import sys from buildman import board from buildman import bsettings +from buildman import cfgutil from buildman import toolchain from buildman.builder import Builder from patman import command @@ -321,6 +322,8 @@ def DoBuildman(options, args, toolchains=None, make_func=None, boards=None, output_dir = os.path.join(options.output_dir, dirname) if clean_dir and os.path.exists(output_dir): shutil.rmtree(output_dir) + adjust_cfg = cfgutil.convert_list_to_dict(options.adjust_cfg) + builder = Builder(toolchains, output_dir, options.git_dir, options.threads, options.jobs, gnu_make=gnu_make, checkout=True, show_unknown=options.show_unknown, step=options.step, @@ -332,7 +335,8 @@ def DoBuildman(options, args, toolchains=None, make_func=None, boards=None, squash_config_y=not options.preserve_config_y, warnings_as_errors=options.warnings_as_errors, work_in_output=options.work_in_output, - test_thread_exceptions=test_thread_exceptions) + test_thread_exceptions=test_thread_exceptions, + adjust_cfg=adjust_cfg) builder.force_config_on_failure = not options.quick if make_func: builder.do_make = make_func