Home | History | Annotate | Download | only in bin
      1 #!/usr/bin/python
      2 
      3 import os
      4 import shlex
      5 import sys
      6 
      7 import bisect_driver
      8 
      9 BISECT_STAGE = os.environ.get('BISECT_STAGE')
     10 DEFAULT_BISECT_DIR = os.path.expanduser('~/ANDROID_BISECT')
     11 BISECT_DIR = os.environ.get('BISECT_DIR') or DEFAULT_BISECT_DIR
     12 
     13 
     14 def ProcessArgFile(arg_file):
     15   args = []
     16   # Read in entire file at once and parse as if in shell
     17   with open(arg_file, 'rb') as f:
     18     args.extend(shlex.split(f.read()))
     19   return args
     20 
     21 
     22 class CompilerWrapper():
     23   def __init__(self, argv):
     24     self.args = argv
     25     self.execargs = []
     26     self.real_compiler = None
     27     self.argv0 = None
     28     self.append_flags = []
     29     self.prepend_flags = []
     30     self.custom_flags = {
     31       '--gomacc-path': None
     32     }
     33 
     34   def set_real_compiler(self):
     35     """Find the real compiler with the absolute path."""
     36     compiler_path = os.path.dirname(os.path.abspath(__file__))
     37     if os.path.islink(__file__):
     38       compiler = os.path.basename(os.readlink(__file__))
     39     else:
     40       compiler = os.path.basename(os.path.abspath(__file__))
     41     self.real_compiler = os.path.join(
     42         compiler_path,
     43         compiler + '.real')
     44     self.argv0 = self.real_compiler
     45 
     46   def process_gomacc_command(self):
     47     """Return the gomacc command if '--gomacc-path' is set."""
     48     gomacc = self.custom_flags['--gomacc-path']
     49     if gomacc and os.path.isfile(gomacc):
     50       self.argv0 = gomacc
     51       self.execargs += [gomacc]
     52 
     53   def parse_custom_flags(self):
     54     i = 0
     55     args = []
     56     while i < len(self.args):
     57       if self.args[i] in self.custom_flags:
     58         if i >= len(self.args) - 1:
     59           sys.exit('The value of {} is not set.'.format(self.args[i]))
     60         self.custom_flags[self.args[i]] = self.args[i + 1]
     61         i = i + 2
     62       else:
     63         args.append(self.args[i])
     64         i = i + 1
     65     self.args = args
     66 
     67   def add_flags(self):
     68     self.args = self.prepend_flags + self.args + self.append_flags
     69 
     70   def prepare_compiler_args(self):
     71     self.set_real_compiler()
     72     self.parse_custom_flags()
     73     self.process_gomacc_command()
     74     self.add_flags()
     75     self.execargs += [self.real_compiler] + self.args
     76 
     77   def invoke_compiler(self):
     78     self.prepare_compiler_args()
     79     os.execv(self.argv0, self.execargs)
     80 
     81   def bisect(self):
     82     self.prepare_compiler_args()
     83     # Handle @file argument syntax with compiler
     84     for idx, _ in enumerate(self.execargs):
     85       # @file can be nested in other @file arguments, use While to re-evaluate
     86       # the first argument of the embedded file.
     87       while execargs[idx][0] == '@':
     88         args_in_file = ProcessArgFile(execargs[idx][1:])
     89         self.execargs = self.execargs[0:idx] + args_in_file + self.execargs[idx + 1:]
     90     bisect_driver.bisect_driver(BISECT_STAGE, BISECT_DIR, execargs)
     91 
     92 
     93 def main(argv):
     94   cw = CompilerWrapper(argv[1:])
     95   if BISECT_STAGE not in bisect_driver.VALID_MODES or '-o' not in argv:
     96     cw.invoke_compiler()
     97   else:
     98     cw.bisect()
     99 
    100 
    101 if __name__ == '__main__':
    102   main(sys.argv)
    103