1#!/usr/bin/env python2
2"""Prototype compiler wrapper.
3
4Only tested with: gcc, g++, clang, clang++
5Installation instructions:
6  1. Rename compiler from <compiler_name> to <compiler_name>.real
7  2. Create symlink from this script (compiler_wrapper.py), and name it
8     <compiler_name>. compiler_wrapper.py can live anywhere as long as it is
9     executable.
10
11Reference page:
12https://sites.google.com/a/google.com/chromeos-toolchain-team-home2/home/team-tools-and-scripts/bisecting-chromeos-compiler-problems/bisection-compiler-wrapper
13
14Design doc:
15https://docs.google.com/document/d/1yDgaUIa2O5w6dc3sSTe1ry-1ehKajTGJGQCbyn0fcEM
16"""
17
18from __future__ import print_function
19
20import os
21import shlex
22import sys
23
24import bisect_driver
25
26WRAPPED = '%s.real' % sys.argv[0]
27BISECT_STAGE = os.environ.get('BISECT_STAGE')
28DEFAULT_BISECT_DIR = os.path.expanduser('~/ANDROID_BISECT')
29BISECT_DIR = os.environ.get('BISECT_DIR') or DEFAULT_BISECT_DIR
30
31
32def ProcessArgFile(arg_file):
33  args = []
34  # Read in entire file at once and parse as if in shell
35  with open(arg_file, 'rb') as f:
36    args.extend(shlex.split(f.read()))
37
38  return args
39
40
41def Main(_):
42  if not os.path.islink(sys.argv[0]):
43    print("Compiler wrapper can't be called directly!")
44    return 1
45
46  execargs = [WRAPPED] + sys.argv[1:]
47
48  if BISECT_STAGE not in bisect_driver.VALID_MODES or '-o' not in execargs:
49    os.execv(WRAPPED, [WRAPPED] + sys.argv[1:])
50
51  # Handle @file argument syntax with compiler
52  for idx, _ in enumerate(execargs):
53    # @file can be nested in other @file arguments, use While to re-evaluate
54    # the first argument of the embedded file.
55    while execargs[idx][0] == '@':
56      args_in_file = ProcessArgFile(execargs[idx][1:])
57      execargs = execargs[0:idx] + args_in_file + execargs[idx + 1:]
58
59  bisect_driver.bisect_driver(BISECT_STAGE, BISECT_DIR, execargs)
60
61
62if __name__ == '__main__':
63  sys.exit(Main(sys.argv[1:]))
64