Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 1 | #!/usr/bin/env python3 |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 2 | # |
Brad Bishop | c342db3 | 2019-05-15 21:57:59 -0400 | [diff] [blame] | 3 | # SPDX-License-Identifier: GPL-2.0-or-later |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 4 | # |
| 5 | # Copyright (C) Darren Hart <dvhart@linux.intel.com>, 2010 |
| 6 | |
| 7 | |
| 8 | import sys |
| 9 | import getopt |
| 10 | import os |
| 11 | import os.path |
| 12 | import re |
| 13 | |
Brad Bishop | 316dfdd | 2018-06-25 12:45:53 -0400 | [diff] [blame] | 14 | # Set up sys.path to let us import tinfoil |
| 15 | scripts_path = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) |
| 16 | lib_path = scripts_path + '/lib' |
| 17 | sys.path.insert(0, lib_path) |
| 18 | import scriptpath |
| 19 | scriptpath.add_bitbake_lib_path() |
| 20 | import bb.tinfoil |
| 21 | |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 22 | def usage(): |
Brad Bishop | 316dfdd | 2018-06-25 12:45:53 -0400 | [diff] [blame] | 23 | print('Usage: %s -d FILENAME [-d FILENAME]*' % os.path.basename(sys.argv[0])) |
Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 24 | print(' -d FILENAME documentation file to search') |
| 25 | print(' -h, --help display this help and exit') |
Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 26 | print(' -t FILENAME documentation config file (for doc tags)') |
| 27 | print(' -T Only display variables with doc tags (requires -t)') |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 28 | |
Brad Bishop | 316dfdd | 2018-06-25 12:45:53 -0400 | [diff] [blame] | 29 | def bbvar_is_documented(var, documented_vars): |
| 30 | ''' Check if variable (var) is in the list of documented variables(documented_vars) ''' |
| 31 | if var in documented_vars: |
| 32 | return True |
| 33 | else: |
| 34 | return False |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 35 | |
Brad Bishop | 316dfdd | 2018-06-25 12:45:53 -0400 | [diff] [blame] | 36 | def collect_documented_vars(docfiles): |
| 37 | ''' Walk the docfiles and collect the documented variables ''' |
| 38 | documented_vars = [] |
Patrick Williams | 73bd93f | 2024-02-20 08:07:48 -0600 | [diff] [blame] | 39 | prog = re.compile(r".*($|[^A-Z_])<glossentry id=\'var-") |
| 40 | var_prog = re.compile(r'<glossentry id=\'var-(.*)\'>') |
Brad Bishop | 316dfdd | 2018-06-25 12:45:53 -0400 | [diff] [blame] | 41 | for d in docfiles: |
| 42 | with open(d) as f: |
| 43 | documented_vars += var_prog.findall(f.read()) |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 44 | |
Brad Bishop | 316dfdd | 2018-06-25 12:45:53 -0400 | [diff] [blame] | 45 | return documented_vars |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 46 | |
| 47 | def bbvar_doctag(var, docconf): |
Patrick Williams | 73bd93f | 2024-02-20 08:07:48 -0600 | [diff] [blame] | 48 | prog = re.compile(r'^%s\[doc\] *= *"(.*)"' % (var)) |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 49 | if docconf == "": |
| 50 | return "?" |
| 51 | |
| 52 | try: |
| 53 | f = open(docconf) |
Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 54 | except IOError as err: |
| 55 | return err.args[1] |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 56 | |
| 57 | for line in f: |
| 58 | m = prog.search(line) |
| 59 | if m: |
| 60 | return m.group(1) |
| 61 | |
| 62 | f.close() |
| 63 | return "" |
| 64 | |
| 65 | def main(): |
| 66 | docfiles = [] |
Brad Bishop | 316dfdd | 2018-06-25 12:45:53 -0400 | [diff] [blame] | 67 | bbvars = set() |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 68 | undocumented = [] |
| 69 | docconf = "" |
| 70 | onlydoctags = False |
| 71 | |
| 72 | # Collect and validate input |
| 73 | try: |
| 74 | opts, args = getopt.getopt(sys.argv[1:], "d:hm:t:T", ["help"]) |
Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 75 | except getopt.GetoptError as err: |
| 76 | print('%s' % str(err)) |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 77 | usage() |
| 78 | sys.exit(2) |
| 79 | |
| 80 | for o, a in opts: |
| 81 | if o in ('-h', '--help'): |
| 82 | usage() |
| 83 | sys.exit(0) |
| 84 | elif o == '-d': |
| 85 | if os.path.isfile(a): |
| 86 | docfiles.append(a) |
| 87 | else: |
Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 88 | print('ERROR: documentation file %s is not a regular file' % a) |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 89 | sys.exit(3) |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 90 | elif o == "-t": |
| 91 | if os.path.isfile(a): |
| 92 | docconf = a |
| 93 | elif o == "-T": |
| 94 | onlydoctags = True |
| 95 | else: |
| 96 | assert False, "unhandled option" |
| 97 | |
| 98 | if len(docfiles) == 0: |
Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 99 | print('ERROR: no docfile specified') |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 100 | usage() |
| 101 | sys.exit(5) |
| 102 | |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 103 | if onlydoctags and docconf == "": |
Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 104 | print('ERROR: no docconf specified') |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 105 | usage() |
| 106 | sys.exit(7) |
| 107 | |
Brad Bishop | 316dfdd | 2018-06-25 12:45:53 -0400 | [diff] [blame] | 108 | prog = re.compile("^[^a-z]*$") |
| 109 | with bb.tinfoil.Tinfoil() as tinfoil: |
| 110 | tinfoil.prepare(config_only=False) |
| 111 | parser = bb.codeparser.PythonParser('parser', None) |
| 112 | datastore = tinfoil.config_data |
| 113 | |
| 114 | def bbvars_update(data): |
| 115 | if prog.match(data): |
| 116 | bbvars.add(data) |
| 117 | if tinfoil.config_data.getVarFlag(data, 'python'): |
| 118 | try: |
| 119 | parser.parse_python(tinfoil.config_data.getVar(data)) |
| 120 | except bb.data_smart.ExpansionError: |
| 121 | pass |
| 122 | for var in parser.references: |
| 123 | if prog.match(var): |
| 124 | bbvars.add(var) |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 125 | else: |
Brad Bishop | 316dfdd | 2018-06-25 12:45:53 -0400 | [diff] [blame] | 126 | try: |
| 127 | expandedVar = datastore.expandWithRefs(datastore.getVar(data, False), data) |
| 128 | for var in expandedVar.references: |
| 129 | if prog.match(var): |
| 130 | bbvars.add(var) |
| 131 | except bb.data_smart.ExpansionError: |
| 132 | pass |
| 133 | |
| 134 | # Use tinfoil to collect all the variable names globally |
| 135 | for data in datastore: |
| 136 | bbvars_update(data) |
| 137 | |
| 138 | # Collect variables from all recipes |
| 139 | for recipe in tinfoil.all_recipe_files(variants=False): |
| 140 | print("Checking %s" % recipe) |
| 141 | for data in tinfoil.parse_recipe_file(recipe): |
| 142 | bbvars_update(data) |
| 143 | |
| 144 | documented_vars = collect_documented_vars(docfiles) |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 145 | |
| 146 | # Check each var for documentation |
| 147 | varlen = 0 |
Brad Bishop | 316dfdd | 2018-06-25 12:45:53 -0400 | [diff] [blame] | 148 | for v in bbvars: |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 149 | if len(v) > varlen: |
| 150 | varlen = len(v) |
Brad Bishop | 316dfdd | 2018-06-25 12:45:53 -0400 | [diff] [blame] | 151 | if not bbvar_is_documented(v, documented_vars): |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 152 | undocumented.append(v) |
| 153 | undocumented.sort() |
| 154 | varlen = varlen + 1 |
| 155 | |
| 156 | # Report all undocumented variables |
Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 157 | print('Found %d undocumented bb variables (out of %d):' % (len(undocumented), len(bbvars))) |
Brad Bishop | 316dfdd | 2018-06-25 12:45:53 -0400 | [diff] [blame] | 158 | header = '%s%s' % (str("VARIABLE").ljust(varlen), str("DOCTAG").ljust(7)) |
Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 159 | print(header) |
| 160 | print(str("").ljust(len(header), '=')) |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 161 | for v in undocumented: |
| 162 | doctag = bbvar_doctag(v, docconf) |
| 163 | if not onlydoctags or not doctag == "": |
Brad Bishop | 316dfdd | 2018-06-25 12:45:53 -0400 | [diff] [blame] | 164 | print('%s%s' % (v.ljust(varlen), doctag)) |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 165 | |
| 166 | |
| 167 | if __name__ == "__main__": |
| 168 | main() |