Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(78)

Side by Side Diff: build/toolchain/mac/linker_driver.py

Issue 1999513002: [Mac/GN] Implement dSYM generation and stripping. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « build/toolchain/mac/BUILD.gn ('k') | chrome/BUILD.gn » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 #!/usr/bin/env python
2
3 # Copyright 2016 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
7 import os
8 import os.path
9 import shutil
10 import subprocess
11 import sys
12
13 # The linker_driver.py is responsible for forwarding a linker invocation to
14 # the compiler driver, while processing special arguments itself.
15 #
16 # On Mac, the logical step of linking is handled by three discrete tools to
17 # perform the image link, debug info link, and strip. The linker_driver.py
18 # combines these three steps into a single tool.
19 #
20 # The command passed to the linker_driver.py is first invoked unaltered (except
21 # for the removal of the special driver arguments, described below). Then the
22 # driver performs additional actions, based on these arguments:
Mark Mentovai 2016/05/20 19:41:11 Specify (perhaps by implication if you provide a s
Robert Sesek 2016/05/24 15:05:33 Done.
23 #
24 # -Wcrl,dsym,<dsym_path_prefix>
25 # After invoking the linker, this will run `dsymutil` on the linker's
26 # output, producing a dSYM bundle, stored at dsym_path_prefix. As an
27 # example, if the linker driver were invoked with:
28 # "... -o out/gn/obj/foo/libbar.dylib ... -Wcrl,dsym,out/gn/ ..."
Mark Mentovai 2016/05/20 19:41:11 If the trailing / isn’t necessary, don’t include i
Robert Sesek 2016/05/24 15:05:33 Done.
29 # The resulting dSYM would be out/gn/libbar.dylib.dSYM/.
30 #
31 # -Wcrl,strip,<strip_arguments>
32 # After invoking the linker, and optionally dsymutil, this will run
33 # the strip command on the linker's output. strip_arguments are
34 # comma-separated arguments to be passed to the strip command.
35
36 def Main(args):
37 """Main function for the linker driver. Separates out the arguments for
38 the main compiler driver and the linker driver, then invokes all the
39 required tools.
40
41 Args:
42 args: list of string, Arguments to the script.
43 """
44
45 if len(args) < 2:
46 raise RuntimeError("Usage: linker_driver.py [linker-invocation]")
47
48 # Collect arguments to the linker driver (this script) and remove them from
49 # the arguments being passed to the compiler driver.
50 linker_driver_actions = {}
51 compiler_driver_args = []
52 for arg in args[1:]:
53 if arg.startswith(_LINKER_DRIVER_ARG_PREFIX):
54 # Convert driver actions into a map of name => lambda to invoke.
55 driver_action = ProcessLinkerDriverArg(arg)
56 linker_driver_actions[driver_action[0]] = driver_action[1]
Mark Mentovai 2016/05/20 19:41:11 assert (or raise if not) driver_action[0] in linke
Robert Sesek 2016/05/24 15:05:33 Done.
57 else:
58 compiler_driver_args.append(arg)
59
60 linker_driver_outputs = [_FindLinkerOutput(compiler_driver_args)]
61
62 try:
63 # Run the linker by invoking the compiler driver.
64 subprocess.check_call(compiler_driver_args)
65
66 # Run the linker driver actions, in the order specified by the actions list.
67 for action in _LINKER_DRIVER_ACTIONS:
68 name = action[0]
69 if name in linker_driver_actions:
70 linker_driver_outputs += linker_driver_actions[name](args)
Mark Mentovai 2016/05/20 19:41:11 I’m not going to force you to fix this because it’
Robert Sesek 2016/05/24 15:05:33 Acknowledged.
71 except:
72 # If a linker driver action failed, remove all the outputs to make the
73 # build step atomic.
74 map(_RemovePath, linker_driver_outputs)
75
76 # Re-report the original failure.
77 raise
78
79
80 def ProcessLinkerDriverArg(arg):
81 """Processes a linker driver argument and returns a tuple containing the
82 name and unary lambda to invoke for that linker driver action.
83
84 Args:
85 arg: string, The linker driver argument.
86
87 Returns:
88 A 2-tuple:
89 0: The driver action name, as in _LINKER_DRIVER_ACTIONS.
90 1: An 1-ary lambda that takes the full list of arguments passed to
91 Main(). The lambda should call the linker driver action that
92 corresponds to the argument.
Mark Mentovai 2016/05/20 19:41:11 and return blah blah blah
Robert Sesek 2016/05/24 15:05:33 Done.
93 """
94 if not arg.startswith(_LINKER_DRIVER_ARG_PREFIX):
95 raise ValueError('%s is not a linker driver argument' % (arg,))
96
97 sub_arg = arg[len(_LINKER_DRIVER_ARG_PREFIX):]
98
99 for driver_action in _LINKER_DRIVER_ACTIONS:
100 (name, action) = driver_action
101 if sub_arg.startswith(name):
102 return (name,
103 lambda full_args: action(sub_arg[len(name):], full_args))
104
105 raise ValueError('Unknown linker driver argument: %s' % (arg,))
106
107
108 def RunDsymUtil(dsym_path_prefix, full_args):
109 """Linker driver action for -Wcrl,dsym,<dsym-path-prefix>. Invokes dsymutil
110 on the linker's output and produces a dsym file at |dsym_file| path.
111
112 Args:
113 dsym_path_prefix: string, The path at which the dsymutil output should be
114 located.
115 full_args: list of string, Full argument list for the linker driver.
116
117 Returns:
118 list of string, Build step outputs.
119 """
120 if not len(dsym_path_prefix):
121 raise ValueError('Unspecified dSYM output file')
122
123 linker_out = _FindLinkerOutput(full_args)
124 (head, tail) = os.path.split(linker_out)
125 dsym_out = os.path.join(dsym_path_prefix, tail + '.dSYM')
126
127 # Remove old dSYMs before invoking dsymutil.
128 _RemovePath(dsym_out)
129 subprocess.check_call(['xcrun', 'dsymutil', '-o', dsym_out, linker_out])
130 return [dsym_out]
Mark Mentovai 2016/05/20 19:41:11 This and RunStrip can return a (tuple) instead of
Robert Sesek 2016/05/24 15:05:33 Returning tuple means having a (turd,). These seem
131
132
133 def RunStrip(strip_args_string, full_args):
134 """Linker driver action for -Wcrl,strip,<strip_arguments>.
135
136 Args:
137 strip_args_string: string, Comma-separated arguments for `strip`.
138 full_args: list of string, Full arguments for the linker driver.
139
140 Returns:
141 list of string, Build step outputs.
142 """
143 strip_args_list = strip_args_string.split(',')
Mark Mentovai 2016/05/20 19:41:11 If you get “-Wcrl,strip,”, then you want to run “s
Robert Sesek 2016/05/24 15:05:33 Done.
144 strip_command = ['xcrun', 'strip'] + strip_args_list
145 strip_command.append(_FindLinkerOutput(full_args))
146 subprocess.check_call(strip_command)
Mark Mentovai 2016/05/20 19:41:11 TODO(maybe?): swallow that bogus strip deprecation
Robert Sesek 2016/05/24 15:05:33 Gonna skip this for now.
147 return []
148
149
150 def _FindLinkerOutput(full_args):
151 """Finds the output of the linker by looking for the output flag in its
152 argument list. As this is a required linker argument, raises an error if it
153 cannot be found.
154 """
155 for (i, arg) in enumerate(full_args):
Mark Mentovai 2016/05/20 19:41:11 Why not just this: return full_args[full_args.ind
Robert Sesek 2016/05/24 15:05:33 Done.
156 if arg == '-o':
157 return full_args[i+1]
158 raise RuntimeError('Unable to locate linker output file (no -o flag)')
159
160
161 def _RemovePath(path):
162 """Removes the file or directory at |path| if it exists."""
163 if os.path.exists(path):
164 if os.path.isdir(path):
165 shutil.rmtree(path)
166 else:
167 os.unlink(path)
168
169
170 _LINKER_DRIVER_ARG_PREFIX = '-Wcrl,'
171
172 """List of linker driver actions. The sort order of this list affects the
173 order in which the actions are invoked. The first item in the tuple is the
174 argument's -Wcrl,<sub_argument> and the second is the function to invoke.
175 """
176 _LINKER_DRIVER_ACTIONS = [
177 ('dsym,', RunDsymUtil),
178 ('strip,', RunStrip),
179 ]
180
181
182 if __name__ == '__main__':
183 Main(sys.argv)
184 sys.exit(0)
OLDNEW
« no previous file with comments | « build/toolchain/mac/BUILD.gn ('k') | chrome/BUILD.gn » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698