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