From: Simon Glass Date: Thu, 15 Aug 2024 19:57:45 +0000 (-0600) Subject: buildman: Allow skipping the dtc build X-Git-Url: http://git.dujemihanovic.xyz/%22/img/sics.gif/%22/static/git-favicon.png?a=commitdiff_plain;h=ba134c35316e275fd8708cf20794f61526d6420a;p=u-boot.git buildman: Allow skipping the dtc build For most boards, the device-tree compiler is built in-tree, ignoring the system version. Add a special option to skip this build. This can be useful when the system dtc is up-to-date, as it speeds up the build. Signed-off-by: Simon Glass --- diff --git a/tools/buildman/builder.py b/tools/buildman/builder.py index c4384f53e8..4090d328b3 100644 --- a/tools/buildman/builder.py +++ b/tools/buildman/builder.py @@ -22,6 +22,7 @@ from buildman import toolchain from patman import gitutil from u_boot_pylib import command from u_boot_pylib import terminal +from u_boot_pylib import tools from u_boot_pylib.terminal import tprint # This indicates an new int or hex Kconfig property with no default @@ -263,7 +264,8 @@ class Builder: adjust_cfg=None, allow_missing=False, no_lto=False, reproducible_builds=False, force_build=False, force_build_failures=False, force_reconfig=False, - in_tree=False, force_config_on_failure=False, make_func=None): + in_tree=False, force_config_on_failure=False, make_func=None, + dtc_skip=False): """Create a new Builder object Args: @@ -312,6 +314,7 @@ class Builder: force_config_on_failure (bool): Reconfigure the build before retrying a failed build make_func (function): Function to call to run 'make' + dtc_skip (bool): True to skip building dtc and use the system one """ self.toolchains = toolchains self.base_dir = base_dir @@ -354,6 +357,12 @@ class Builder: self.in_tree = in_tree self.force_config_on_failure = force_config_on_failure self.fallback_mrproper = fallback_mrproper + if dtc_skip: + self.dtc = shutil.which('dtc') + if not self.dtc: + raise ValueError('Cannot find dtc') + else: + self.dtc = None if not self.squash_config_y: self.config_filenames += EXTRA_CONFIG_FILENAMES @@ -407,6 +416,22 @@ class Builder: def signal_handler(self, signal, frame): sys.exit(1) + def make_environment(self, toolchain): + """Create the environment to use for building + + Args: + toolchain (Toolchain): Toolchain to use for building + + Returns: + dict: + key (str): Variable name + value (str): Variable value + """ + env = toolchain.MakeEnvironment(self.full_path) + if self.dtc: + env[b'DTC'] = tools.to_bytes(self.dtc) + return env + def set_display_options(self, show_errors=False, show_sizes=False, show_detail=False, show_bloat=False, list_error_boards=False, show_config=False, diff --git a/tools/buildman/builderthread.py b/tools/buildman/builderthread.py index 55658487ab..b5afee61af 100644 --- a/tools/buildman/builderthread.py +++ b/tools/buildman/builderthread.py @@ -406,7 +406,7 @@ class BuilderThread(threading.Thread): the next incremental build """ # Set up the environment and command line - env = self.toolchain.MakeEnvironment(self.builder.full_path) + env = self.builder.make_environment(self.toolchain) mkdir(out_dir) args, cwd, src_dir = self._build_args(brd, out_dir, out_rel_dir, @@ -574,7 +574,7 @@ class BuilderThread(threading.Thread): outf.write(f'{result.return_code}') # Write out the image and function size information and an objdump - env = result.toolchain.MakeEnvironment(self.builder.full_path) + env = self.builder.make_environment(self.toolchain) with open(os.path.join(build_dir, 'out-env'), 'wb') as outf: for var in sorted(env.keys()): outf.write(b'%s="%s"' % (var, env[var])) diff --git a/tools/buildman/buildman.rst b/tools/buildman/buildman.rst index b8ff3bf1ab..e873611e59 100644 --- a/tools/buildman/buildman.rst +++ b/tools/buildman/buildman.rst @@ -1030,6 +1030,9 @@ of the source tree, thus allowing rapid tested evolution of the code:: ./tools/buildman/buildman -Pr tegra +Note also the `--dtc-skip` option which uses the system device-tree compiler to +avoid needing to build it for each board. This can save 10-20% of build time. +An alternative is to set DTC=/path/to/dtc when running buildman. Checking configuration ---------------------- diff --git a/tools/buildman/cmdline.py b/tools/buildman/cmdline.py index 544a391a46..7573e5bdfe 100644 --- a/tools/buildman/cmdline.py +++ b/tools/buildman/cmdline.py @@ -46,6 +46,8 @@ def add_upto_m(parser): help='Show detailed size delta for each board in the -S summary') parser.add_argument('-D', '--debug', action='store_true', help='Enabling debugging (provides a full traceback on error)') + parser.add_argument('--dtc-skip', action='store_true', default=False, + help='Skip building of dtc and use the system version') parser.add_argument('-e', '--show_errors', action='store_true', default=False, help='Show errors and warnings') parser.add_argument('-E', '--warnings-as-errors', action='store_true', diff --git a/tools/buildman/control.py b/tools/buildman/control.py index d3d027f02a..55d4d770c5 100644 --- a/tools/buildman/control.py +++ b/tools/buildman/control.py @@ -809,7 +809,8 @@ def do_buildman(args, toolchains=None, make_func=None, brds=None, force_build = args.force_build, force_build_failures = args.force_build_failures, force_reconfig = args.force_reconfig, in_tree = args.in_tree, - force_config_on_failure=not args.quick, make_func=make_func) + force_config_on_failure=not args.quick, make_func=make_func, + dtc_skip=args.dtc_skip) TEST_BUILDER = builder diff --git a/tools/buildman/test.py b/tools/buildman/test.py index 46aa2a1791..15801f6097 100644 --- a/tools/buildman/test.py +++ b/tools/buildman/test.py @@ -999,6 +999,37 @@ class TestBuild(unittest.TestCase): self.assertEqual( {b'CROSS_COMPILE': b'fred aarch64-linux-', b'LC_ALL': b'C'}, diff) + def test_skip_dtc(self): + """Test skipping building the dtc tool""" + old_path = os.getenv('PATH') + try: + os.environ['PATH'] = self.base_dir + + # Check a missing tool + with self.assertRaises(ValueError) as exc: + builder.Builder(self.toolchains, self.base_dir, None, 0, 2, + dtc_skip=True) + self.assertIn('Cannot find dtc', str(exc.exception)) + + # Create a fake tool to use + dtc = os.path.join(self.base_dir, 'dtc') + tools.write_file(dtc, b'xx') + os.chmod(dtc, 0o777) + + build = builder.Builder(self.toolchains, self.base_dir, None, 0, 2, + dtc_skip=True) + toolchain = self.toolchains.Select('arm') + env = build.make_environment(toolchain) + self.assertIn(b'DTC', env) + + # Try the normal case, i.e. not skipping the dtc build + build = builder.Builder(self.toolchains, self.base_dir, None, 0, 2) + toolchain = self.toolchains.Select('arm') + env = build.make_environment(toolchain) + self.assertNotIn(b'DTC', env) + finally: + os.environ['PATH'] = old_path + if __name__ == "__main__": unittest.main()