Re: [bitbake-devel] [PATCH v4] bitbake-setup: use bb.fetch for buildtools installer download
Alexander Kanavin <[email protected]> Tue, 30 Jun 2026 13:47:14 +0200
| Newsgroups | org.openembedded.lists.bitbake-devel |
|---|---|
| Message-ID | <CANNYZj_+k-yvOjJJM_JKAnVPH6Rpy5n4WJyYvrzgph=yX8-8Og@mail.gmail.com> |
Thanks, I think this is good overall. Perhaps there's no need to set buildtools_download_dir twice in the same way in two different code paths, but that's a minor issue. The patch should go to general review and CI now. Alex On Mon, 29 Jun 2026 at 22:34, Jaipaul Cheernam via lists.openembedded.org <[email protected]> wrote: > > When url and sha256sum are configured in the selected configuration, > download the buildtools installer via bb.fetch with checksum > enforcement. The file is unpacked to the standard buildtools download > location and passed to install-buildtools via --local-file. > > If no config is present or --default is passed, fall back to > calling install-buildtools directly with its built-in defaults. > > CLI overrides available via --url and --sha256. > > Depends: [oe-core] install-buildtools: add --local-file option > AI-Generated: Kiro with Claude Opus 4.6 > Signed-off-by: Jaipaul Cheernam <[email protected]> > --- > > Changes since v3: > - install-buildtools config is per-configuration only (no top-level) > - Use buildtools_download_dir for unpack (consistent with default path) > - Updated schema, docs, and tests to match > > Changes since v2: > - Added --default to bypass config and use script defaults > - Use fetcher.unpack() instead of reading from DL_DIR directly > - Removed explicit sha256 verification (fetcher handles it for https) > > Changes since v1: > - Use bb.fetch with mandatory sha256sum when configured > - Fall back to install-buildtools defaults when no config present > - Combined url+filename into single url field > - Removed --sdk-name, --filename, --no-check/--check > - Added --url and --sha256 CLI overrides > - Updated schema, docs, and tests > bin/bitbake-setup | 89 ++++++++++++++++++- > .../bitbake-user-manual-environment-setup.rst | 24 +++++ > lib/bb/tests/setup.py | 77 +++++++++++++++- > setup-schema/bitbake-setup.schema.json | 21 +++++ > 4 files changed, 203 insertions(+), 8 deletions(-) > > diff --git a/bin/bitbake-setup b/bin/bitbake-setup > index 97ea08d11..9a3507c1e 100755 > --- a/bin/bitbake-setup > +++ b/bin/bitbake-setup > @@ -1053,10 +1053,88 @@ def install_buildtools(top_dir, settings, args, d): > return > shutil.rmtree(buildtools_install_dir) > > - install_buildtools = os.path.join(args.setup_dir, 'layers/oe-scripts/install-buildtools') > - buildtools_download_dir = add_unique_timestamp_to_path(os.path.join(args.setup_dir, 'buildtools-downloads/buildtools')) > - logger.plain("Buildtools archive is downloaded into {} and its content installed into {}".format(buildtools_download_dir, buildtools_install_dir)) > - subprocess.check_call("{} -d {} --downloads-directory {}".format(install_buildtools, buildtools_install_dir, buildtools_download_dir), shell=True) > + install_buildtools_script = os.path.join(args.setup_dir, 'layers/oe-scripts/install-buildtools') > + > + buildtools_config = {} > + upstream_config_path = os.path.join(args.setup_dir, 'config', 'config-upstream.json') > + try: > + with open(upstream_config_path) as f: > + upstream_config = json.load(f) > + buildtools_config = upstream_config.get('bitbake-config', {}).get('install-buildtools', {}) > + except FileNotFoundError: > + pass > + except json.JSONDecodeError as e: > + logger.error("Failed to parse %s: %s" % (upstream_config_path, e)) > + sys.exit(1) > + > + url = args.url if args.url is not None else buildtools_config.get('url') > + sha256 = args.sha256 if args.sha256 is not None else buildtools_config.get('sha256sum') > + > + if args.default or (not url and not sha256): > + # No config or --default: fall back to install-buildtools defaults > + logger.plain("Using install-buildtools script defaults") > + buildtools_download_dir = add_unique_timestamp_to_path( > + os.path.join(args.setup_dir, 'buildtools-downloads/buildtools')) > + subprocess.check_call([install_buildtools_script, > + '-d', buildtools_install_dir, > + '--downloads-directory', buildtools_download_dir]) > + return > + > + if not url: > + logger.error("No buildtools URL configured. " > + "Set 'url' in the install-buildtools config section or pass --url.") > + sys.exit(1) > + > + if not sha256: > + logger.error("No sha256sum configured for buildtools installer. " > + "Add 'sha256sum' to the install-buildtools config section or pass --sha256.\n" > + "You can obtain it with: sha256sum <installer-file>") > + sys.exit(1) > + > + # Download using bb.fetch with sha256 validation > + src_uri = "{};sha256sum={}".format(url, sha256) > + > + logger.plain("Fetching buildtools installer using bitbake fetcher") > + logger.plain(" {}".format(url)) > + > + fetcher = bb.fetch.Fetch([src_uri], d) > + try: > + fetcher.download() > + except bb.fetch2.ChecksumError as e: > + logger.error("Checksum mismatch for buildtools installer. " > + "Verify the URL and downloaded file.\n%s" % str(e)) > + sys.exit(1) > + except bb.fetch2.FetchError as e: > + logger.error("Failed to download buildtools installer: %s" % str(e)) > + sys.exit(1) > + > + # Unpack into the standard buildtools download location > + buildtools_download_dir = add_unique_timestamp_to_path( > + os.path.join(args.setup_dir, 'buildtools-downloads/buildtools')) > + os.makedirs(buildtools_download_dir, exist_ok=True) > + fetcher.unpack(buildtools_download_dir) > + > + filename = os.path.basename(url.rstrip('/')) > + matches = glob.glob(os.path.join(buildtools_download_dir, '**', filename), recursive=True) > + if not matches: > + logger.error("Unpacked file not found: %s" % filename) > + sys.exit(1) > + local_path = matches[0] > + > + logger.plain("Buildtools installer will be installed into {}".format( > + buildtools_install_dir)) > + > + cmd = [ > + install_buildtools_script, > + '--local-file', local_path, > + '-d', buildtools_install_dir, > + ] > + > + try: > + subprocess.check_call(cmd) > + except subprocess.CalledProcessError as e: > + logger.error("install-buildtools failed with exit code %d" % e.returncode) > + sys.exit(1) > > def create_siteconf(top_dir, non_interactive, settings): > siteconfpath = os.path.join(top_dir, 'site.conf') > @@ -1286,6 +1364,9 @@ def main(): > parser_install_buildtools = subparsers.add_parser('install-buildtools', help='Install buildtools which can help fulfil missing or incorrect dependencies on the host machine') > add_setup_dir_arg(parser_install_buildtools) > parser_install_buildtools.add_argument('--force', action='store_true', help='Force a reinstall of buildtools over the previous installation.') > + parser_install_buildtools.add_argument('--default', action='store_true', help='Use install-buildtools script defaults, ignoring any config.') > + parser_install_buildtools.add_argument('--url', help='Full URL to the buildtools SDK installer. Overrides config value.') > + parser_install_buildtools.add_argument('--sha256', help='SHA256 checksum of the buildtools installer. Overrides config value.') > parser_install_buildtools.set_defaults(func=install_buildtools) > > parser_settings_arg_global = argparse.ArgumentParser(add_help=False) > diff --git a/doc/bitbake-user-manual/bitbake-user-manual-environment-setup.rst b/doc/bitbake-user-manual/bitbake-user-manual-environment-setup.rst > index aa546c30b..e1701555e 100644 > --- a/doc/bitbake-user-manual/bitbake-user-manual-environment-setup.rst > +++ b/doc/bitbake-user-manual/bitbake-user-manual-environment-setup.rst > @@ -660,6 +660,30 @@ In addition, the command can take the following arguments: > - ``--setup-dir``: path to the :term:`Setup` to check to status for. Not > required if :term:`BBPATH` is already configured. > > +- ``--url``: full URL to the buildtools SDK installer. Overrides the value > + from the configuration file. > + > +- ``--sha256``: SHA256 checksum of the buildtools installer. Overrides the > + value from the configuration file. > + > +When ``url`` and ``sha256sum`` are set in the :term:`Configuration File`, > +the installer is downloaded via ``bb.fetch`` (cached in ``DL_DIR``) and its > +checksum is enforced. If no configuration is present, the script falls back > +to its built-in defaults:: > + > + "bitbake-setup": { > + "configurations": [ > + { > + "name": "my-config", > + "install-buildtools": { > + "url": "https://example.com/buildtools/x86_64-buildtools-extended-nativesdk-standalone-5.0.sh", > + "sha256sum": "af76648b..." > + }, > + ... > + } > + ] > + } > + > .. _ref-bbsetup-command-settings: > > ``bitbake-setup settings`` > diff --git a/lib/bb/tests/setup.py b/lib/bb/tests/setup.py > index 5592e8196..8ca64cb50 100644 > --- a/lib/bb/tests/setup.py > +++ b/lib/bb/tests/setup.py > @@ -61,16 +61,31 @@ import getopt > import sys > import os > > -opts, args = getopt.getopt(sys.argv[1:], "d:", ["downloads-directory="]) > +opts, args = getopt.getopt(sys.argv[1:], "d:", ["downloads-directory=", "local-file="]) > +installdir = None > +local_file = None > for option, value in opts: > if option == '-d': > installdir = value > + elif option == '--local-file': > + local_file = value > + print("install-buildtools local-file={}".format(value)) > > print("Buildtools installed into {}".format(installdir)) > -os.makedirs(installdir) > +os.makedirs(installdir, exist_ok=True) > """ > self.add_file_to_testrepo('scripts/install-buildtools', installbuildtools, script=True) > > + # Dummy buildtools installer for bb.fetch testing > + self.buildtools_dir = os.path.join(self.tempdir, "buildtools-dl") > + os.makedirs(self.buildtools_dir) > + self.buildtools_filename = "x86_64-buildtools-nativesdk-standalone-test.sh" > + buildtools_filepath = os.path.join(self.buildtools_dir, self.buildtools_filename) > + with open(buildtools_filepath, 'w') as f: > + f.write("#!/bin/sh\necho dummy\n") > + with open(buildtools_filepath, 'rb') as f: > + self.buildtools_sha256 = hashlib.sha256(f.read()).hexdigest() > + > bitbakeconfigbuild = """#!/usr/bin/env python3 > import os > import sys > @@ -108,7 +123,11 @@ print("BBPATH is {{}}".format(os.environ["BBPATH"])) > "name": "gadget", > "description": "Gadget configuration", > "oe-template": "test-configuration-gadget", > - "oe-fragments": ["test-fragment-1"] > + "oe-fragments": ["test-fragment-1"], > + "install-buildtools": { > + "url": "file://%s/%s", > + "sha256sum": "%s" > + } > }, > { > "name": "gizmo", > @@ -176,7 +195,7 @@ print("BBPATH is {{}}".format(os.environ["BBPATH"])) > }, > "version": "1.0" > } > -""" % (sources) > +""" % (sources, self.buildtools_dir, self.buildtools_filename, self.buildtools_sha256) > os.makedirs(os.path.join(self.registrypath, os.path.dirname(name)), exist_ok=True) > with open(os.path.join(self.registrypath, name), 'w') as f: > f.write(config) > @@ -644,6 +663,56 @@ print("BBPATH is {{}}".format(os.environ["BBPATH"])) > def _count_layer_backups(self, layers_path): > return len([f for f in os.listdir(layers_path) if 'backup' in f]) > > + def test_install_buildtools_fetch(self): > + """Test that install-buildtools uses bb.fetch with sha256 and passes --local-file""" > + import shutil > + > + if 'BBPATH' in os.environ: > + del os.environ['BBPATH'] > + os.chdir(self.tempdir) > + > + registry_uri = "git://{};protocol=file;branch=master;rev=master".format( > + self.registrypath) > + self.runbbsetup(["settings", "set", "default", "registry", registry_uri]) > + self.add_file_to_testrepo('test-file', 'initial\n') > + self.add_json_config_to_registry('test-config-bt.conf.json', 'master', 'master') > + self.runbbsetup(["init", "--non-interactive", "test-config-bt", "gadget"]) > + setuppath = self.get_setup_path('test-config-bt', 'gadget') > + > + # test config-driven install (url + sha256sum from config) > + out = self.runbbsetup(["install-buildtools", "--setup-dir", setuppath]) > + self.assertIn("Buildtools installed into", out[0]) > + self.assertIn("install-buildtools local-file=", out[0]) > + self.assertTrue(os.path.exists(os.path.join(setuppath, 'buildtools'))) > + > + # test CLI overrides (use a different file to prove precedence) > + shutil.rmtree(os.path.join(setuppath, 'buildtools')) > + alt_filename = "alt-buildtools-test.sh" > + alt_filepath = os.path.join(self.buildtools_dir, alt_filename) > + with open(alt_filepath, 'w') as f: > + f.write("#!/bin/sh\necho alt\n") > + with open(alt_filepath, 'rb') as f: > + alt_sha256 = hashlib.sha256(f.read()).hexdigest() > + alt_url = "file://{}/{}".format(self.buildtools_dir, alt_filename) > + out = self.runbbsetup(["install-buildtools", "--setup-dir", setuppath, > + "--url", alt_url, > + "--sha256", alt_sha256]) > + self.assertIn("Buildtools installed into", out[0]) > + self.assertIn("install-buildtools local-file=", out[0]) > + self.assertIn(alt_filename, out[0]) > + > + # test missing sha256sum is a hard error > + shutil.rmtree(os.path.join(setuppath, 'buildtools'), ignore_errors=True) > + with open(os.path.join(setuppath, 'config', 'config-upstream.json')) as f: > + config_upstream = json.load(f) > + config_upstream['bitbake-config']['install-buildtools'] = { > + 'url': 'file://{}/{}'.format(self.buildtools_dir, self.buildtools_filename) > + } > + with open(os.path.join(setuppath, 'config', 'config-upstream.json'), 'w') as f: > + json.dump(config_upstream, f) > + with self.assertRaises(bb.process.ExecutionError): > + self.runbbsetup(["install-buildtools", "--setup-dir", setuppath, "--force"]) > + > def test_update_rebase_conflicts_strategy(self): > """Test the --rebase-conflicts-strategy option for the update command. > > diff --git a/setup-schema/bitbake-setup.schema.json b/setup-schema/bitbake-setup.schema.json > index 99f47f73d..797d45252 100644 > --- a/setup-schema/bitbake-setup.schema.json > +++ b/setup-schema/bitbake-setup.schema.json > @@ -137,6 +137,27 @@ > "setup-dir-name": { > "type": "string", > "description": "A suggestion for the setup directory name, $-prefixed keys from oe-fragments-one-of will be substituted with user selections." > + }, > + "install-buildtools": { > + "type": "object", > + "description": "Settings for downloading buildtools via bb.fetch", > + "properties": { > + "url": { > + "type": "string", > + "minLength": 1, > + "description": "Full URL to the buildtools SDK installer." > + }, > + "sha256sum": { > + "type": "string", > + "minLength": 1, > + "description": "SHA256 checksum of the buildtools installer." > + } > + }, > + "required": [ > + "url", > + "sha256sum" > + ], > + "additionalProperties": false > } > }, > "additionalProperties": false > -- > 2.34.1 > > > -=-=-=-=-=-=-=-=-=-=-=- > Links: You receive all messages sent to this group. > View/Reply Online (#19808): https://lists.openembedded.org/g/bitbake-devel/message/19808 > Mute This Topic: https://lists.openembedded.org/mt/120037327/1686489 > Group Owner: [email protected] > Unsubscribe: https://lists.openembedded.org/g/bitbake-devel/unsub [[email protected]] > -=-=-=-=-=-=-=-=-=-=-=- >