Skip to content

Commit 7fa749f

Browse files
ulfalizernashif
authored andcommitted
checks: kconfig: Check for references to undefined Kconfig symbols
Use 'git grep' to look for the pattern CONFIG_[A-Z0-9_]+ at word boundaries in all files. For each match, check that the corresponding Kconfig symbol is defined. This check is broad enough that it will always need some whitelisting, e.g. due to token pasting (CONFIG_FOO_#x) and non-existent symbols used as examples. The message printed on failures points out where the whitelist is. There's a few stragglers in the whitelist for small issues that are about to be fixed (the issue IDs are included). Skip the samples/ and tests/ directories for now. They contain Kconfig files that aren't part of the main Kconfig tree, which triggers false positives. Maybe something fancier could be done later to include those. Signed-off-by: Ulf Magnusson <[email protected]>
1 parent 586359d commit 7fa749f

File tree

1 file changed

+122
-0
lines changed

1 file changed

+122
-0
lines changed

scripts/ci/check_compliance.py

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#
55
# SPDX-License-Identifier: Apache-2.0
66

7+
import collections
78
import sys
89
import subprocess
910
import re
@@ -195,6 +196,7 @@ def run(self):
195196

196197
self.check_no_undef_within_kconfig(kconf)
197198
self.check_top_menu_not_too_long(kconf)
199+
self.check_no_undef_outside_kconfig(kconf)
198200

199201
def get_modules(self, modules_file):
200202
"""
@@ -295,6 +297,126 @@ def check_top_menu_not_too_long(self, kconf):
295297
entries, then bump the 'max_top_items' variable in {}.
296298
""".format(max_top_items, n_top_items, __file__))
297299

300+
def check_no_undef_outside_kconfig(self, kconf):
301+
"""
302+
Checks that there are no references to undefined Kconfig symbols
303+
outside Kconfig files (any CONFIG_FOO where no FOO symbol exists)
304+
"""
305+
# Grep for symbol references.
306+
#
307+
# Example output line for a reference to CONFIG_BAZ at line 17 of
308+
# foo/bar.c:
309+
#
310+
# foo/bar.c<null>17<null>CONFIG_BAZ
311+
#
312+
# Skip the samples/ and tests/ directories for now. They often contain
313+
# Kconfig files that are not part of the main Kconfig tree, which will
314+
# trigger false positives until we do something fancier. Skip
315+
# doc/releases too, which often references removed symbols.
316+
grep_cmd = "git grep --only-matching --line-number -I --null " \
317+
"--extended-regexp --word-regexp CONFIG_[A-Z0-9_]+ " \
318+
"-- :!samples :!tests :!doc/releases"
319+
320+
grep_process = subprocess.Popen(grep_cmd.split(),
321+
stdout=subprocess.PIPE,
322+
stderr=subprocess.PIPE,
323+
cwd=self.zephyr_base)
324+
325+
grep_stdout, grep_stderr = grep_process.communicate()
326+
# Fail if there's anything on stderr too, so that it doesn't get missed
327+
if grep_process.returncode or grep_stderr:
328+
self.error("'{}' failed with exit code {} (while searching for "
329+
"Kconfig symbol references)\n\nstdout:\n{}\n\n"
330+
"stderr:\n{}"
331+
.format(grep_cmd, grep_process.returncode, grep_stdout,
332+
grep_stderr))
333+
334+
defined_syms = set(sym.name for sym in kconf.unique_defined_syms)
335+
undef_to_locs = collections.defaultdict(list)
336+
337+
# splitlines() supports various line terminators
338+
for line in grep_stdout.decode("utf-8").splitlines():
339+
path, lineno, sym_name = line.split("\0")
340+
341+
# [7:] removes the "CONFIG_" prefix
342+
if sym_name[7:] not in defined_syms and \
343+
sym_name not in UNDEF_KCONFIG_WHITELIST:
344+
345+
undef_to_locs[sym_name].append("{}:{}".format(path, lineno))
346+
347+
if not undef_to_locs:
348+
return
349+
350+
# String that describes all referenced but undefined Kconfig symbols,
351+
# in alphabetical order, along with the locations where they're
352+
# referenced. Example:
353+
#
354+
# CONFIG_ALSO_MISSING arch/xtensa/core/fatal.c:273
355+
# CONFIG_MISSING arch/xtensa/core/fatal.c:264, subsys/fb/cfb.c:20
356+
undef_desc = "\n".join(
357+
"{:35} {}".format(sym_name, ", ".join(locs))
358+
for sym_name, locs in sorted(undef_to_locs.items()))
359+
360+
self.add_failure("""
361+
Found references to undefined Kconfig symbols. If any of these are false
362+
positives, then add them to UNDEF_KCONFIG_WHITELIST in {} in the ci-tools
363+
repo.\n\n{}""".format(__file__, undef_desc))
364+
365+
366+
# Many of these are either symbols used as examples or due to token pasting
367+
# (CONFIG_FOO_#x, etc.). Note that the list is sorted alphabetically.
368+
UNDEF_KCONFIG_WHITELIST = {
369+
"CONFIG_2ND_LVL_INTR_",
370+
"CONFIG_3RD_LVL_INTR_",
371+
"CONFIG_APP_LINK_WITH_",
372+
"CONFIG_CDC_ACM_PORT_NAME_",
373+
"CONFIG_CLOCK_STM32_PLL_SRC_",
374+
"CONFIG_CLOCK_STM32_SYSCLK_SRC_",
375+
"CONFIG_CMU",
376+
"CONFIG_COUNTER_RTC",
377+
"CONFIG_COUNTER_RTC_STM32_CLOCK_SRC",
378+
"CONFIG_COUNTER_TIMER",
379+
"CONFIG_DEEP_SLEEP", # #defined by RV32M1 in ext/
380+
"CONFIG_DESCRIPTION",
381+
"CONFIG_ERR",
382+
"CONFIG_ESP_DIF_LIBRARY", # Referenced in CMake comment
383+
"CONFIG_EXPERIMENTAL",
384+
"CONFIG_FFT", # Used as an example in cmake/extensions.cmake
385+
"CONFIG_FLAG", # Used as an example
386+
"CONFIG_FOO",
387+
"CONFIG_FOO_LOG_LEVEL",
388+
"CONFIG_FOO_SETTING_1",
389+
"CONFIG_FOO_SETTING_2",
390+
"CONFIG_GPIO_SIFIVE_",
391+
"CONFIG_I2C_GPIO_",
392+
"CONFIG_I2S_CAVS_",
393+
"CONFIG_LIS2DW12_INT_PIN",
394+
"CONFIG_MODULES",
395+
"CONFIG_MYFEATURE",
396+
"CONFIG_MY_DRIVER_0",
397+
"CONFIG_NORMAL_SLEEP", # #defined by RV32M1 in ext/
398+
"CONFIG_OPT",
399+
"CONFIG_OPT_0",
400+
"CONFIG_PWM_",
401+
"CONFIG_REG1",
402+
"CONFIG_REG2",
403+
"CONFIG_SEL",
404+
"CONFIG_SOC_SERIES_",
405+
"CONFIG_SOC_WATCH", # Issue 13749
406+
"CONFIG_SOME_BOOL",
407+
"CONFIG_SOME_INT",
408+
"CONFIG_SOME_OTHER_BOOL",
409+
"CONFIG_SOME_STRING",
410+
"CONFIG_SPI_",
411+
"CONFIG_STD_CPP", # Referenced in CMake comment
412+
"CONFIG_TEST1",
413+
"CONFIG_TYPE_BOOLEAN",
414+
"CONFIG_UART_",
415+
"CONFIG_USB_CONSOLE",
416+
"CONFIG_USB_HID_DEVICE_NAME_",
417+
"CONFIG_WHATEVER",
418+
}
419+
298420

299421
class Codeowners(ComplianceTest):
300422
"""

0 commit comments

Comments
 (0)