1#!/usr/bin/env python3 2# Copyright 2015 The Chromium Authors 3# Use of this source code is governed by a BSD-style license that can be 4# found in the LICENSE file. 5 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 21# When running on a Windows host and using a toolchain whose tools are 22# actually wrapper scripts (i.e. .bat files on Windows) rather than binary 23# executables, the "command" to run has to be prefixed with this magic. 24# The GN toolchain definitions take care of that for when GN/Ninja is 25# running the tool directly. When that command is passed in to this 26# script, it appears as a unitary string but needs to be split up so that 27# just 'cmd' is the actual command given to Python's subprocess module. 28BAT_PREFIX = 'cmd /c call ' 29 30def CommandToRun(command): 31 if command[0].startswith(BAT_PREFIX): 32 command = command[0].split(None, 3) + command[1:] 33 return command 34 35 36def main(): 37 parser = argparse.ArgumentParser(description=__doc__) 38 parser.add_argument('--strip', 39 help='The strip binary to run', 40 metavar='PATH') 41 parser.add_argument('--unstripped-file', 42 help='Executable file produced by linking command', 43 metavar='FILE') 44 parser.add_argument('--map-file', 45 help=('Use --Wl,-Map to generate a map file. Will be ' 46 'gzipped if extension ends with .gz'), 47 metavar='FILE') 48 parser.add_argument('--dwp', help=('The dwp binary to run'), metavar='FILE') 49 parser.add_argument('--output', 50 required=True, 51 help='Final output executable file', 52 metavar='FILE') 53 parser.add_argument('command', nargs='+', 54 help='Linking command') 55 args = parser.parse_args() 56 57 # Work-around for gold being slow-by-default. http://crbug.com/632230 58 fast_env = dict(os.environ) 59 fast_env['LC_ALL'] = 'C' 60 result = wrapper_utils.RunLinkWithOptionalMapFile(args.command, env=fast_env, 61 map_file=args.map_file) 62 if result != 0: 63 return result 64 65 # If dwp is set, then package debug info for this exe. 66 dwp_proc = None 67 if args.dwp: 68 exe_file = args.output 69 if args.unstripped_file: 70 exe_file = args.unstripped_file 71 # Suppress warnings about duplicate CU entries (https://crbug.com/1264130) 72 dwp_proc = subprocess.Popen(wrapper_utils.CommandToRun( 73 [args.dwp, '-e', exe_file, '-o', exe_file + '.dwp']), 74 stderr=subprocess.DEVNULL) 75 76 # Finally, strip the linked executable (if desired). 77 if args.strip: 78 result = subprocess.call( 79 CommandToRun([args.strip, '-o', args.output, args.unstripped_file])) 80 81 if dwp_proc: 82 dwp_result = dwp_proc.wait() 83 if dwp_result != 0: 84 sys.stderr.write('dwp failed with error code {}\n'.format(dwp_result)) 85 return dwp_result 86 87 return result 88 89 90if __name__ == "__main__": 91 sys.exit(main()) 92