From 72954a7eb8785888fa9f3d336c72c7104008733d Mon Sep 17 00:00:00 2001 From: Igor Velkov <325961+iav@users.noreply.github.com> Date: Tue, 17 Feb 2026 02:15:19 +0200 Subject: [PATCH] extension: fix binman pkg_resources removal in setuptools >= 82 setuptools 82.0.0 removed the deprecated pkg_resources module. U-Boot's binman (tools/binman/control.py) uses `import pkg_resources` for reading package resources in versions prior to v2025.10. Add extension that patches binman at build time via pre_config_uboot_target hook, migrating from pkg_resources to importlib.resources: - Old U-Boot (<=v2023.x): adds try/except importlib_resources import block - Intermediate U-Boot (v2024.01+): aliases existing importlib.resources import - New U-Boot (>=v2025.10): no-op (pkg_resources already removed upstream) Replaces: - pkg_resources.resource_string() -> importlib_resources.files().joinpath().read_bytes() - pkg_resources.resource_listdir() -> [r.name for r in ...files().joinpath().iterdir()] Using an extension rather than patch files because BOOTPATCHDIR varies across ~15 families, and control.py differs between U-Boot versions. A single idempotent extension covers all versions. Can be removed once all BOOTBRANCH versions in Armbian are >= v2025.10. Tested: - tritium-h5 (sunxi, U-Boot v2024.01): patch applied, build OK - odroidc4 (meson-sm1, U-Boot v2022.07): patch applied, build OK - odroidm2 (rk3588, U-Boot v2025.10): no-op as expected, build OK Co-Authored-By: Claude Opus 4.6 --- extensions/uboot-binman-fix-pkg-resources.sh | 88 ++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 extensions/uboot-binman-fix-pkg-resources.sh diff --git a/extensions/uboot-binman-fix-pkg-resources.sh b/extensions/uboot-binman-fix-pkg-resources.sh new file mode 100644 index 0000000000..a8ad96fef7 --- /dev/null +++ b/extensions/uboot-binman-fix-pkg-resources.sh @@ -0,0 +1,88 @@ +#!/usr/bin/env bash +# +# SPDX-License-Identifier: GPL-2.0 +# +# Copyright (c) 2013-2026 Igor Pecovnik, igor@armbian.com +# +# This file is a part of the Armbian Build Framework +# https://github.com/armbian/build/ +# +# Fix binman's use of pkg_resources (removed in setuptools >= 82) +# by migrating to importlib.resources. +# +# Safe for all U-Boot versions: no-op if pkg_resources is not used. +# Can be removed once all BOOTBRANCH versions are >= v2025.10. + +function pre_config_uboot_target__fix_binman_pkg_resources() { + local control_py="tools/binman/control.py" + + # Skip if file doesn't exist or doesn't use pkg_resources + [[ -f "${control_py}" ]] || return 0 + grep -q 'import pkg_resources' "${control_py}" || return 0 + + display_alert "Patching binman" "migrating pkg_resources to importlib.resources" "info" + + python3 << 'PYTHON_SCRIPT' +import re + +control_py = "tools/binman/control.py" + +with open(control_py, "r") as f: + content = f.read() + +# 1. Remove "import pkg_resources" line +content = re.sub(r'^import pkg_resources\b[^\n]*\n', '', content, flags=re.MULTILINE) + +# 2. Ensure importlib_resources alias is available +has_importlib_alias = 'importlib_resources' in content +has_importlib_dotted = re.search(r'^import importlib\.resources\s*$', content, flags=re.MULTILINE) + +if not has_importlib_alias and has_importlib_dotted: + # New U-Boot (v2024.01+): has "import importlib.resources" without alias + content = re.sub( + r'^import importlib\.resources\s*$', + 'import importlib.resources as importlib_resources', + content, count=1, flags=re.MULTILINE + ) + # Update existing dotted usage to use the alias + content = re.sub(r'\bimportlib\.resources\.', 'importlib_resources.', content) +elif not has_importlib_alias: + # Old U-Boot (<=v2023.x): no importlib.resources at all + import_block = ( + 'try:\n' + ' import importlib.resources as importlib_resources\n' + ' importlib_resources.files\n' + 'except (ImportError, AttributeError):\n' + ' import importlib_resources\n' + ) + # Insert after the last top-level import line + lines = content.split('\n') + last_import_idx = 0 + for i, line in enumerate(lines): + if re.match(r'^(?:import |from \S+ import )', line): + last_import_idx = i + lines.insert(last_import_idx + 1, import_block) + content = '\n'.join(lines) + +# 3. Replace pkg_resources.resource_string(__name__, X) +# with importlib_resources.files(__package__).joinpath(X).read_bytes() +content = re.sub( + r'pkg_resources\.resource_string\s*\(\s*__name__\s*,\s*(.+?)\s*\)', + r'importlib_resources.files(__package__).joinpath(\1).read_bytes()', + content +) + +# 4. Replace pkg_resources.resource_listdir(__name__, X) +# with [r.name for r in importlib_resources.files(__package__).joinpath(X).iterdir() if r.is_file()] +content = re.sub( + r'pkg_resources\.resource_listdir\s*\(\s*__name__\s*,\s*(.+?)\s*\)', + r'[r.name for r in importlib_resources.files(__package__).joinpath(\1).iterdir() if r.is_file()]', + content +) + +with open(control_py, "w") as f: + f.write(content) + +print("binman control.py patched successfully") +PYTHON_SCRIPT +}