• 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"""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