blob: 0a91dfd06b66fabb8737fa62fd1e3bfe99684b7a [file] [log] [blame]
#!/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 <kconfig>]
[-e|--exclude <dir_to_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 <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 <subdir_to_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)