Skip to content

Commit dfc2826

Browse files
committed
[nrf fromtree] scripts: ci: check_compliance: Add sysbuild Kconfig checks
Introduce sysbuild-specific variants of existing Kconfig checks: * SysbuildKconfig * SysbuildKconfigBasic * SysbuildKconfigBasicNoModules This involves a few additions to the base `KconfigCheck` class: * Supporting a variable symbol prefix, to handle `SB_CONFIG_`. * Generating extra files, including `Kconfig.sysbuild.modules`. Although these are never sourced outside of sysbuild Kconfig, they're still generated for every regular Zephyr build, so it's natural to let all Kconfig checks follow this behavior. Signed-off-by: Grzegorz Swiderski <[email protected]> (cherry picked from commit 7ce6ac2)
1 parent f922948 commit dfc2826

File tree

3 files changed

+72
-7
lines changed

3 files changed

+72
-7
lines changed

.github/workflows/compliance.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ jobs:
8282
git log --pretty=oneline | head -n 10
8383
# Increase rename limit to allow for large PRs
8484
git config diff.renameLimit 10000
85-
./scripts/ci/check_compliance.py --annotate -e KconfigBasic -e ClangFormat \
85+
./scripts/ci/check_compliance.py --annotate -e KconfigBasic -e SysbuildKconfigBasic -e ClangFormat \
8686
-c origin/${BASE_REF}..
8787
8888
- name: upload-results

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,5 +104,8 @@ Nits.txt
104104
Pylint.txt
105105
Ruff.txt
106106
SphinxLint.txt
107+
SysbuildKconfig.txt
108+
SysbuildKconfigBasic.txt
109+
SysbuildKconfigBasicNoModules.txt
107110
TextEncoding.txt
108111
YAMLLint.txt

scripts/ci/check_compliance.py

Lines changed: 68 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,9 @@ class KconfigCheck(ComplianceTest):
374374
# Top-level Kconfig file. The path can be relative to srctree (ZEPHYR_BASE).
375375
FILENAME = "Kconfig"
376376

377+
# Kconfig symbol prefix/namespace.
378+
CONFIG_ = "CONFIG_"
379+
377380
def run(self):
378381
kconf = self.parse_kconfig()
379382

@@ -385,7 +388,7 @@ def run(self):
385388
self.check_soc_name_sync(kconf)
386389
self.check_no_undef_outside_kconfig(kconf)
387390

388-
def get_modules(self, modules_file, settings_file):
391+
def get_modules(self, modules_file, sysbuild_modules_file, settings_file):
389392
"""
390393
Get a list of modules and put them in a file that is parsed by
391394
Kconfig
@@ -398,7 +401,9 @@ def get_modules(self, modules_file, settings_file):
398401
zephyr_module_path = os.path.join(ZEPHYR_BASE, "scripts",
399402
"zephyr_module.py")
400403
cmd = [sys.executable, zephyr_module_path,
401-
'--kconfig-out', modules_file, '--settings-out', settings_file]
404+
'--kconfig-out', modules_file,
405+
'--sysbuild-kconfig-out', sysbuild_modules_file,
406+
'--settings-out', settings_file]
402407
try:
403408
subprocess.run(cmd, check=True, stdout=subprocess.PIPE,
404409
stderr=subprocess.STDOUT)
@@ -501,6 +506,7 @@ def get_v2_model(self, kconfig_dir, settings_file):
501506

502507
kconfig_file = os.path.join(kconfig_dir, 'boards', 'Kconfig')
503508
kconfig_boards_file = os.path.join(kconfig_dir, 'boards', 'Kconfig.boards')
509+
kconfig_sysbuild_file = os.path.join(kconfig_dir, 'boards', 'Kconfig.sysbuild')
504510
kconfig_defconfig_file = os.path.join(kconfig_dir, 'boards', 'Kconfig.defconfig')
505511

506512
board_roots = self.get_module_setting_root('board', settings_file)
@@ -517,6 +523,11 @@ def get_v2_model(self, kconfig_dir, settings_file):
517523
for board_dir in board.directories:
518524
fp.write('osource "' + (board_dir / 'Kconfig.defconfig').as_posix() + '"\n')
519525

526+
with open(kconfig_sysbuild_file, 'w') as fp:
527+
for board in v2_boards:
528+
for board_dir in board.directories:
529+
fp.write('osource "' + (board_dir / 'Kconfig.sysbuild').as_posix() + '"\n')
530+
520531
with open(kconfig_boards_file, 'w') as fp:
521532
for board in v2_boards:
522533
board_str = 'BOARD_' + re.sub(r"[^a-zA-Z0-9_]", "_", board.name).upper()
@@ -538,6 +549,7 @@ def get_v2_model(self, kconfig_dir, settings_file):
538549
fp.write('osource "' + (board_dir / 'Kconfig').as_posix() + '"\n')
539550

540551
kconfig_defconfig_file = os.path.join(kconfig_dir, 'soc', 'Kconfig.defconfig')
552+
kconfig_sysbuild_file = os.path.join(kconfig_dir, 'soc', 'Kconfig.sysbuild')
541553
kconfig_soc_file = os.path.join(kconfig_dir, 'soc', 'Kconfig.soc')
542554
kconfig_file = os.path.join(kconfig_dir, 'soc', 'Kconfig')
543555

@@ -549,6 +561,10 @@ def get_v2_model(self, kconfig_dir, settings_file):
549561
for folder in soc_folders:
550562
fp.write('osource "' + (Path(folder) / 'Kconfig.defconfig').as_posix() + '"\n')
551563

564+
with open(kconfig_sysbuild_file, 'w') as fp:
565+
for folder in soc_folders:
566+
fp.write('osource "' + (Path(folder) / 'Kconfig.sysbuild').as_posix() + '"\n')
567+
552568
with open(kconfig_soc_file, 'w') as fp:
553569
for folder in soc_folders:
554570
fp.write('source "' + (Path(folder) / 'Kconfig.soc').as_posix() + '"\n')
@@ -603,6 +619,7 @@ def parse_kconfig(self):
603619

604620
# For multi repo support
605621
self.get_modules(os.path.join(kconfiglib_dir, "Kconfig.modules"),
622+
os.path.join(kconfiglib_dir, "Kconfig.sysbuild.modules"),
606623
os.path.join(kconfiglib_dir, "settings_file.txt"))
607624
# For Kconfig.dts support
608625
self.get_kconfig_dts(os.path.join(kconfiglib_dir, "Kconfig.dts"),
@@ -849,7 +866,7 @@ def check_no_undef_outside_kconfig(self, kconf):
849866
undef_to_locs = collections.defaultdict(list)
850867

851868
# Warning: Needs to work with both --perl-regexp and the 're' module
852-
regex = r"\bCONFIG_[A-Z0-9_]+\b(?!\s*##|[$@{(.*])"
869+
regex = r"\b" + self.CONFIG_ + r"[A-Z0-9_]+\b(?!\s*##|[$@{(.*])"
853870

854871
# Skip doc/releases and doc/security/vulnerabilities.rst, which often
855872
# reference removed symbols
@@ -865,7 +882,7 @@ def check_no_undef_outside_kconfig(self, kconf):
865882
# Extract symbol references (might be more than one) within the
866883
# line
867884
for sym_name in re.findall(regex, line):
868-
sym_name = sym_name[7:] # Strip CONFIG_
885+
sym_name = sym_name[len(self.CONFIG_):] # Strip CONFIG_
869886
if sym_name not in defined_syms and \
870887
sym_name not in self.UNDEF_KCONFIG_ALLOWLIST and \
871888
not (sym_name.endswith("_MODULE") and sym_name[:-7] in defined_syms):
@@ -881,7 +898,7 @@ def check_no_undef_outside_kconfig(self, kconf):
881898
#
882899
# CONFIG_ALSO_MISSING arch/xtensa/core/fatal.c:273
883900
# CONFIG_MISSING arch/xtensa/core/fatal.c:264, subsys/fb/cfb.c:20
884-
undef_desc = "\n".join(f"CONFIG_{sym_name:35} {', '.join(locs)}"
901+
undef_desc = "\n".join(f"{self.CONFIG_}{sym_name:35} {', '.join(locs)}"
885902
for sym_name, locs in sorted(undef_to_locs.items()))
886903

887904
self.failure(f"""
@@ -1047,10 +1064,13 @@ class KconfigBasicNoModulesCheck(KconfigBasicCheck):
10471064
"""
10481065
name = "KconfigBasicNoModules"
10491066

1050-
def get_modules(self, modules_file, settings_file):
1067+
def get_modules(self, modules_file, sysbuild_modules_file, settings_file):
10511068
with open(modules_file, 'w') as fp_module_file:
10521069
fp_module_file.write("# Empty\n")
10531070

1071+
with open(sysbuild_modules_file, 'w') as fp_module_file:
1072+
fp_module_file.write("# Empty\n")
1073+
10541074

10551075
class KconfigHWMv2Check(KconfigBasicCheck):
10561076
"""
@@ -1066,6 +1086,48 @@ class KconfigHWMv2Check(KconfigBasicCheck):
10661086
FILENAME = os.path.join(os.path.dirname(__file__), "Kconfig.board.v2")
10671087

10681088

1089+
class SysbuildKconfigCheck(KconfigCheck):
1090+
"""
1091+
Checks if we are introducing any new warnings/errors with sysbuild Kconfig,
1092+
for example using undefined Kconfig variables.
1093+
"""
1094+
name = "SysbuildKconfig"
1095+
1096+
FILENAME = "share/sysbuild/Kconfig"
1097+
CONFIG_ = "SB_CONFIG_"
1098+
1099+
# A different allowlist is used for symbols prefixed with SB_CONFIG_ (omitted here).
1100+
UNDEF_KCONFIG_ALLOWLIST = {
1101+
# zephyr-keep-sorted-start re(^\s+")
1102+
"FOO",
1103+
"SECOND_SAMPLE", # Used in sysbuild documentation
1104+
"SUIT_ENVELOPE", # Used by nRF runners to program provisioning data
1105+
"SUIT_MPI_APP_AREA_PATH", # Used by nRF runners to program provisioning data
1106+
"SUIT_MPI_GENERATE", # Used by nRF runners to program provisioning data
1107+
"SUIT_MPI_RAD_AREA_PATH", # Used by nRF runners to program provisioning data
1108+
# zephyr-keep-sorted-stop
1109+
}
1110+
1111+
1112+
class SysbuildKconfigBasicCheck(SysbuildKconfigCheck, KconfigBasicCheck):
1113+
"""
1114+
Checks if we are introducing any new warnings/errors with sysbuild Kconfig,
1115+
for example using undefined Kconfig variables.
1116+
This runs the basic Kconfig test, which is checking only for undefined
1117+
references inside the sysbuild Kconfig tree.
1118+
"""
1119+
name = "SysbuildKconfigBasic"
1120+
1121+
1122+
class SysbuildKconfigBasicNoModulesCheck(SysbuildKconfigCheck, KconfigBasicNoModulesCheck):
1123+
"""
1124+
Checks if we are introducing any new warnings/errors with sysbuild Kconfig
1125+
when no modules are available. Catches symbols used in the main repository
1126+
but defined only in a module.
1127+
"""
1128+
name = "SysbuildKconfigBasicNoModules"
1129+
1130+
10691131
class Nits(ComplianceTest):
10701132
"""
10711133
Checks various nits in added/modified files. Doesn't check stuff that's

0 commit comments

Comments
 (0)