#!/usr/bin/env python3 """Zephyr Check kconfigs Definitions Check all CONFIG_* in the code are defined into a Kconfig file usage: checkconfig.py [-h] [-k KCONFIG] [-c] [-e EXCLUDE] """ import sys import os import re import argparse from argparse import SUPPRESS help_text=""" Checkconfig script scans all '*.c', '*.h' and '*.S' looking for all kconfig items used in the Zephyr Code and validates if they are defined in any '*.kconfig*' file. To run script use command: checkconfig.py [-h|--help] [-c|--complete-log] [-k|--kconfig ] [-e|--exclude ] It will send to output: -config name -location where config is used -full line where the config is being used -location were config is being defined (there could be multiple declarations) [-c|--complete-log] is an optional parameter. If it is not given it will print only the kconfigs not defined If given, it will print all the kconfigs found [-s|--subdir ] is an optional parameter. When a directory is given it will start scan from that specific directorywith . By default it scans from zephyr base tree [-e|--exclude ] is an optional parameter. When a subdirectory is given it will be appended to defaut exclude dirs list. Default exclude dirs are: "doc", "sanity-out" and "outdir" """ #the genrest dir contains kconfiglib.py zephyrbase = os.environ.get('ZEPHYR_BASE') if zephyrbase == None: print ("env. variable ZEPHYR_BASE is not set, " "ensure you have source zephyr-env.sh") exit(1) elif not os.path.exists(zephyrbase): print ("env. variable ZEPHYR_BASE \""+ zephyrbase + "\" does not exist as a valid zephyr base directory") exit(1) os.environ['srctree'] = os.path.join(zephyrbase + os.path.sep) sys.path.append(os.path.join(zephyrbase,'doc','scripts','genrest')) import kconfiglib def separate_location_lines(dirs): for dir in dirs: print(" ", dir) def search_kconfig_items(items, name, completelog): findConfig = False for item in items: if item.is_symbol(): if (item.get_name() == name): if (completelog == True): separate_location_lines(item.get_def_locations()) findConfig = True break elif item.is_menu(): if search_kconfig_items(item.get_items(), name, completelog): return True elif item.is_choice(): if search_kconfig_items(item.get_items(), name, completelog): return True elif item.is_comment(): if (item.get_text() == name): print(completelog) if (completelog == True): separate_location_lines(item.get_location()) findConfig = True break return findConfig def search_config_in_file(tree, items, completelog, exclude): configs = 0 notdefConfig = 0 for dirName, subdirs, files in os.walk(tree, topdown=True): subdirs[:] = [d for d in subdirs if d not in exclude] for fname in files: if (fname.endswith(".c") or fname.endswith(".h") or fname.endswith(".S")): with open(os.path.join(dirName, fname), "r", encoding="utf-8", errors="ignore") as f: searchConf = f.readlines() for i, line in enumerate(searchConf): if re.search('(^|[\s|(])CONFIG_([a-zA-Z0-9_]+)', line) : configName = re.search('(^|[\s|(])' +'CONFIG_([a-zA-Z0-9_]+)', line) configs = configs + 1 if (completelog == True): print('\n' + configName.group(2) + ' at ' + os.path.join(dirName, fname)) print('line: ' + line.rstrip()) find = search_kconfig_items(items, configName.group(2), completelog) if (find == False): print('\n' + configName.group(2) + ' at ' + os.path.join(dirName, fname) + ' IS NOT DEFINED') print('line: ' + line.rstrip()) notdefConfig = notdefConfig + 1 if (completelog == True): print("\n{} Kconfigs evaluated".format(configs)) print("{} Kconfigs not defined".format(notdefConfig)) parser = argparse.ArgumentParser(description = help_text, usage = SUPPRESS, formatter_class = argparse.RawTextHelpFormatter) parser.add_argument('-s', '--subdir', action='store', dest='subdir', default="", help='sub directory to be scanned') parser.add_argument('-c', '--complete-log', action='store_true', dest='completelog', default=False, help='Prints all the kconfigs found') parser.add_argument('-e', '--exclude', action='append', dest='exclude', default=["doc", "sanity-out", "outdir"], help='Dirs to be excluded for verification') args= parser.parse_args() if args.completelog: print('sub dir = ', os.path.join(zephyrbase + args.subdir)) print('complete-log = ', args.completelog) print('exclude dirs = ', args.exclude) conf = kconfiglib.Config(os.path.join(zephyrbase,'Kconfig')) search_config_in_file(os.path.join(zephyrbase + os.path.sep + args.subdir), conf.get_top_level_items(), args.completelog, args.exclude)