• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3# Copyright (c) 2022 Huawei Device Co., Ltd.
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8#     http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16"""
171. add {{ldflags}} and extend everyone in {{ldflags}} to -Clink-args=%s.
182. replace blank with newline in .rsp file because of rustc.
193. add {{rustenv}} and in order to avoid ninja can't incremental compiling,
20   delete them from .d files.
21"""
22
23import os
24import stat
25import sys
26import re
27import argparse
28import pathlib
29import subprocess
30
31import rust_strip
32sys.path.append(
33    os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
34from scripts.util import build_utils  # noqa: E402
35
36
37def exec_formatted_command(args):
38    remaining_args = args.args
39
40    ldflags_index = remaining_args.index("LDFLAGS")
41    rustenv_index = remaining_args.index("RUSTENV", ldflags_index)
42    rustc_args = remaining_args[:ldflags_index]
43    ldflags = remaining_args[ldflags_index + 1:rustenv_index]
44    rustenv = remaining_args[rustenv_index + 1:]
45    for arg in ldflags:
46        if "cfi.versionscript" not in arg:
47            rustc_args.append("-Clink-arg=%s" % arg)
48    rustc_args.insert(0, args.rustc)
49
50    if args.rsp:
51        flags = os.O_WRONLY
52        modes = stat.S_IWUSR | stat.S_IRUSR
53        with open(args.rsp) as rspfile:
54            rsp_content = [l.rstrip() for l in rspfile.read().split(' ') if l.rstrip()]
55        with open(args.rsp, 'w') as rspfile:
56            rspfile.write("\n".join(rsp_content))
57        rustc_args.append(f'@{args.rsp}')
58
59    env = os.environ.copy()
60    fixed_env_vars = []
61    for item in rustenv:
62        (key, value) = item.split("=", 1)
63        env[key] = value
64        fixed_env_vars.append(key)
65
66    ret = subprocess.run([args.clippy_driver, *rustc_args], env=env, check=False)
67    if ret.returncode != 0:
68        sys.exit(ret.returncode)
69
70    if args.depfile is not None:
71        env_dep_re = re.compile("# env-dep:(.*)=.*")
72        replacement_lines = []
73        dirty = False
74        with open(args.depfile, encoding="utf-8") as depfile:
75            for line in depfile:
76                matched = env_dep_re.match(line)
77                if matched and matched.group(1) in fixed_env_vars:
78                    dirty = True
79                else:
80                    replacement_lines.append(line)
81        if dirty:
82            with build_utils.atomic_output(args.depfile) as output:
83                output.write("\n".join(replacement_lines).encode("utf-8"))
84    return 0
85
86
87def main():
88    parser = argparse.ArgumentParser()
89    parser.add_argument('--clippy-driver',
90                        required=True,
91                        type=pathlib.Path)
92    parser.add_argument('--rustc',
93                        required=True,
94                        type=pathlib.Path)
95    parser.add_argument('--depfile',
96                        type=pathlib.Path)
97    parser.add_argument('--rsp',
98                        type=pathlib.Path)
99    parser.add_argument('--strip',
100                        help='The strip binary to run',
101                        metavar='PATH')
102    parser.add_argument('--unstripped-file',
103                        help='Executable file produced by linking command',
104                        metavar='FILE')
105    parser.add_argument('--output',
106                        help='Final output executable file',
107                        metavar='FILE')
108    parser.add_argument('--mini-debug',
109                        action='store_true',
110                        default=False,
111                        help='Add .gnu_debugdata section for stripped sofile')
112    parser.add_argument('--clang-base-dir', help='')
113
114    parser.add_argument('args', metavar='ARG', nargs='+')
115
116    args = parser.parse_args()
117
118    result = exec_formatted_command(args)
119    if result != 0:
120        return result
121    if args.strip:
122        result = rust_strip.do_strip(args.strip, args.output, args.unstripped_file, args.mini_debug,
123            args.clang_base_dir)
124    return result
125
126
127if __name__ == '__main__':
128    sys.exit(main())
129