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
      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