From bb5e615593297c0ad2e6f7d82d10e96878c01324 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20M=C3=A9lotte?= Date: Thu, 17 Sep 2026 11:18:54 +0200 Subject: [PATCH] utils/check-symbols: check for undefined host symbols MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit get_warnings_for_symbols_without_definition() skips any symbol matching BR2_PACKAGE_HOST_* or BR2_PACKAGE_HAS_HOST_*, via br.re_host_symbol. This blanket exclusion was needed because we don't require a Config.in.host to be present for host packages, so BR2_PACKAGE_HOST_FOO may in fact be undefined and that's perfectly fine. However, this also excludes any other options that should be defined in the Config.in.host, e.g. a BR2_PACKAGE_HOST_FOO_BAR suboption. If such an option is misspelled in the .mk file, we will not notice. We already treat the BR2_PACKAGE_* symbols specially. They are considered as "used" even if there is no direct reference to them in the .mk file. This is done in the handle_eval function. Depending on the package infra and the type of package (bootloader, toolchain, ...) it sets the corresponding kconfig symbol as "used". At that point, we can also handle the special case of the host kconfig symbols. Instead of a blanket exclusion, we say that the BR2_PACKAGE_HOST_FOO option is implicitly defined by the eval statement. We only add BR2_PACKAGE_HOST_FOO as implicitly defined, so any suboptions will still be checked by get_warnings_for_symbols_without_definition(). We could alternatively also have skipped the "usage" marking of host packages. This approach felt more consistent though. Make handle_eval() in checksymbolslib/makefile.py record the implicitly defined symbols directly, at the $(eval $(host-...)) line that creates them: - BR2_PACKAGE_HOST_ as a definition, for host-*-package and host-virtual-package; - BR2_PACKAGE_HAS_HOST_ as virtual, for host-virtual-package, mirroring how the plain virtual-package case already registers BR2_PACKAGE_HAS_. This makes br.re_host_symbol and its use in get_warnings_for_symbols_without_definition() unnecessary, so drop them. The check now flags a real symbol name once it lacks both an explicit and an implicit definition, instead of ignoring the whole BR2_PACKAGE_HOST_*/BR2_PACKAGE_HAS_HOST_* namespace. Assisted-by: LLM Signed-off-by: Raphaël Mélotte Signed-off-by: Arnout Vandecappelle (cherry picked from commit 48e4bab464ccc6c829c57bf01482c2dc29af4301) Signed-off-by: Raphaël Mélotte --- utils/checksymbolslib/br.py | 1 - utils/checksymbolslib/db.py | 2 -- utils/checksymbolslib/makefile.py | 7 +++++++ utils/checksymbolslib/test_db.py | 4 ---- utils/checksymbolslib/test_makefile.py | 11 ++++++++--- 5 files changed, 15 insertions(+), 10 deletions(-) diff --git a/utils/checksymbolslib/br.py b/utils/checksymbolslib/br.py index a4c1b84c56..f3afa18a0a 100644 --- a/utils/checksymbolslib/br.py +++ b/utils/checksymbolslib/br.py @@ -120,7 +120,6 @@ re_menu = re.compile(r'^\s*menu\b') re_endmenu = re.compile(r'^\s*endmenu\b') re_comments = re.compile(r'#.*$') re_legacy_special_comment = re.compile(r'#.*(BR2_\w+)\s.*still referenced') -re_host_symbol = re.compile(r'(BR2_PACKAGE_HOST_\w+|BR2_PACKAGE_HAS_HOST_\w+)') re_makefile_symbol_usage = re.compile(r'\$\((BR2_\w+)\)') re_makefile_symbol_export = re.compile(r'export\s*(BR2_\w+)') re_makefile_symbol_attribution = re.compile(r'^\s*(BR2_\w+)\s*[?:=]') diff --git a/utils/checksymbolslib/db.py b/utils/checksymbolslib/db.py index cb0dfa476f..a92fe8e382 100644 --- a/utils/checksymbolslib/db.py +++ b/utils/checksymbolslib/db.py @@ -122,8 +122,6 @@ class DB: continue if legacy_definition in entries: continue - if br.re_host_symbol.search(symbol): - continue if br.is_an_optional_symbol_for_a_roofts(symbol): continue if symbol in br.symbols_defined_only_at_command_line: diff --git a/utils/checksymbolslib/makefile.py b/utils/checksymbolslib/makefile.py index e3894dd1f9..084530c29b 100644 --- a/utils/checksymbolslib/makefile.py +++ b/utils/checksymbolslib/makefile.py @@ -28,6 +28,8 @@ def handle_eval(db, filename, lineno, line): return # mimic package/pkg-generic.mk and package/pkg-virtual.mk + # They have ifeq ($$($$($(2)_KCONFIG_VAR)),y) so consider that a usage. + # Virtual packages have additional conditions. if '$(virtual-' in line: prefixes = ['BR2_PACKAGE_PROVIDES_', 'BR2_PACKAGE_HAS_'] if filename.startswith('toolchain/'): @@ -39,8 +41,13 @@ def handle_eval(db, filename, lineno, line): prefixes.append(prefix) elif '$(host-virtual-' in line: prefixes = ['BR2_PACKAGE_HOST_', 'BR2_PACKAGE_PROVIDES_HOST_', 'BR2_PACKAGE_HAS_HOST_'] + # For host packages, we allow it to not be defined in Config.in.host, so + # consider the symbol as defined as well. + db.add_symbol_definition('BR2_PACKAGE_HOST_' + package, filename, lineno) + db.add_symbol_virtual('BR2_PACKAGE_HAS_HOST_' + package, filename, lineno) elif '$(host-' in line: prefixes = ['BR2_PACKAGE_HOST_'] + db.add_symbol_definition('BR2_PACKAGE_HOST_' + package, filename, lineno) elif filename.startswith('boot/'): prefixes = [br.boot_prefix] elif filename.startswith('toolchain/'): diff --git a/utils/checksymbolslib/test_db.py b/utils/checksymbolslib/test_db.py index 15576fa897..ee5b626168 100644 --- a/utils/checksymbolslib/test_db.py +++ b/utils/checksymbolslib/test_db.py @@ -156,8 +156,6 @@ def test_get_warnings_for_symbols_without_definition(): db.add_symbol_usage_in_legacy('BR2_undef3', 'file', 3) db.add_symbol_usage('BR2_undef3', 'another', 1) db.add_symbol_legacy_usage('BR2_undef3', 'another', 2) - db.add_symbol_usage('BR2_PACKAGE_HOST_undef', 'file', 1) - db.add_symbol_usage('BR2_PACKAGE_HAS_HOST_undef', 'file', 1) db.add_symbol_usage('BR2_TARGET_ROOTFS_undef_XZ', 'file', 1) db.add_symbol_usage('BR2_GRAPH_ALT', 'file', 1) db.add_symbol_usage('BR2_EXTERNAL', 'file', 1) @@ -170,8 +168,6 @@ def test_get_warnings_for_symbols_without_definition(): 'BR2_undef1': {'normal usage': {'file': [1]}}, 'BR2_undef2': {'legacy usage': {'file': [2]}}, 'BR2_undef3': {'usage inside legacy': {'file': [3]}, 'normal usage': {'another': [1]}, 'legacy usage': {'another': [2]}}, - 'BR2_PACKAGE_HOST_undef': {'normal usage': {'file': [1]}}, - 'BR2_PACKAGE_HAS_HOST_undef': {'normal usage': {'file': [1]}}, 'BR2_TARGET_ROOTFS_undef_XZ': {'normal usage': {'file': [1]}}, 'BR2_GRAPH_ALT': {'normal usage': {'file': [1]}}, 'BR2_EXTERNAL': {'normal usage': {'file': [1]}}, diff --git a/utils/checksymbolslib/test_makefile.py b/utils/checksymbolslib/test_makefile.py index 9d24484124..859d99e42d 100644 --- a/utils/checksymbolslib/test_makefile.py +++ b/utils/checksymbolslib/test_makefile.py @@ -74,12 +74,15 @@ handle_eval = [ {'add_symbol_usage': [ call('BR2_PACKAGE_PROVIDES_HOST_FOO', 'package/foo/foo.mk', 18), call('BR2_PACKAGE_HAS_HOST_FOO', 'package/foo/foo.mk', 18), - call('BR2_PACKAGE_HOST_FOO', 'package/foo/foo.mk', 18)]}), + call('BR2_PACKAGE_HOST_FOO', 'package/foo/foo.mk', 18)], + 'add_symbol_definition': [call('BR2_PACKAGE_HOST_FOO', 'package/foo/foo.mk', 18)], + 'add_symbol_virtual': [call('BR2_PACKAGE_HAS_HOST_FOO', 'package/foo/foo.mk', 18)]}), ('host generic package', 'package/foo/foo.mk', 18, '$(eval $(host-package))', - {'add_symbol_usage': [call('BR2_PACKAGE_HOST_FOO', 'package/foo/foo.mk', 18)]}), + {'add_symbol_usage': [call('BR2_PACKAGE_HOST_FOO', 'package/foo/foo.mk', 18)], + 'add_symbol_definition': [call('BR2_PACKAGE_HOST_FOO', 'package/foo/foo.mk', 18)]}), ('boot package', 'boot/foo/foo.mk', 18, @@ -178,7 +181,9 @@ handle_usage = [ {'add_symbol_usage': [ call('BR2_PACKAGE_PROVIDES_HOST_FOO', 'package/foo/foo.mk', 18), call('BR2_PACKAGE_HAS_HOST_FOO', 'package/foo/foo.mk', 18), - call('BR2_PACKAGE_HOST_FOO', 'package/foo/foo.mk', 18)]}), + call('BR2_PACKAGE_HOST_FOO', 'package/foo/foo.mk', 18)], + 'add_symbol_definition': [call('BR2_PACKAGE_HOST_FOO', 'package/foo/foo.mk', 18)], + 'add_symbol_virtual': [call('BR2_PACKAGE_HAS_HOST_FOO', 'package/foo/foo.mk', 18)]}), ]