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