• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3# Copyright 2015 The Chromium Authors. All rights reserved.
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6"""Runs a linking command and optionally a strip command.
7
8This script exists to avoid using complex shell commands in
9gcc_toolchain.gni's tool("link"), in case the host running the compiler
10does not have a POSIX-like shell (e.g. Windows).
11"""
12
13import argparse
14import os
15import subprocess
16import sys
17
18import wrapper_utils
19
20# When running on a Windows host and using a toolchain whose tools are
21# actually wrapper scripts (i.e. .bat files on Windows) rather than binary
22# executables, the "command" to run has to be prefixed with this magic.
23# The GN toolchain definitions take care of that for when GN/Ninja is
24# running the tool directly.  When that command is passed in to this
25# script, it appears as a unitary string but needs to be split up so that
26# just 'cmd' is the actual command given to Python's subprocess module.
27BAT_PREFIX = 'cmd /c call '
28
29
30def command_to_run(command):
31    if command[0].startswith(BAT_PREFIX):
32        command = command[0].split(None, 3) + command[1:]
33    return command
34
35
36def is_static_link(command):
37    if "-static" in command:
38        return True
39    else:
40        return False
41
42
43""" since static link and dynamic link have different CRT files on ohos,
44and we use dynamic link CRT files as default, so when link statically,
45we need change the CRT files
46"""
47
48
49def update_crt(command):
50    for item in command:
51        if str(item).find("crtbegin_dynamic.o") >= 0:
52            index = command.index(item)
53            new_crtbegin = str(item).replace("crtbegin_dynamic.o",
54                                             "crtbegin_static.o")
55            command[index] = new_crtbegin
56    return command
57
58
59def main():
60    parser = argparse.ArgumentParser(description=__doc__)
61    parser.add_argument('--strip',
62                        help='The strip binary to run',
63                        metavar='PATH')
64    parser.add_argument('--unstripped-file',
65                        help='Executable file produced by linking command',
66                        metavar='FILE')
67    parser.add_argument('--map-file',
68                        help=('Use --Wl,-Map to generate a map file. Will be '
69                              'gzipped if extension ends with .gz'),
70                        metavar='FILE')
71    parser.add_argument('--output',
72                        required=True,
73                        help='Final output executable file',
74                        metavar='FILE')
75    parser.add_argument('--clang_rt_dso_path',
76                        help=('Clang asan runtime shared library'))
77    parser.add_argument('command', nargs='+', help='Linking command')
78    parser.add_argument('--mini-debug',
79                        action='store_true',
80                        default=False,
81                        help='Add .gnu_debugdata section for stripped sofile')
82    args = parser.parse_args()
83
84    # Work-around for gold being slow-by-default. http://crbug.com/632230
85    fast_env = dict(os.environ)
86    fast_env['LC_ALL'] = 'C'
87    if is_static_link(args.command):
88        command = update_crt(args.command)
89        if args.clang_rt_dso_path is not None:
90            return 0
91    else:
92        command = args.command
93    result = wrapper_utils.run_link_with_optional_map_file(
94        command, env=fast_env, map_file=args.map_file)
95    if result != 0:
96        return result
97
98    # Finally, strip the linked executable (if desired).
99    if args.strip:
100        result = subprocess.call(
101            command_to_run(
102                [args.strip, '-o', args.output, args.unstripped_file]))
103
104    if args.mini_debug and not args.unstripped_file.endswith(".exe"):
105        unstripped_libfile = os.path.abspath(args.unstripped_file)
106        script_path = os.path.join(
107            os.path.dirname(__file__), 'mini_debug_info.py')
108        ohos_root_path = os.path.join(os.path.dirname(__file__), '../..')
109        result = subprocess.call(
110            wrapper_utils.command_to_run(
111                ['python3', script_path, '--unstripped-path', unstripped_libfile, '--stripped-path', args.output,
112                '--root-path', ohos_root_path]))
113
114    return result
115
116
117if __name__ == "__main__":
118    sys.exit(main())
119