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