|  | #!/usr/bin/env python | 
|  | # | 
|  | # this program is used to find source code that includes linux kernel headers directly | 
|  | # (e.g. with #include <linux/...> or #include <asm/...>) | 
|  | # | 
|  | # then it lists them on the standard output. | 
|  |  | 
|  | import sys, cpp, glob, os, re, getopt, kernel | 
|  | from utils import * | 
|  | from defaults import * | 
|  |  | 
|  | program_dir = find_program_dir() | 
|  |  | 
|  | wanted_archs   = kernel_archs | 
|  | wanted_config  = None | 
|  |  | 
|  | def usage(): | 
|  | print """\ | 
|  | usage:  find_headers.py [options] <kernel-root> (file|directory|@listfile)+ | 
|  |  | 
|  | options: | 
|  | -c <file>          specify .config file (none by default) | 
|  |  | 
|  | -a <archs>         used to specify an alternative list | 
|  | of architectures to support | 
|  | ('%s' by default) | 
|  |  | 
|  | -v                 enable verbose mode | 
|  |  | 
|  | this program is used to find all the kernel headers that are used | 
|  | by a set of source files or directories containing them. the search | 
|  | is recursive to find *all* required files. | 
|  |  | 
|  | """ % ( string.join(kernel_archs,",") ) | 
|  | sys.exit(1) | 
|  |  | 
|  |  | 
|  | try: | 
|  | optlist, args = getopt.getopt( sys.argv[1:], 'vc:d:a:k:' ) | 
|  | except: | 
|  | # unrecognized option | 
|  | print "error: unrecognized option" | 
|  | usage() | 
|  |  | 
|  | for opt, arg in optlist: | 
|  | if opt == '-a': | 
|  | wanted_archs = string.split(arg,',') | 
|  | elif opt == '-c': | 
|  | wanted_config = arg | 
|  | elif opt == '-v': | 
|  | kernel.verboseSearch = 1 | 
|  | kernel.verboseFind   = 1 | 
|  | verbose = 1 | 
|  | else: | 
|  | usage() | 
|  |  | 
|  | if len(args) < 2: | 
|  | usage() | 
|  |  | 
|  | kernel_root = args[0] | 
|  | if not os.path.exists(kernel_root): | 
|  | sys.stderr.write( "error: directory '%s' does not exist\n" % kernel_root ) | 
|  | sys.exit(1) | 
|  |  | 
|  | if not os.path.isdir(kernel_root): | 
|  | sys.stderr.write( "error: '%s' is not a directory\n" % kernel_root ) | 
|  | sys.exit(1) | 
|  |  | 
|  | if not os.path.isdir(kernel_root+"/include/linux"): | 
|  | sys.stderr.write( "error: '%s' does not have an 'include/linux' directory\n" % kernel_root ) | 
|  | sys.exit(1) | 
|  |  | 
|  | if wanted_config: | 
|  | if not os.path.exists(wanted_config): | 
|  | sys.stderr.write( "error: file '%s' does not exist\n" % wanted_config ) | 
|  | sys.exit(1) | 
|  |  | 
|  | if not os.path.isfile(wanted_config): | 
|  | sys.stderr.write( "error: '%s' is not a file\n" % wanted_config ) | 
|  | sys.exit(1) | 
|  |  | 
|  | # find all architectures in the kernel tree | 
|  | archs   = [] | 
|  | for archdir in os.listdir(kernel_root+"/arch"): | 
|  | if os.path.exists("%s/arch/%s/include/asm" % (kernel_root, archdir)): | 
|  | if verbose: | 
|  | print "Found arch '%s'" % archdir | 
|  | archs.append(archdir) | 
|  |  | 
|  | # if we're using the 'kernel_headers' directory, there is only asm/ | 
|  | # and no other asm-<arch> directories (arm is assumed, which sucks) | 
|  | # | 
|  | in_kernel_headers = False | 
|  | if len(archs) == 0: | 
|  | # this can happen when we're using the 'kernel_headers' directory | 
|  | if os.path.isdir(kernel_root+"/asm"): | 
|  | in_kernel_headers = True | 
|  | archs = [ "arm" ] | 
|  |  | 
|  | # if the user has specified some architectures with -a <archs> ensure that | 
|  | # all those he wants are available from the kernel include tree | 
|  | if wanted_archs != None: | 
|  | if in_kernel_headers and wanted_archs != [ "arm" ]: | 
|  | sys.stderr.write( "error: when parsing kernel_headers, 'arm' architecture only is supported at the moment\n" ) | 
|  | sys.exit(1) | 
|  | missing = [] | 
|  | for arch in wanted_archs: | 
|  | if arch not in archs: | 
|  | missing.append(arch) | 
|  | if len(missing) > 0: | 
|  | sys.stderr.write( "error: the following requested architectures are not in the kernel tree: " ) | 
|  | for a in missing: | 
|  | sys.stderr.write( " %s" % a ) | 
|  | sys.stderr.write( "\n" ) | 
|  | sys.exit(1) | 
|  |  | 
|  | archs = wanted_archs | 
|  |  | 
|  | # helper function used to walk the user files | 
|  | def parse_file(path, parser): | 
|  | #print "parse %s" % path | 
|  | parser.parseFile(path) | 
|  |  | 
|  |  | 
|  | # remove previous destination directory | 
|  | #destdir = "/tmp/bionic-kernel-headers/" | 
|  | #cleanup_dir(destdir) | 
|  |  | 
|  | # try to read the config file | 
|  | try: | 
|  | cparser = kernel.ConfigParser() | 
|  | if wanted_config: | 
|  | cparser.parseFile( wanted_config ) | 
|  | except: | 
|  | sys.stderr.write( "error: can't parse '%s'" % wanted_config ) | 
|  | sys.exit(1) | 
|  |  | 
|  | kernel_config = cparser.getDefinitions() | 
|  |  | 
|  | # first, obtain the list of kernel files used by our clients | 
|  | fparser = kernel.HeaderScanner() | 
|  | dir_excludes=[".repo","external/kernel-headers","ndk","out","prebuilt","bionic/libc/kernel","development/ndk","external/qemu/distrib"] | 
|  | walk_source_files( args[1:], parse_file, fparser, excludes=["./"+f for f in dir_excludes] ) | 
|  | headers = fparser.getHeaders() | 
|  | files   = fparser.getFiles() | 
|  |  | 
|  | # now recursively scan the kernel headers for additionnal sub-included headers | 
|  | hparser = kernel.KernelHeaderFinder(headers,archs,kernel_root,kernel_config) | 
|  | headers = hparser.scanForAllArchs() | 
|  |  | 
|  | if 0:    # just for debugging | 
|  | dumpHeaderUsers = False | 
|  |  | 
|  | print "the following %d headers:" % len(headers) | 
|  | for h in sorted(headers): | 
|  | if dumpHeaderUsers: | 
|  | print "  %s (%s)" % (h, repr(hparser.getHeaderUsers(h))) | 
|  | else: | 
|  | print "  %s" % h | 
|  |  | 
|  | print "are used by the following %d files:" % len(files) | 
|  | for f in sorted(files): | 
|  | print "  %s" % f | 
|  |  | 
|  | sys.exit(0) | 
|  |  | 
|  | for h in sorted(headers): | 
|  | print "%s" % h | 
|  |  | 
|  | sys.exit(0) |