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