summaryrefslogtreecommitdiffstats
path: root/scripts/contrib
diff options
context:
space:
mode:
authorDarren Hart <dvhart@linux.intel.com>2011-01-11 15:29:58 -0800
committerSaul Wold <sgw@linux.intel.com>2011-01-12 00:55:49 -0800
commite5e3fb23a2c5d8e40e4f751d804d9ea6fc3bfd2f (patch)
tree88a070e2e6c16605cd799987af9a1c87997606a6 /scripts/contrib
parent514e59c780ac24439ae0839fab311d843841bf68 (diff)
downloadpoky-e5e3fb23a2c5d8e40e4f751d804d9ea6fc3bfd2f.tar.gz
bbvars.py: add a script to look for undocumented variables
bbvars.py will compare recipes in meta directories with documentation files and report on variables that don't appear to be documented. It reports the number of times a variable is used as well as any doctags present in the documentation config file. The output of this is intended to aid in determining where documentation may be lacking, but it is not perfect, and does generate some false positives. An experienced eye and careful attention to count and doctag should be applied to the results. $ ./bbvars.py -d ../../documentation/poky-ref-manual/poky-ref-manual.html -m ../../meta -t ../../meta/conf/documentation.conf -T | head -n 10 Found 1413 undocumented bb variables (out of 1578): VARIABLE COUNT DOCTAG =================================================== BUILD_ARCH 4 The name of the building architecture. E.g. i686. BUILD_CC_ARCH 2 FIXME BUILD_PREFIX 4 FIXME BUILD_SYS 13 FIXME BUILD_VENDOR 2 FIXME CACHE 1 The directory holding the cache of the metadata. COMPATIBLE_HOST 19 A regular expression which matches the HOST_SYS names supported by the package/file. Failure to match will cause the file to be skipped by the parser. Signed-off-by: Darren Hart <dvhart@linux.intel.com> CC: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'scripts/contrib')
-rwxr-xr-xscripts/contrib/bbvars.py186
1 files changed, 186 insertions, 0 deletions
diff --git a/scripts/contrib/bbvars.py b/scripts/contrib/bbvars.py
new file mode 100755
index 0000000000..0896d64445
--- /dev/null
+++ b/scripts/contrib/bbvars.py
@@ -0,0 +1,186 @@
1#!/usr/bin/env python
2
3# This program is free software; you can redistribute it and/or modify
4# it under the terms of the GNU General Public License as published by
5# the Free Software Foundation; either version 2 of the License, or
6# (at your option) any later version.
7#
8# This program is distributed in the hope that it will be useful,
9# but WITHOUT ANY WARRANTY; without even the implied warranty of
10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11# GNU General Public License for more details.
12#
13# You should have received a copy of the GNU General Public License
14# along with this program; if not, write to the Free Software
15# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16#
17# Copyright (C) Darren Hart <dvhart@linux.intel.com>, 2010
18
19
20import sys
21import getopt
22import os
23import os.path
24import re
25
26def usage():
27 print 'Usage: %s -d FILENAME [-d FILENAME]* -m METADIR [-m MATADIR]*' % os.path.basename(sys.argv[0])
28 print ' -d FILENAME documentation file to search'
29 print ' -h, --help display this help and exit'
30 print ' -m METADIR meta directory to search for recipes'
31 print ' -t FILENAME documentation config file (for doc tags)'
32 print ' -T Only display variables with doc tags (requires -t)'
33
34def recipe_bbvars(recipe):
35 ''' Return a unique set of every bbvar encountered in the recipe '''
36 prog = re.compile("[A-Z_]+")
37 vset = set()
38 try:
39 r = open(recipe)
40 except IOError as (errno, strerror):
41 print 'WARNING: Failed to open recipe ', recipe
42 print strerror
43
44 for line in r:
45 # Strip any comments from the line
46 line = line.rsplit('#')[0]
47 vset = vset.union(set(prog.findall(line)))
48 r.close()
49
50 bbvars = {}
51 for v in vset:
52 bbvars[v] = 1
53
54 return bbvars
55
56def collect_bbvars(metadir):
57 ''' Walk the metadir and collect the bbvars from each recipe found '''
58 bbvars = {}
59 for root,dirs,files in os.walk(metadir):
60 for name in files:
61 if name.find(".bb") >= 0:
62 for key in recipe_bbvars(os.path.join(root,name)).iterkeys():
63 if bbvars.has_key(key):
64 bbvars[key] = bbvars[key] + 1
65 else:
66 bbvars[key] = 1
67 return bbvars
68
69def bbvar_is_documented(var, docfiles):
70 prog = re.compile(".*($|[^A-Z_])%s([^A-Z_]|$)" % (var))
71 for doc in docfiles:
72 try:
73 f = open(doc)
74 except IOError as (errno, strerror):
75 print 'WARNING: Failed to open doc ', doc
76 print strerror
77 for line in f:
78 if prog.match(line):
79 return True
80 f.close()
81 return False
82
83def bbvar_doctag(var, docconf):
84 prog = re.compile('^%s\[doc\] *= *"(.*)"' % (var))
85 if docconf == "":
86 return "?"
87
88 try:
89 f = open(docconf)
90 except IOError as (errno, strerror):
91 return strerror
92
93 for line in f:
94 m = prog.search(line)
95 if m:
96 return m.group(1)
97
98 f.close()
99 return ""
100
101def main():
102 docfiles = []
103 metadirs = []
104 bbvars = {}
105 undocumented = []
106 docconf = ""
107 onlydoctags = False
108
109 # Collect and validate input
110 try:
111 opts, args = getopt.getopt(sys.argv[1:], "d:hm:t:T", ["help"])
112 except getopt.GetoptError, err:
113 print '%s' % str(err)
114 usage()
115 sys.exit(2)
116
117 for o, a in opts:
118 if o in ('-h', '--help'):
119 usage()
120 sys.exit(0)
121 elif o == '-d':
122 if os.path.isfile(a):
123 docfiles.append(a)
124 else:
125 print 'ERROR: documentation file %s is not a regular file' % (a)
126 sys.exit(3)
127 elif o == '-m':
128 if os.path.isdir(a):
129 metadirs.append(a)
130 else:
131 print 'ERROR: meta directory %s is not a directory' % (a)
132 sys.exit(4)
133 elif o == "-t":
134 if os.path.isfile(a):
135 docconf = a
136 elif o == "-T":
137 onlydoctags = True
138 else:
139 assert False, "unhandled option"
140
141 if len(docfiles) == 0:
142 print 'ERROR: no docfile specified'
143 usage()
144 sys.exit(5)
145
146 if len(metadirs) == 0:
147 print 'ERROR: no metadir specified'
148 usage()
149 sys.exit(6)
150
151 if onlydoctags and docconf == "":
152 print 'ERROR: no docconf specified'
153 usage()
154 sys.exit(7)
155
156 # Collect all the variable names from the recipes in the metadirs
157 for m in metadirs:
158 for key,cnt in collect_bbvars(m).iteritems():
159 if bbvars.has_key(key):
160 bbvars[key] = bbvars[key] + cnt
161 else:
162 bbvars[key] = cnt
163
164 # Check each var for documentation
165 varlen = 0
166 for v in bbvars.iterkeys():
167 if len(v) > varlen:
168 varlen = len(v)
169 if not bbvar_is_documented(v, docfiles):
170 undocumented.append(v)
171 undocumented.sort()
172 varlen = varlen + 1
173
174 # Report all undocumented variables
175 print 'Found %d undocumented bb variables (out of %d):' % (len(undocumented), len(bbvars))
176 header = '%s%s%s' % (str("VARIABLE").ljust(varlen), str("COUNT").ljust(6), str("DOCTAG").ljust(7))
177 print header
178 print str("").ljust(len(header), '=')
179 for v in undocumented:
180 doctag = bbvar_doctag(v, docconf)
181 if not onlydoctags or not doctag == "":
182 print '%s%s%s' % (v.ljust(varlen), str(bbvars[v]).ljust(6), doctag)
183
184
185if __name__ == "__main__":
186 main()