1*8975f5c5SAndroid Build Coastguard Worker#!/usr/bin/env python3 2*8975f5c5SAndroid Build Coastguard Worker 3*8975f5c5SAndroid Build Coastguard Worker# Copyright 2016 The Chromium Authors 4*8975f5c5SAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be 5*8975f5c5SAndroid Build Coastguard Worker# found in the LICENSE file. 6*8975f5c5SAndroid Build Coastguard Worker 7*8975f5c5SAndroid Build Coastguard Workerimport os 8*8975f5c5SAndroid Build Coastguard Workerimport os.path 9*8975f5c5SAndroid Build Coastguard Workerimport re 10*8975f5c5SAndroid Build Coastguard Workerimport shutil 11*8975f5c5SAndroid Build Coastguard Workerimport subprocess 12*8975f5c5SAndroid Build Coastguard Workerimport sys 13*8975f5c5SAndroid Build Coastguard Workerimport tempfile 14*8975f5c5SAndroid Build Coastguard Worker 15*8975f5c5SAndroid Build Coastguard Worker# The path to `whole_archive`. 16*8975f5c5SAndroid Build Coastguard Workersys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..')) 17*8975f5c5SAndroid Build Coastguard Worker 18*8975f5c5SAndroid Build Coastguard Workerimport whole_archive 19*8975f5c5SAndroid Build Coastguard Worker 20*8975f5c5SAndroid Build Coastguard Worker# Prefix for all custom linker driver arguments. 21*8975f5c5SAndroid Build Coastguard WorkerLINKER_DRIVER_ARG_PREFIX = '-Wcrl,' 22*8975f5c5SAndroid Build Coastguard WorkerLINKER_DRIVER_COMPILER_ARG_PREFIX = '-Wcrl,driver,' 23*8975f5c5SAndroid Build Coastguard Worker# Linker action to create a directory and pass it to the linker as 24*8975f5c5SAndroid Build Coastguard Worker# `-object_path_lto`. Special-cased since it has to run before the link. 25*8975f5c5SAndroid Build Coastguard WorkerOBJECT_PATH_LTO = 'object_path_lto' 26*8975f5c5SAndroid Build Coastguard Worker 27*8975f5c5SAndroid Build Coastguard Worker# The linker_driver.py is responsible for forwarding a linker invocation to 28*8975f5c5SAndroid Build Coastguard Worker# the compiler driver, while processing special arguments itself. 29*8975f5c5SAndroid Build Coastguard Worker# 30*8975f5c5SAndroid Build Coastguard Worker# Usage: linker_driver.py -Wcrl,driver,clang++ main.o -L. -llib -o prog \ 31*8975f5c5SAndroid Build Coastguard Worker# -Wcrl,dsym,out 32*8975f5c5SAndroid Build Coastguard Worker# 33*8975f5c5SAndroid Build Coastguard Worker# On Mac, the logical step of linking is handled by three discrete tools to 34*8975f5c5SAndroid Build Coastguard Worker# perform the image link, debug info link, and strip. The linker_driver.py 35*8975f5c5SAndroid Build Coastguard Worker# combines these three steps into a single tool. 36*8975f5c5SAndroid Build Coastguard Worker# 37*8975f5c5SAndroid Build Coastguard Worker# The compiler driver invocation for the linker is specified by the following 38*8975f5c5SAndroid Build Coastguard Worker# required argument. 39*8975f5c5SAndroid Build Coastguard Worker# 40*8975f5c5SAndroid Build Coastguard Worker# -Wcrl,driver,<path_to_compiler_driver> 41*8975f5c5SAndroid Build Coastguard Worker# Specifies the path to the compiler driver. 42*8975f5c5SAndroid Build Coastguard Worker# 43*8975f5c5SAndroid Build Coastguard Worker# After running the compiler driver, the script performs additional actions, 44*8975f5c5SAndroid Build Coastguard Worker# based on these arguments: 45*8975f5c5SAndroid Build Coastguard Worker# 46*8975f5c5SAndroid Build Coastguard Worker# -Wcrl,installnametoolpath,<install_name_tool_path> 47*8975f5c5SAndroid Build Coastguard Worker# Sets the path to the `install_name_tool` to run with 48*8975f5c5SAndroid Build Coastguard Worker# -Wcrl,installnametool, in which case `xcrun` is not used to invoke it. 49*8975f5c5SAndroid Build Coastguard Worker# 50*8975f5c5SAndroid Build Coastguard Worker# -Wcrl,installnametool,<arguments,...> 51*8975f5c5SAndroid Build Coastguard Worker# After invoking the linker, this will run install_name_tool on the linker's 52*8975f5c5SAndroid Build Coastguard Worker# output. |arguments| are comma-separated arguments to be passed to the 53*8975f5c5SAndroid Build Coastguard Worker# install_name_tool command. 54*8975f5c5SAndroid Build Coastguard Worker# 55*8975f5c5SAndroid Build Coastguard Worker# -Wcrl,dsym,<dsym_path_prefix> 56*8975f5c5SAndroid Build Coastguard Worker# After invoking the linker, this will run `dsymutil` on the linker's 57*8975f5c5SAndroid Build Coastguard Worker# output, producing a dSYM bundle, stored at dsym_path_prefix. As an 58*8975f5c5SAndroid Build Coastguard Worker# example, if the linker driver were invoked with: 59*8975f5c5SAndroid Build Coastguard Worker# "... -o out/gn/obj/foo/libbar.dylib ... -Wcrl,dsym,out/gn ..." 60*8975f5c5SAndroid Build Coastguard Worker# The resulting dSYM would be out/gn/libbar.dylib.dSYM/. 61*8975f5c5SAndroid Build Coastguard Worker# 62*8975f5c5SAndroid Build Coastguard Worker# -Wcrl,dsymutilpath,<dsymutil_path> 63*8975f5c5SAndroid Build Coastguard Worker# Sets the path to the dsymutil to run with -Wcrl,dsym, in which case 64*8975f5c5SAndroid Build Coastguard Worker# `xcrun` is not used to invoke it. 65*8975f5c5SAndroid Build Coastguard Worker# 66*8975f5c5SAndroid Build Coastguard Worker# -Wcrl,unstripped,<unstripped_path_prefix> 67*8975f5c5SAndroid Build Coastguard Worker# After invoking the linker, and before strip, this will save a copy of 68*8975f5c5SAndroid Build Coastguard Worker# the unstripped linker output in the directory unstripped_path_prefix. 69*8975f5c5SAndroid Build Coastguard Worker# 70*8975f5c5SAndroid Build Coastguard Worker# -Wcrl,strip,<strip_arguments> 71*8975f5c5SAndroid Build Coastguard Worker# After invoking the linker, and optionally dsymutil, this will run 72*8975f5c5SAndroid Build Coastguard Worker# the strip command on the linker's output. strip_arguments are 73*8975f5c5SAndroid Build Coastguard Worker# comma-separated arguments to be passed to the strip command. 74*8975f5c5SAndroid Build Coastguard Worker# 75*8975f5c5SAndroid Build Coastguard Worker# -Wcrl,strippath,<strip_path> 76*8975f5c5SAndroid Build Coastguard Worker# Sets the path to the strip to run with -Wcrl,strip, in which case 77*8975f5c5SAndroid Build Coastguard Worker# `xcrun` is not used to invoke it. 78*8975f5c5SAndroid Build Coastguard Worker# -Wcrl,object_path_lto 79*8975f5c5SAndroid Build Coastguard Worker# Creates temporary directory for LTO object files. 80*8975f5c5SAndroid Build Coastguard Worker 81*8975f5c5SAndroid Build Coastguard Worker 82*8975f5c5SAndroid Build Coastguard Workerclass LinkerDriver(object): 83*8975f5c5SAndroid Build Coastguard Worker def __init__(self, args): 84*8975f5c5SAndroid Build Coastguard Worker """Creates a new linker driver. 85*8975f5c5SAndroid Build Coastguard Worker 86*8975f5c5SAndroid Build Coastguard Worker Args: 87*8975f5c5SAndroid Build Coastguard Worker args: list of string, Arguments to the script. 88*8975f5c5SAndroid Build Coastguard Worker """ 89*8975f5c5SAndroid Build Coastguard Worker self._args = args 90*8975f5c5SAndroid Build Coastguard Worker 91*8975f5c5SAndroid Build Coastguard Worker # List of linker driver actions. **The sort order of this list affects 92*8975f5c5SAndroid Build Coastguard Worker # the order in which the actions are invoked.** 93*8975f5c5SAndroid Build Coastguard Worker # The first item in the tuple is the argument's -Wcrl,<sub_argument> 94*8975f5c5SAndroid Build Coastguard Worker # and the second is the function to invoke. 95*8975f5c5SAndroid Build Coastguard Worker self._actions = [ 96*8975f5c5SAndroid Build Coastguard Worker ('installnametoolpath,', self.set_install_name_tool_path), 97*8975f5c5SAndroid Build Coastguard Worker ('installnametool,', self.run_install_name_tool), 98*8975f5c5SAndroid Build Coastguard Worker ('dsymutilpath,', self.set_dsymutil_path), 99*8975f5c5SAndroid Build Coastguard Worker ('dsym,', self.run_dsymutil), 100*8975f5c5SAndroid Build Coastguard Worker ('unstripped,', self.run_save_unstripped), 101*8975f5c5SAndroid Build Coastguard Worker ('strippath,', self.set_strip_path), 102*8975f5c5SAndroid Build Coastguard Worker ('strip,', self.run_strip), 103*8975f5c5SAndroid Build Coastguard Worker ] 104*8975f5c5SAndroid Build Coastguard Worker 105*8975f5c5SAndroid Build Coastguard Worker # Linker driver actions can modify the these values. 106*8975f5c5SAndroid Build Coastguard Worker self._driver_path = None # Must be specified on the command line. 107*8975f5c5SAndroid Build Coastguard Worker self._install_name_tool_cmd = ['xcrun', 'install_name_tool'] 108*8975f5c5SAndroid Build Coastguard Worker self._dsymutil_cmd = ['xcrun', 'dsymutil'] 109*8975f5c5SAndroid Build Coastguard Worker self._strip_cmd = ['xcrun', 'strip'] 110*8975f5c5SAndroid Build Coastguard Worker 111*8975f5c5SAndroid Build Coastguard Worker # The linker output file, lazily computed in self._get_linker_output(). 112*8975f5c5SAndroid Build Coastguard Worker self._linker_output = None 113*8975f5c5SAndroid Build Coastguard Worker # The temporary directory for intermediate LTO object files. If it 114*8975f5c5SAndroid Build Coastguard Worker # exists, it will clean itself up on script exit. 115*8975f5c5SAndroid Build Coastguard Worker self._object_path_lto = None 116*8975f5c5SAndroid Build Coastguard Worker 117*8975f5c5SAndroid Build Coastguard Worker def run(self): 118*8975f5c5SAndroid Build Coastguard Worker """Runs the linker driver, separating out the main compiler driver's 119*8975f5c5SAndroid Build Coastguard Worker arguments from the ones handled by this class. It then invokes the 120*8975f5c5SAndroid Build Coastguard Worker required tools, starting with the compiler driver to produce the linker 121*8975f5c5SAndroid Build Coastguard Worker output. 122*8975f5c5SAndroid Build Coastguard Worker """ 123*8975f5c5SAndroid Build Coastguard Worker # Collect arguments to the linker driver (this script) and remove them 124*8975f5c5SAndroid Build Coastguard Worker # from the arguments being passed to the compiler driver. 125*8975f5c5SAndroid Build Coastguard Worker linker_driver_actions = {} 126*8975f5c5SAndroid Build Coastguard Worker compiler_driver_args = [] 127*8975f5c5SAndroid Build Coastguard Worker for index, arg in enumerate(self._args[1:]): 128*8975f5c5SAndroid Build Coastguard Worker if arg.startswith(LINKER_DRIVER_COMPILER_ARG_PREFIX): 129*8975f5c5SAndroid Build Coastguard Worker assert not self._driver_path 130*8975f5c5SAndroid Build Coastguard Worker self._driver_path = arg[len(LINKER_DRIVER_COMPILER_ARG_PREFIX 131*8975f5c5SAndroid Build Coastguard Worker ):] 132*8975f5c5SAndroid Build Coastguard Worker elif arg.startswith(LINKER_DRIVER_ARG_PREFIX): 133*8975f5c5SAndroid Build Coastguard Worker # Convert driver actions into a map of name => lambda to invoke. 134*8975f5c5SAndroid Build Coastguard Worker driver_action = self._process_driver_arg(arg) 135*8975f5c5SAndroid Build Coastguard Worker assert driver_action[0] not in linker_driver_actions 136*8975f5c5SAndroid Build Coastguard Worker linker_driver_actions[driver_action[0]] = driver_action[1] 137*8975f5c5SAndroid Build Coastguard Worker else: 138*8975f5c5SAndroid Build Coastguard Worker # TODO(crbug.com/40268754): On Apple, the linker command line 139*8975f5c5SAndroid Build Coastguard Worker # produced by rustc for LTO includes these arguments, but the 140*8975f5c5SAndroid Build Coastguard Worker # Apple linker doesn't accept them. 141*8975f5c5SAndroid Build Coastguard Worker # Upstream bug: https://github.com/rust-lang/rust/issues/60059 142*8975f5c5SAndroid Build Coastguard Worker BAD_RUSTC_ARGS = '-Wl,-plugin-opt=O[0-9],-plugin-opt=mcpu=.*' 143*8975f5c5SAndroid Build Coastguard Worker if not re.match(BAD_RUSTC_ARGS, arg): 144*8975f5c5SAndroid Build Coastguard Worker compiler_driver_args.append(arg) 145*8975f5c5SAndroid Build Coastguard Worker 146*8975f5c5SAndroid Build Coastguard Worker if not self._driver_path: 147*8975f5c5SAndroid Build Coastguard Worker raise RuntimeError( 148*8975f5c5SAndroid Build Coastguard Worker "Usage: linker_driver.py -Wcrl,driver,<compiler-driver> " 149*8975f5c5SAndroid Build Coastguard Worker "[linker-args]...") 150*8975f5c5SAndroid Build Coastguard Worker 151*8975f5c5SAndroid Build Coastguard Worker if self._object_path_lto is not None: 152*8975f5c5SAndroid Build Coastguard Worker compiler_driver_args.append('-Wl,-object_path_lto,{}'.format( 153*8975f5c5SAndroid Build Coastguard Worker os.path.relpath(self._object_path_lto.name))) 154*8975f5c5SAndroid Build Coastguard Worker if self._get_linker_output() is None: 155*8975f5c5SAndroid Build Coastguard Worker raise ValueError( 156*8975f5c5SAndroid Build Coastguard Worker 'Could not find path to linker output (-o or --output)') 157*8975f5c5SAndroid Build Coastguard Worker 158*8975f5c5SAndroid Build Coastguard Worker # We want to link rlibs as --whole-archive if they are part of a unit 159*8975f5c5SAndroid Build Coastguard Worker # test target. This is determined by switch 160*8975f5c5SAndroid Build Coastguard Worker # `-LinkWrapper,add-whole-archive`. 161*8975f5c5SAndroid Build Coastguard Worker compiler_driver_args = whole_archive.wrap_with_whole_archive( 162*8975f5c5SAndroid Build Coastguard Worker compiler_driver_args, is_apple=True) 163*8975f5c5SAndroid Build Coastguard Worker 164*8975f5c5SAndroid Build Coastguard Worker linker_driver_outputs = [self._get_linker_output()] 165*8975f5c5SAndroid Build Coastguard Worker 166*8975f5c5SAndroid Build Coastguard Worker try: 167*8975f5c5SAndroid Build Coastguard Worker # Zero the mtime in OSO fields for deterministic builds. 168*8975f5c5SAndroid Build Coastguard Worker # https://crbug.com/330262. 169*8975f5c5SAndroid Build Coastguard Worker env = os.environ.copy() 170*8975f5c5SAndroid Build Coastguard Worker env['ZERO_AR_DATE'] = '1' 171*8975f5c5SAndroid Build Coastguard Worker # Run the linker by invoking the compiler driver. 172*8975f5c5SAndroid Build Coastguard Worker subprocess.check_call([self._driver_path] + compiler_driver_args, 173*8975f5c5SAndroid Build Coastguard Worker env=env) 174*8975f5c5SAndroid Build Coastguard Worker 175*8975f5c5SAndroid Build Coastguard Worker # Run the linker driver actions, in the order specified by the 176*8975f5c5SAndroid Build Coastguard Worker # actions list. 177*8975f5c5SAndroid Build Coastguard Worker for action in self._actions: 178*8975f5c5SAndroid Build Coastguard Worker name = action[0] 179*8975f5c5SAndroid Build Coastguard Worker if name in linker_driver_actions: 180*8975f5c5SAndroid Build Coastguard Worker linker_driver_outputs += linker_driver_actions[name]() 181*8975f5c5SAndroid Build Coastguard Worker except: 182*8975f5c5SAndroid Build Coastguard Worker # If a linker driver action failed, remove all the outputs to make 183*8975f5c5SAndroid Build Coastguard Worker # the build step atomic. 184*8975f5c5SAndroid Build Coastguard Worker map(_remove_path, linker_driver_outputs) 185*8975f5c5SAndroid Build Coastguard Worker 186*8975f5c5SAndroid Build Coastguard Worker # Re-report the original failure. 187*8975f5c5SAndroid Build Coastguard Worker raise 188*8975f5c5SAndroid Build Coastguard Worker 189*8975f5c5SAndroid Build Coastguard Worker def _get_linker_output(self): 190*8975f5c5SAndroid Build Coastguard Worker """Returns the value of the output argument to the linker.""" 191*8975f5c5SAndroid Build Coastguard Worker if not self._linker_output: 192*8975f5c5SAndroid Build Coastguard Worker for index, arg in enumerate(self._args): 193*8975f5c5SAndroid Build Coastguard Worker if arg in ('-o', '-output', '--output'): 194*8975f5c5SAndroid Build Coastguard Worker self._linker_output = self._args[index + 1] 195*8975f5c5SAndroid Build Coastguard Worker break 196*8975f5c5SAndroid Build Coastguard Worker return self._linker_output 197*8975f5c5SAndroid Build Coastguard Worker 198*8975f5c5SAndroid Build Coastguard Worker def _process_driver_arg(self, arg): 199*8975f5c5SAndroid Build Coastguard Worker """Processes a linker driver argument and returns a tuple containing the 200*8975f5c5SAndroid Build Coastguard Worker name and unary lambda to invoke for that linker driver action. 201*8975f5c5SAndroid Build Coastguard Worker 202*8975f5c5SAndroid Build Coastguard Worker Args: 203*8975f5c5SAndroid Build Coastguard Worker arg: string, The linker driver argument. 204*8975f5c5SAndroid Build Coastguard Worker 205*8975f5c5SAndroid Build Coastguard Worker Returns: 206*8975f5c5SAndroid Build Coastguard Worker A 2-tuple: 207*8975f5c5SAndroid Build Coastguard Worker 0: The driver action name, as in |self._actions|. 208*8975f5c5SAndroid Build Coastguard Worker 1: A lambda that calls the linker driver action with its direct 209*8975f5c5SAndroid Build Coastguard Worker argument and returns a list of outputs from the action. 210*8975f5c5SAndroid Build Coastguard Worker """ 211*8975f5c5SAndroid Build Coastguard Worker if not arg.startswith(LINKER_DRIVER_ARG_PREFIX): 212*8975f5c5SAndroid Build Coastguard Worker raise ValueError('%s is not a linker driver argument' % (arg, )) 213*8975f5c5SAndroid Build Coastguard Worker 214*8975f5c5SAndroid Build Coastguard Worker sub_arg = arg[len(LINKER_DRIVER_ARG_PREFIX):] 215*8975f5c5SAndroid Build Coastguard Worker # Special-cased, since it needs to run before the link. 216*8975f5c5SAndroid Build Coastguard Worker # TODO(lgrey): Remove if/when we start running `dsymutil` 217*8975f5c5SAndroid Build Coastguard Worker # through the clang driver. See https://crbug.com/1324104 218*8975f5c5SAndroid Build Coastguard Worker if sub_arg == OBJECT_PATH_LTO: 219*8975f5c5SAndroid Build Coastguard Worker self._object_path_lto = tempfile.TemporaryDirectory( 220*8975f5c5SAndroid Build Coastguard Worker dir=os.getcwd()) 221*8975f5c5SAndroid Build Coastguard Worker return (OBJECT_PATH_LTO, lambda: []) 222*8975f5c5SAndroid Build Coastguard Worker 223*8975f5c5SAndroid Build Coastguard Worker for driver_action in self._actions: 224*8975f5c5SAndroid Build Coastguard Worker (name, action) = driver_action 225*8975f5c5SAndroid Build Coastguard Worker if sub_arg.startswith(name): 226*8975f5c5SAndroid Build Coastguard Worker return (name, lambda: action(sub_arg[len(name):])) 227*8975f5c5SAndroid Build Coastguard Worker 228*8975f5c5SAndroid Build Coastguard Worker raise ValueError('Unknown linker driver argument: %s' % (arg, )) 229*8975f5c5SAndroid Build Coastguard Worker 230*8975f5c5SAndroid Build Coastguard Worker def set_install_name_tool_path(self, install_name_tool_path): 231*8975f5c5SAndroid Build Coastguard Worker """Linker driver action for -Wcrl,installnametoolpath,<path>. 232*8975f5c5SAndroid Build Coastguard Worker 233*8975f5c5SAndroid Build Coastguard Worker Sets the invocation command for install_name_tool, which allows the 234*8975f5c5SAndroid Build Coastguard Worker caller to specify an alternate path. This action is always 235*8975f5c5SAndroid Build Coastguard Worker processed before the run_install_name_tool action. 236*8975f5c5SAndroid Build Coastguard Worker 237*8975f5c5SAndroid Build Coastguard Worker Args: 238*8975f5c5SAndroid Build Coastguard Worker install_name_tool_path: string, The path to the install_name_tool 239*8975f5c5SAndroid Build Coastguard Worker binary to run 240*8975f5c5SAndroid Build Coastguard Worker 241*8975f5c5SAndroid Build Coastguard Worker Returns: 242*8975f5c5SAndroid Build Coastguard Worker No output - this step is run purely for its side-effect. 243*8975f5c5SAndroid Build Coastguard Worker """ 244*8975f5c5SAndroid Build Coastguard Worker self._install_name_tool_cmd = [install_name_tool_path] 245*8975f5c5SAndroid Build Coastguard Worker return [] 246*8975f5c5SAndroid Build Coastguard Worker 247*8975f5c5SAndroid Build Coastguard Worker def run_install_name_tool(self, args_string): 248*8975f5c5SAndroid Build Coastguard Worker """Linker driver action for -Wcrl,installnametool,<args>. Invokes 249*8975f5c5SAndroid Build Coastguard Worker install_name_tool on the linker's output. 250*8975f5c5SAndroid Build Coastguard Worker 251*8975f5c5SAndroid Build Coastguard Worker Args: 252*8975f5c5SAndroid Build Coastguard Worker args_string: string, Comma-separated arguments for 253*8975f5c5SAndroid Build Coastguard Worker `install_name_tool`. 254*8975f5c5SAndroid Build Coastguard Worker 255*8975f5c5SAndroid Build Coastguard Worker Returns: 256*8975f5c5SAndroid Build Coastguard Worker No output - this step is run purely for its side-effect. 257*8975f5c5SAndroid Build Coastguard Worker """ 258*8975f5c5SAndroid Build Coastguard Worker command = list(self._install_name_tool_cmd) 259*8975f5c5SAndroid Build Coastguard Worker command.extend(args_string.split(',')) 260*8975f5c5SAndroid Build Coastguard Worker command.append(self._get_linker_output()) 261*8975f5c5SAndroid Build Coastguard Worker subprocess.check_call(command) 262*8975f5c5SAndroid Build Coastguard Worker return [] 263*8975f5c5SAndroid Build Coastguard Worker 264*8975f5c5SAndroid Build Coastguard Worker def run_dsymutil(self, dsym_path_prefix): 265*8975f5c5SAndroid Build Coastguard Worker """Linker driver action for -Wcrl,dsym,<dsym-path-prefix>. Invokes 266*8975f5c5SAndroid Build Coastguard Worker dsymutil on the linker's output and produces a dsym file at |dsym_file| 267*8975f5c5SAndroid Build Coastguard Worker path. 268*8975f5c5SAndroid Build Coastguard Worker 269*8975f5c5SAndroid Build Coastguard Worker Args: 270*8975f5c5SAndroid Build Coastguard Worker dsym_path_prefix: string, The path at which the dsymutil output 271*8975f5c5SAndroid Build Coastguard Worker should be located. 272*8975f5c5SAndroid Build Coastguard Worker 273*8975f5c5SAndroid Build Coastguard Worker Returns: 274*8975f5c5SAndroid Build Coastguard Worker list of string, Build step outputs. 275*8975f5c5SAndroid Build Coastguard Worker """ 276*8975f5c5SAndroid Build Coastguard Worker if not len(dsym_path_prefix): 277*8975f5c5SAndroid Build Coastguard Worker raise ValueError('Unspecified dSYM output file') 278*8975f5c5SAndroid Build Coastguard Worker 279*8975f5c5SAndroid Build Coastguard Worker linker_output = self._get_linker_output() 280*8975f5c5SAndroid Build Coastguard Worker base = os.path.basename(linker_output) 281*8975f5c5SAndroid Build Coastguard Worker dsym_out = os.path.join(dsym_path_prefix, base + '.dSYM') 282*8975f5c5SAndroid Build Coastguard Worker 283*8975f5c5SAndroid Build Coastguard Worker # Remove old dSYMs before invoking dsymutil. 284*8975f5c5SAndroid Build Coastguard Worker _remove_path(dsym_out) 285*8975f5c5SAndroid Build Coastguard Worker 286*8975f5c5SAndroid Build Coastguard Worker tools_paths = _find_tools_paths(self._args) 287*8975f5c5SAndroid Build Coastguard Worker if os.environ.get('PATH'): 288*8975f5c5SAndroid Build Coastguard Worker tools_paths.append(os.environ['PATH']) 289*8975f5c5SAndroid Build Coastguard Worker dsymutil_env = os.environ.copy() 290*8975f5c5SAndroid Build Coastguard Worker dsymutil_env['PATH'] = ':'.join(tools_paths) 291*8975f5c5SAndroid Build Coastguard Worker subprocess.check_call(self._dsymutil_cmd + 292*8975f5c5SAndroid Build Coastguard Worker ['-o', dsym_out, linker_output], 293*8975f5c5SAndroid Build Coastguard Worker env=dsymutil_env) 294*8975f5c5SAndroid Build Coastguard Worker return [dsym_out] 295*8975f5c5SAndroid Build Coastguard Worker 296*8975f5c5SAndroid Build Coastguard Worker def set_dsymutil_path(self, dsymutil_path): 297*8975f5c5SAndroid Build Coastguard Worker """Linker driver action for -Wcrl,dsymutilpath,<dsymutil_path>. 298*8975f5c5SAndroid Build Coastguard Worker 299*8975f5c5SAndroid Build Coastguard Worker Sets the invocation command for dsymutil, which allows the caller to 300*8975f5c5SAndroid Build Coastguard Worker specify an alternate dsymutil. This action is always processed before 301*8975f5c5SAndroid Build Coastguard Worker the RunDsymUtil action. 302*8975f5c5SAndroid Build Coastguard Worker 303*8975f5c5SAndroid Build Coastguard Worker Args: 304*8975f5c5SAndroid Build Coastguard Worker dsymutil_path: string, The path to the dsymutil binary to run 305*8975f5c5SAndroid Build Coastguard Worker 306*8975f5c5SAndroid Build Coastguard Worker Returns: 307*8975f5c5SAndroid Build Coastguard Worker No output - this step is run purely for its side-effect. 308*8975f5c5SAndroid Build Coastguard Worker """ 309*8975f5c5SAndroid Build Coastguard Worker self._dsymutil_cmd = [dsymutil_path] 310*8975f5c5SAndroid Build Coastguard Worker return [] 311*8975f5c5SAndroid Build Coastguard Worker 312*8975f5c5SAndroid Build Coastguard Worker def run_save_unstripped(self, unstripped_path_prefix): 313*8975f5c5SAndroid Build Coastguard Worker """Linker driver action for -Wcrl,unstripped,<unstripped_path_prefix>. 314*8975f5c5SAndroid Build Coastguard Worker Copies the linker output to |unstripped_path_prefix| before stripping. 315*8975f5c5SAndroid Build Coastguard Worker 316*8975f5c5SAndroid Build Coastguard Worker Args: 317*8975f5c5SAndroid Build Coastguard Worker unstripped_path_prefix: string, The path at which the unstripped 318*8975f5c5SAndroid Build Coastguard Worker output should be located. 319*8975f5c5SAndroid Build Coastguard Worker 320*8975f5c5SAndroid Build Coastguard Worker Returns: 321*8975f5c5SAndroid Build Coastguard Worker list of string, Build step outputs. 322*8975f5c5SAndroid Build Coastguard Worker """ 323*8975f5c5SAndroid Build Coastguard Worker if not len(unstripped_path_prefix): 324*8975f5c5SAndroid Build Coastguard Worker raise ValueError('Unspecified unstripped output file') 325*8975f5c5SAndroid Build Coastguard Worker 326*8975f5c5SAndroid Build Coastguard Worker base = os.path.basename(self._get_linker_output()) 327*8975f5c5SAndroid Build Coastguard Worker unstripped_out = os.path.join(unstripped_path_prefix, 328*8975f5c5SAndroid Build Coastguard Worker base + '.unstripped') 329*8975f5c5SAndroid Build Coastguard Worker 330*8975f5c5SAndroid Build Coastguard Worker shutil.copyfile(self._get_linker_output(), unstripped_out) 331*8975f5c5SAndroid Build Coastguard Worker return [unstripped_out] 332*8975f5c5SAndroid Build Coastguard Worker 333*8975f5c5SAndroid Build Coastguard Worker def run_strip(self, strip_args_string): 334*8975f5c5SAndroid Build Coastguard Worker """Linker driver action for -Wcrl,strip,<strip_arguments>. 335*8975f5c5SAndroid Build Coastguard Worker 336*8975f5c5SAndroid Build Coastguard Worker Args: 337*8975f5c5SAndroid Build Coastguard Worker strip_args_string: string, Comma-separated arguments for `strip`. 338*8975f5c5SAndroid Build Coastguard Worker 339*8975f5c5SAndroid Build Coastguard Worker Returns: 340*8975f5c5SAndroid Build Coastguard Worker list of string, Build step outputs. 341*8975f5c5SAndroid Build Coastguard Worker """ 342*8975f5c5SAndroid Build Coastguard Worker strip_command = list(self._strip_cmd) 343*8975f5c5SAndroid Build Coastguard Worker if len(strip_args_string) > 0: 344*8975f5c5SAndroid Build Coastguard Worker strip_command += strip_args_string.split(',') 345*8975f5c5SAndroid Build Coastguard Worker strip_command.append(self._get_linker_output()) 346*8975f5c5SAndroid Build Coastguard Worker subprocess.check_call(strip_command) 347*8975f5c5SAndroid Build Coastguard Worker return [] 348*8975f5c5SAndroid Build Coastguard Worker 349*8975f5c5SAndroid Build Coastguard Worker def set_strip_path(self, strip_path): 350*8975f5c5SAndroid Build Coastguard Worker """Linker driver action for -Wcrl,strippath,<strip_path>. 351*8975f5c5SAndroid Build Coastguard Worker 352*8975f5c5SAndroid Build Coastguard Worker Sets the invocation command for strip, which allows the caller to 353*8975f5c5SAndroid Build Coastguard Worker specify an alternate strip. This action is always processed before the 354*8975f5c5SAndroid Build Coastguard Worker RunStrip action. 355*8975f5c5SAndroid Build Coastguard Worker 356*8975f5c5SAndroid Build Coastguard Worker Args: 357*8975f5c5SAndroid Build Coastguard Worker strip_path: string, The path to the strip binary to run 358*8975f5c5SAndroid Build Coastguard Worker 359*8975f5c5SAndroid Build Coastguard Worker Returns: 360*8975f5c5SAndroid Build Coastguard Worker No output - this step is run purely for its side-effect. 361*8975f5c5SAndroid Build Coastguard Worker """ 362*8975f5c5SAndroid Build Coastguard Worker self._strip_cmd = [strip_path] 363*8975f5c5SAndroid Build Coastguard Worker return [] 364*8975f5c5SAndroid Build Coastguard Worker 365*8975f5c5SAndroid Build Coastguard Worker 366*8975f5c5SAndroid Build Coastguard Workerdef _find_tools_paths(full_args): 367*8975f5c5SAndroid Build Coastguard Worker """Finds all paths where the script should look for additional tools.""" 368*8975f5c5SAndroid Build Coastguard Worker paths = [] 369*8975f5c5SAndroid Build Coastguard Worker for idx, arg in enumerate(full_args): 370*8975f5c5SAndroid Build Coastguard Worker if arg in ['-B', '--prefix']: 371*8975f5c5SAndroid Build Coastguard Worker paths.append(full_args[idx + 1]) 372*8975f5c5SAndroid Build Coastguard Worker elif arg.startswith('-B'): 373*8975f5c5SAndroid Build Coastguard Worker paths.append(arg[2:]) 374*8975f5c5SAndroid Build Coastguard Worker elif arg.startswith('--prefix='): 375*8975f5c5SAndroid Build Coastguard Worker paths.append(arg[9:]) 376*8975f5c5SAndroid Build Coastguard Worker return paths 377*8975f5c5SAndroid Build Coastguard Worker 378*8975f5c5SAndroid Build Coastguard Worker 379*8975f5c5SAndroid Build Coastguard Workerdef _remove_path(path): 380*8975f5c5SAndroid Build Coastguard Worker """Removes the file or directory at |path| if it exists.""" 381*8975f5c5SAndroid Build Coastguard Worker if os.path.exists(path): 382*8975f5c5SAndroid Build Coastguard Worker if os.path.isdir(path): 383*8975f5c5SAndroid Build Coastguard Worker shutil.rmtree(path) 384*8975f5c5SAndroid Build Coastguard Worker else: 385*8975f5c5SAndroid Build Coastguard Worker os.unlink(path) 386*8975f5c5SAndroid Build Coastguard Worker 387*8975f5c5SAndroid Build Coastguard Worker 388*8975f5c5SAndroid Build Coastguard Workerif __name__ == '__main__': 389*8975f5c5SAndroid Build Coastguard Worker LinkerDriver(sys.argv).run() 390*8975f5c5SAndroid Build Coastguard Worker sys.exit(0) 391