1 #!/usr/bin/env python 2 # 3 # this program is used to find source code that includes linux kernel headers directly 4 # (e.g. with #include <linux/...> or #include <asm/...>) 5 # 6 # then it lists 7 8 import sys, cpp, glob, os, re, getopt, kernel 9 from utils import * 10 from defaults import * 11 12 program_dir = find_program_dir() 13 14 wanted_archs = kernel_archs 15 wanted_include = os.path.normpath(program_dir + '/../original') 16 wanted_config = os.path.normpath(program_dir + '/../original/config') 17 18 def usage(): 19 print """\ 20 usage: find_headers.py [options] (file|directory|@listfile)+ 21 22 options: 23 -d <include-dir> specify alternate kernel headers 24 'include' directory 25 ('%s' by default) 26 27 -c <file> specify alternate .config file 28 ('%s' by default) 29 30 -a <archs> used to specify an alternative list 31 of architectures to support 32 ('%s' by default) 33 34 -v enable verbose mode 35 36 this program is used to find all the kernel headers that are used 37 by a set of source files or directories containing them. the search 38 is recursive to find *all* required files. 39 40 """ % ( wanted_include, wanted_config, string.join(kernel_archs,",") ) 41 sys.exit(1) 42 43 44 try: 45 optlist, args = getopt.getopt( sys.argv[1:], 'vc:d:a:' ) 46 except: 47 # unrecognized option 48 print "error: unrecognized option" 49 usage() 50 51 for opt, arg in optlist: 52 if opt == '-a': 53 wanted_archs = string.split(arg,',') 54 elif opt == '-d': 55 wanted_include = arg 56 elif opt == '-c': 57 wanted_config = arg 58 elif opt == '-v': 59 kernel.verboseSearch = 1 60 kernel.verboseFind = 1 61 verbose = 1 62 else: 63 usage() 64 65 if len(args) < 1: 66 usage() 67 68 kernel_root = wanted_include 69 if not os.path.exists(kernel_root): 70 sys.stderr.write( "error: directory '%s' does not exist\n" % kernel_root ) 71 sys.exit(1) 72 73 if not os.path.isdir(kernel_root): 74 sys.stderr.write( "error: '%s' is not a directory\n" % kernel_root ) 75 sys.exit(1) 76 77 if not os.path.isdir(kernel_root+"/linux"): 78 sys.stderr.write( "error: '%s' does not have a 'linux' directory\n" % kernel_root ) 79 sys.exit(1) 80 81 if not os.path.exists(wanted_config): 82 sys.stderr.write( "error: file '%s' does not exist\n" % wanted_config ) 83 sys.exit(1) 84 85 if not os.path.isfile(wanted_config): 86 sys.stderr.write( "error: '%s' is not a file\n" % wanted_config ) 87 sys.exit(1) 88 89 # find all architectures in the kernel tree 90 re_asm_ = re.compile(r"asm-(\w+)") 91 archs = [] 92 for dir in os.listdir(kernel_root): 93 m = re_asm_.match(dir) 94 if m: 95 if verbose: print ">> found kernel arch '%s'" % m.group(1) 96 archs.append(m.group(1)) 97 98 # if we're using the 'kernel_headers' directory, there is only asm/ 99 # and no other asm-<arch> directories (arm is assumed, which sucks) 100 # 101 in_kernel_headers = False 102 if len(archs) == 0: 103 # this can happen when we're using the 'kernel_headers' directory 104 if os.path.isdir(kernel_root+"/asm"): 105 in_kernel_headers = True 106 archs = [ "arm" ] 107 108 # if the user has specified some architectures with -a <archs> ensure that 109 # all those he wants are available from the kernel include tree 110 if wanted_archs != None: 111 if in_kernel_headers and wanted_archs != [ "arm" ]: 112 sys.stderr.write( "error: when parsing kernel_headers, 'arm' architecture only is supported at the moment\n" ) 113 sys.exit(1) 114 missing = [] 115 for arch in wanted_archs: 116 if arch not in archs: 117 missing.append(arch) 118 if len(missing) > 0: 119 sys.stderr.write( "error: the following requested architectures are not in the kernel tree: " ) 120 for a in missing: 121 sys.stderr.write( " %s" % a ) 122 sys.stderr.write( "\n" ) 123 sys.exit(1) 124 125 archs = wanted_archs 126 127 # helper function used to walk the user files 128 def parse_file(path, parser): 129 parser.parseFile(path) 130 131 132 # remove previous destination directory 133 #destdir = "/tmp/bionic-kernel-headers/" 134 #cleanup_dir(destdir) 135 136 # try to read the config file 137 try: 138 cparser = kernel.ConfigParser() 139 cparser.parseFile( wanted_config ) 140 except: 141 sys.stderr.write( "error: can't parse '%s'" % wanted_config ) 142 sys.exit(1) 143 144 kernel_config = cparser.getDefinitions() 145 146 # first, obtain the list of kernel files used by our clients 147 fparser = kernel.HeaderScanner() 148 walk_source_files( args, parse_file, fparser, excludes=["kernel_headers"] ) 149 headers = fparser.getHeaders() 150 files = fparser.getFiles() 151 152 # now recursively scan the kernel headers for additionnal sub-included headers 153 hparser = kernel.KernelHeaderFinder(headers,archs,kernel_root,kernel_config) 154 headers = hparser.scanForAllArchs() 155 156 if 0: # just for debugging 157 dumpHeaderUsers = False 158 159 print "the following %d headers:" % len(headers) 160 for h in sorted(headers): 161 if dumpHeaderUsers: 162 print " %s (%s)" % (h, repr(hparser.getHeaderUsers(h))) 163 else: 164 print " %s" % h 165 166 print "are used by the following %d files:" % len(files) 167 for f in sorted(files): 168 print " %s" % f 169 170 sys.exit(0) 171 172 for h in sorted(headers): 173 print h 174 175 sys.exit(0) 176