@@ -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
10551075class 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+
10691131class Nits (ComplianceTest ):
10701132 """
10711133 Checks various nits in added/modified files. Doesn't check stuff that's
0 commit comments