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