blob: 0a91dfd06b66fabb8737fa62fd1e3bfe99684b7a [file] [log] [blame]
Punit Vara2f28bf52017-06-08 14:40:48 +05301#!/usr/bin/env python3
Sonia Leon Bautista616e9622016-06-14 17:55:24 -05002
3"""Zephyr Check kconfigs Definitions
4
5Check all CONFIG_* in the code are defined into a Kconfig file
6
7usage: checkconfig.py [-h] [-k KCONFIG] [-c] [-e EXCLUDE]
8
9"""
10
11import sys
12import os
13import re
14import argparse
15from argparse import SUPPRESS
16
17help_text="""
18Checkconfig script scans all '*.c', '*.h' and '*.S' looking for all kconfig
19items used in the Zephyr Code and validates if they are defined in any
20'*.kconfig*' file.
21
22To run script use command:
23
24checkconfig.py [-h|--help] [-c|--complete-log] [-k|--kconfig <kconfig>]
25 [-e|--exclude <dir_to_exclude>]
26
27It will send to output:
28-config name
29-location where config is used
30-full line where the config is being used
31-location were config is being defined (there could be multiple declarations)
32
33 [-c|--complete-log] is an optional parameter.
34 If it is not given it will print only the kconfigs not defined
35 If given, it will print all the kconfigs found
36
37 [-s|--subdir <subdir>] is an optional parameter.
38 When a directory is given it will start scan from that specific directorywith .
39 By default it scans from zephyr base tree
40
41 [-e|--exclude <subdir_to_exclude>] is an optional parameter.
42 When a subdirectory is given it will be appended to defaut exclude dirs list.
43 Default exclude dirs are: "doc", "sanity-out" and "outdir"
44"""
45
46#the genrest dir contains kconfiglib.py
47zephyrbase = os.environ.get('ZEPHYR_BASE')
48
49if zephyrbase == None:
50 print ("env. variable ZEPHYR_BASE is not set, "
51 "ensure you have source zephyr-env.sh")
52 exit(1)
53elif not os.path.exists(zephyrbase):
54 print ("env. variable ZEPHYR_BASE \""+ zephyrbase +
55 "\" does not exist as a valid zephyr base directory")
56 exit(1)
57
58os.environ['srctree'] = os.path.join(zephyrbase + os.path.sep)
59sys.path.append(os.path.join(zephyrbase,'doc','scripts','genrest'))
60
61import kconfiglib
62
63def separate_location_lines(dirs):
64 for dir in dirs:
Punit Vara2f28bf52017-06-08 14:40:48 +053065 print(" ", dir)
Sonia Leon Bautista616e9622016-06-14 17:55:24 -050066
67def search_kconfig_items(items, name, completelog):
68 findConfig = False
69 for item in items:
70 if item.is_symbol():
71 if (item.get_name() == name):
72 if (completelog == True):
73 separate_location_lines(item.get_def_locations())
74 findConfig = True
75 break
76
77 elif item.is_menu():
78 if search_kconfig_items(item.get_items(), name, completelog):
79 return True
80
81 elif item.is_choice():
82 if search_kconfig_items(item.get_items(), name, completelog):
83 return True
84
85 elif item.is_comment():
86 if (item.get_text() == name):
Punit Vara2f28bf52017-06-08 14:40:48 +053087 print(completelog)
Sonia Leon Bautista616e9622016-06-14 17:55:24 -050088 if (completelog == True):
89 separate_location_lines(item.get_location())
90 findConfig = True
91 break
92 return findConfig
93
94def search_config_in_file(tree, items, completelog, exclude):
95 configs = 0
96 notdefConfig = 0
97 for dirName, subdirs, files in os.walk(tree, topdown=True):
98 subdirs[:] = [d for d in subdirs if d not in exclude]
99 for fname in files:
100 if (fname.endswith(".c") or
101 fname.endswith(".h") or
102 fname.endswith(".S")):
Punit Vara2f28bf52017-06-08 14:40:48 +0530103 with open(os.path.join(dirName, fname), "r", encoding="utf-8", errors="ignore") as f:
Sonia Leon Bautista616e9622016-06-14 17:55:24 -0500104 searchConf = f.readlines()
105 for i, line in enumerate(searchConf):
106 if re.search('(^|[\s|(])CONFIG_([a-zA-Z0-9_]+)', line) :
107 configName = re.search('(^|[\s|(])'
108 +'CONFIG_([a-zA-Z0-9_]+)', line)
109 configs = configs + 1
110 if (completelog == True):
Punit Vara2f28bf52017-06-08 14:40:48 +0530111 print('\n' + configName.group(2) + ' at '
Sonia Leon Bautista616e9622016-06-14 17:55:24 -0500112 + os.path.join(dirName, fname))
Punit Vara2f28bf52017-06-08 14:40:48 +0530113 print('line: ' + line.rstrip())
Sonia Leon Bautista616e9622016-06-14 17:55:24 -0500114 find = search_kconfig_items(items, configName.group(2),
115 completelog)
116 if (find == False):
Punit Vara2f28bf52017-06-08 14:40:48 +0530117 print('\n' + configName.group(2) + ' at '
Sonia Leon Bautista616e9622016-06-14 17:55:24 -0500118 + os.path.join(dirName, fname)
119 + ' IS NOT DEFINED')
Punit Vara2f28bf52017-06-08 14:40:48 +0530120 print('line: ' + line.rstrip())
Sonia Leon Bautista616e9622016-06-14 17:55:24 -0500121 notdefConfig = notdefConfig + 1
122 if (completelog == True):
Punit Vara2f28bf52017-06-08 14:40:48 +0530123 print("\n{} Kconfigs evaluated".format(configs))
124 print("{} Kconfigs not defined".format(notdefConfig))
Sonia Leon Bautista616e9622016-06-14 17:55:24 -0500125
126parser = argparse.ArgumentParser(description = help_text,
127 usage = SUPPRESS,
128 formatter_class = argparse.RawTextHelpFormatter)
129parser.add_argument('-s', '--subdir', action='store', dest='subdir',
130 default="",
131 help='sub directory to be scanned')
132parser.add_argument('-c', '--complete-log', action='store_true',
133 dest='completelog', default=False,
134 help='Prints all the kconfigs found')
135parser.add_argument('-e', '--exclude', action='append', dest='exclude',
136 default=["doc", "sanity-out", "outdir"],
137 help='Dirs to be excluded for verification')
138
139args= parser.parse_args()
140if args.completelog:
Punit Vara2f28bf52017-06-08 14:40:48 +0530141 print('sub dir = ', os.path.join(zephyrbase + args.subdir))
142 print('complete-log = ', args.completelog)
143 print('exclude dirs = ', args.exclude)
Sonia Leon Bautista616e9622016-06-14 17:55:24 -0500144
145conf = kconfiglib.Config(os.path.join(zephyrbase,'Kconfig'))
146search_config_in_file(os.path.join(zephyrbase + os.path.sep + args.subdir),
147 conf.get_top_level_items(), args.completelog, args.exclude)