@@ -1053,10 +1053,87 @@ 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')
+
+ buildtools_download_dir = add_unique_timestamp_to_path(
+ os.path.join(args.setup_dir, 'buildtools-downloads/buildtools'))
+
+ 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")
+ 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
+ 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 +1363,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)
@@ -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``
@@ -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.
@@ -170,7 +170,28 @@
},
"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"
+ "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
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 <jaipaul.cheernam@est.tech> --- Changes since v4: - Rebased on latest master - Deduplicate buildtools_download_dir definition 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 | 88 ++++++++++++++++++- .../bitbake-user-manual-environment-setup.rst | 24 +++++ lib/bb/tests/setup.py | 77 +++++++++++++++- setup-schema/bitbake-setup.schema.json | 23 ++++- 4 files changed, 203 insertions(+), 9 deletions(-)