@@ -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 )
@@ -485,6 +490,7 @@ def get_v2_model(self, kconfig_dir, settings_file):
485490
486491 kconfig_file = os .path .join (kconfig_dir , 'boards' , 'Kconfig' )
487492 kconfig_boards_file = os .path .join (kconfig_dir , 'boards' , 'Kconfig.boards' )
493+ kconfig_sysbuild_file = os .path .join (kconfig_dir , 'boards' , 'Kconfig.sysbuild' )
488494 kconfig_defconfig_file = os .path .join (kconfig_dir , 'boards' , 'Kconfig.defconfig' )
489495
490496 board_roots = self .get_module_setting_root ('board' , settings_file )
@@ -501,6 +507,11 @@ def get_v2_model(self, kconfig_dir, settings_file):
501507 for board_dir in board .directories :
502508 fp .write ('osource "' + (board_dir / 'Kconfig.defconfig' ).as_posix () + '"\n ' )
503509
510+ with open (kconfig_sysbuild_file , 'w' ) as fp :
511+ for board in v2_boards :
512+ for board_dir in board .directories :
513+ fp .write ('osource "' + (board_dir / 'Kconfig.sysbuild' ).as_posix () + '"\n ' )
514+
504515 with open (kconfig_boards_file , 'w' ) as fp :
505516 for board in v2_boards :
506517 board_str = 'BOARD_' + re .sub (r"[^a-zA-Z0-9_]" , "_" , board .name ).upper ()
@@ -522,6 +533,7 @@ def get_v2_model(self, kconfig_dir, settings_file):
522533 fp .write ('osource "' + (board_dir / 'Kconfig' ).as_posix () + '"\n ' )
523534
524535 kconfig_defconfig_file = os .path .join (kconfig_dir , 'soc' , 'Kconfig.defconfig' )
536+ kconfig_sysbuild_file = os .path .join (kconfig_dir , 'soc' , 'Kconfig.sysbuild' )
525537 kconfig_soc_file = os .path .join (kconfig_dir , 'soc' , 'Kconfig.soc' )
526538 kconfig_file = os .path .join (kconfig_dir , 'soc' , 'Kconfig' )
527539
@@ -533,6 +545,10 @@ def get_v2_model(self, kconfig_dir, settings_file):
533545 for folder in soc_folders :
534546 fp .write ('osource "' + (Path (folder ) / 'Kconfig.defconfig' ).as_posix () + '"\n ' )
535547
548+ with open (kconfig_sysbuild_file , 'w' ) as fp :
549+ for folder in soc_folders :
550+ fp .write ('osource "' + (Path (folder ) / 'Kconfig.sysbuild' ).as_posix () + '"\n ' )
551+
536552 with open (kconfig_soc_file , 'w' ) as fp :
537553 for folder in soc_folders :
538554 fp .write ('source "' + (Path (folder ) / 'Kconfig.soc' ).as_posix () + '"\n ' )
@@ -587,6 +603,7 @@ def parse_kconfig(self):
587603
588604 # For multi repo support
589605 self .get_modules (os .path .join (kconfiglib_dir , "Kconfig.modules" ),
606+ os .path .join (kconfiglib_dir , "Kconfig.sysbuild.modules" ),
590607 os .path .join (kconfiglib_dir , "settings_file.txt" ))
591608 # For Kconfig.dts support
592609 self .get_kconfig_dts (os .path .join (kconfiglib_dir , "Kconfig.dts" ),
@@ -833,7 +850,7 @@ def check_no_undef_outside_kconfig(self, kconf):
833850 undef_to_locs = collections .defaultdict (list )
834851
835852 # Warning: Needs to work with both --perl-regexp and the 're' module
836- regex = r"\bCONFIG_ [A-Z0-9_]+\b(?!\s*##|[$@{(.*])"
853+ regex = r"\b" + self . CONFIG_ + r" [A-Z0-9_]+\b(?!\s*##|[$@{(.*])"
837854
838855 # Skip doc/releases and doc/security/vulnerabilities.rst, which often
839856 # reference removed symbols
@@ -849,7 +866,7 @@ def check_no_undef_outside_kconfig(self, kconf):
849866 # Extract symbol references (might be more than one) within the
850867 # line
851868 for sym_name in re .findall (regex , line ):
852- sym_name = sym_name [7 :] # Strip CONFIG_
869+ sym_name = sym_name [len ( self . CONFIG_ ) :] # Strip CONFIG_
853870 if sym_name not in defined_syms and \
854871 sym_name not in self .UNDEF_KCONFIG_ALLOWLIST and \
855872 not (sym_name .endswith ("_MODULE" ) and sym_name [:- 7 ] in defined_syms ):
@@ -865,7 +882,7 @@ def check_no_undef_outside_kconfig(self, kconf):
865882 #
866883 # CONFIG_ALSO_MISSING arch/xtensa/core/fatal.c:273
867884 # CONFIG_MISSING arch/xtensa/core/fatal.c:264, subsys/fb/cfb.c:20
868- undef_desc = "\n " .join (f"CONFIG_{ sym_name :35} { ', ' .join (locs )} "
885+ undef_desc = "\n " .join (f"{ self . CONFIG_ } { sym_name :35} { ', ' .join (locs )} "
869886 for sym_name , locs in sorted (undef_to_locs .items ()))
870887
871888 self .failure (f"""
@@ -1031,10 +1048,13 @@ class KconfigBasicNoModulesCheck(KconfigBasicCheck):
10311048 """
10321049 name = "KconfigBasicNoModules"
10331050
1034- def get_modules (self , modules_file , settings_file ):
1051+ def get_modules (self , modules_file , sysbuild_modules_file , settings_file ):
10351052 with open (modules_file , 'w' ) as fp_module_file :
10361053 fp_module_file .write ("# Empty\n " )
10371054
1055+ with open (sysbuild_modules_file , 'w' ) as fp_module_file :
1056+ fp_module_file .write ("# Empty\n " )
1057+
10381058
10391059class KconfigHWMv2Check (KconfigBasicCheck ):
10401060 """
@@ -1050,6 +1070,48 @@ class KconfigHWMv2Check(KconfigBasicCheck):
10501070 FILENAME = os .path .join (os .path .dirname (__file__ ), "Kconfig.board.v2" )
10511071
10521072
1073+ class SysbuildKconfigCheck (KconfigCheck ):
1074+ """
1075+ Checks if we are introducing any new warnings/errors with sysbuild Kconfig,
1076+ for example using undefined Kconfig variables.
1077+ """
1078+ name = "SysbuildKconfig"
1079+
1080+ FILENAME = "share/sysbuild/Kconfig"
1081+ CONFIG_ = "SB_CONFIG_"
1082+
1083+ # A different allowlist is used for symbols prefixed with SB_CONFIG_ (omitted here).
1084+ UNDEF_KCONFIG_ALLOWLIST = {
1085+ # zephyr-keep-sorted-start re(^\s+")
1086+ "FOO" ,
1087+ "SECOND_SAMPLE" , # Used in sysbuild documentation
1088+ "SUIT_ENVELOPE" , # Used by nRF runners to program provisioning data
1089+ "SUIT_MPI_APP_AREA_PATH" , # Used by nRF runners to program provisioning data
1090+ "SUIT_MPI_GENERATE" , # Used by nRF runners to program provisioning data
1091+ "SUIT_MPI_RAD_AREA_PATH" , # Used by nRF runners to program provisioning data
1092+ # zephyr-keep-sorted-stop
1093+ }
1094+
1095+
1096+ class SysbuildKconfigBasicCheck (SysbuildKconfigCheck , KconfigBasicCheck ):
1097+ """
1098+ Checks if we are introducing any new warnings/errors with sysbuild Kconfig,
1099+ for example using undefined Kconfig variables.
1100+ This runs the basic Kconfig test, which is checking only for undefined
1101+ references inside the sysbuild Kconfig tree.
1102+ """
1103+ name = "SysbuildKconfigBasic"
1104+
1105+
1106+ class SysbuildKconfigBasicNoModulesCheck (SysbuildKconfigCheck , KconfigBasicNoModulesCheck ):
1107+ """
1108+ Checks if we are introducing any new warnings/errors with sysbuild Kconfig
1109+ when no modules are available. Catches symbols used in the main repository
1110+ but defined only in a module.
1111+ """
1112+ name = "SysbuildKconfigBasicNoModules"
1113+
1114+
10531115class Nits (ComplianceTest ):
10541116 """
10551117 Checks various nits in added/modified files. Doesn't check stuff that's
0 commit comments