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"""Runs 'ld -shared' and generates a .TOC file that's untouched when unchanged. 16 17This script exists to avoid using complex shell commands in 18gcc_toolchain.gni's tool("solink"), in case the host running the compiler 19does not have a POSIX-like shell (e.g. Windows). 20""" 21 22import argparse 23import os 24import subprocess 25import sys 26import shutil 27 28 29def reformat_rsp_file(rspfile): 30 """ Move all implibs from --whole-archive section""" 31 with open(rspfile, "r") as fi: 32 rspcontent = fi.read() 33 result = [] 34 implibs = [] 35 naflag = False 36 for arg in rspcontent.split(" "): 37 if naflag and arg.endswith(".lib"): 38 implibs.append(arg) 39 continue 40 result.append(arg) 41 if arg == "-Wl,--whole-archive": 42 naflag = True 43 continue 44 if arg == "-Wl,--no-whole-archive": 45 naflag = False 46 result.extend(implibs) 47 48 with open(rspfile, "w") as fo: 49 fo.write(" ".join(result)) 50 51 52def main(): 53 parser = argparse.ArgumentParser(description=__doc__) 54 parser.add_argument('--strip', 55 help='The strip binary to run', 56 metavar='PATH') 57 parser.add_argument('--sofile', 58 required=True, 59 help='Shared object file produced by linking command', 60 metavar='FILE') 61 parser.add_argument('--output', 62 required=True, 63 help='Final output shared object file', 64 metavar='FILE') 65 parser.add_argument('--libfile', required=False, metavar='FILE') 66 parser.add_argument('command', nargs='+', help='Linking command') 67 args = parser.parse_args() 68 69 if args.sofile.endswith(".dll"): 70 rspfile = None 71 for a in args.command: 72 if a[0] == "@": 73 rspfile = a[1:] 74 break 75 if rspfile: 76 reformat_rsp_file(rspfile) 77 # Work-around for gold being slow-by-default. http://crbug.com/632230 78 fast_env = dict(os.environ) 79 fast_env['LC_ALL'] = 'C' 80 81 # First, run the actual link. 82 result = subprocess.call(args.command, env=fast_env) 83 if result != 0: 84 return result 85 86 # Finally, strip the linked shared object file (if desired). 87 if args.strip: 88 result = subprocess.call([args.strip, '-o', args.output, args.sofile]) 89 if args.libfile: 90 libfile_name = os.path.basename(args.libfile) 91 sofile_output_dir = os.path.dirname(args.sofile) 92 unstripped_libfile = os.path.join(sofile_output_dir, libfile_name) 93 shutil.copy2(unstripped_libfile, args.libfile) 94 95 return result 96 97 98if __name__ == "__main__": 99 sys.exit(main()) 100