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