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

Side by Side Diff: tools/clang/scripts/run_tool.py

Issue 2448133006: Tool added to extract network traffic annotations. (Closed)
Patch Set: Created 4 years, 1 month 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
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright (c) 2013 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2013 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 """Wrapper script to help run clang tools across Chromium code. 5 """Wrapper script to help run clang tools across Chromium code.
6 6
7 How to use this tool: 7 How to use this tool:
8 If you want to run the tool across all Chromium code: 8 If you want to run the tool across all Chromium code:
9 run_tool.py <tool> <path/to/compiledb> 9 run_tool.py <tool> <path/to/compiledb>
10 10
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
107 edit_type, path, offset, length, replacement = line.split(':::', 4) 107 edit_type, path, offset, length, replacement = line.split(':::', 4)
108 replacement = replacement.replace('\0', '\n') 108 replacement = replacement.replace('\0', '\n')
109 # Normalize the file path emitted by the clang tool. 109 # Normalize the file path emitted by the clang tool.
110 path = os.path.realpath(os.path.join(build_directory, path)) 110 path = os.path.realpath(os.path.join(build_directory, path))
111 edits[path].append(Edit(edit_type, int(offset), int(length), replacement)) 111 edits[path].append(Edit(edit_type, int(offset), int(length), replacement))
112 except ValueError: 112 except ValueError:
113 print 'Unable to parse edit: %s' % line 113 print 'Unable to parse edit: %s' % line
114 return edits 114 return edits
115 115
116 116
117 def _ExecuteTool(toolname, build_directory, filename): 117 def _ExecuteTool(toolname, tool_params, build_directory, filename):
118 """Executes the tool. 118 """Executes the tool.
119 119
120 This is defined outside the class so it can be pickled for the multiprocessing 120 This is defined outside the class so it can be pickled for the multiprocessing
121 module. 121 module.
122 122
123 Args: 123 Args:
124 toolname: Path to the tool to execute. 124 toolname: Path to the tool to execute.
125 build_directory: Directory that contains the compile database. 125 build_directory: Directory that contains the compile database.
126 filename: The file to run the tool over. 126 filename: The file to run the tool over.
127 127
128 Returns: 128 Returns:
129 A dictionary that must contain the key "status" and a boolean value 129 A dictionary that must contain the key "status" and a boolean value
130 associated with it. 130 associated with it.
131 131
132 If status is True, then the generated edits are stored with the key "edits" 132 If status is True, then the generated edits are stored with the key "edits"
133 in the dictionary. 133 in the dictionary.
134 134
135 Otherwise, the filename and the output from stderr are associated with the 135 Otherwise, the filename and the output from stderr are associated with the
136 keys "filename" and "stderr" respectively. 136 keys "filename" and "stderr" respectively.
137 """ 137 """
138 command = subprocess.Popen( 138 command = subprocess.Popen(
139 (toolname, '-p', build_directory, filename), 139 (toolname, '-p', build_directory, filename) if tool_params is None else
140 (toolname, '-p', build_directory, filename, tool_params),
140 stdout=subprocess.PIPE, 141 stdout=subprocess.PIPE,
141 stderr=subprocess.PIPE) 142 stderr=subprocess.PIPE)
142 stdout, stderr = command.communicate() 143 stdout, stderr = command.communicate()
143 if command.returncode != 0: 144 if command.returncode != 0:
144 return {'status': False, 'filename': filename, 'stderr': stderr} 145 return {'status': False, 'filename': filename, 'stderr': stderr}
145 else: 146 else:
146 return {'status': True, 147 return {'status': True,
147 'edits': _ExtractEditsFromStdout(build_directory, stdout)} 148 'edits': _ExtractEditsFromStdout(build_directory, stdout)}
148 149
149 150
150 class _CompilerDispatcher(object): 151 class _CompilerDispatcher(object):
151 """Multiprocessing controller for running clang tools in parallel.""" 152 """Multiprocessing controller for running clang tools in parallel."""
152 153
153 def __init__(self, toolname, build_directory, filenames): 154 def __init__(self, toolname, tool_params, build_directory, filenames):
154 """Initializer method. 155 """Initializer method.
155 156
156 Args: 157 Args:
157 toolname: Path to the tool to execute. 158 toolname: Path to the tool to execute.
158 build_directory: Directory that contains the compile database. 159 build_directory: Directory that contains the compile database.
159 filenames: The files to run the tool over. 160 filenames: The files to run the tool over.
160 """ 161 """
161 self.__toolname = toolname 162 self.__toolname = toolname
163 self.__tool_params = tool_params
162 self.__build_directory = build_directory 164 self.__build_directory = build_directory
163 self.__filenames = filenames 165 self.__filenames = filenames
164 self.__success_count = 0 166 self.__success_count = 0
165 self.__failed_count = 0 167 self.__failed_count = 0
166 self.__edit_count = 0 168 self.__edit_count = 0
167 self.__edits = collections.defaultdict(list) 169 self.__edits = collections.defaultdict(list)
168 170
169 @property 171 @property
170 def edits(self): 172 def edits(self):
171 return self.__edits 173 return self.__edits
172 174
173 @property 175 @property
174 def failed_count(self): 176 def failed_count(self):
175 return self.__failed_count 177 return self.__failed_count
176 178
177 def Run(self): 179 def Run(self):
178 """Does the grunt work.""" 180 """Does the grunt work."""
179 pool = multiprocessing.Pool() 181 pool = multiprocessing.Pool()
180 result_iterator = pool.imap_unordered( 182 result_iterator = pool.imap_unordered(
181 functools.partial(_ExecuteTool, self.__toolname, 183 functools.partial(_ExecuteTool, self.__toolname, self.__tool_params,
182 self.__build_directory), self.__filenames) 184 self.__build_directory),
185 self.__filenames)
183 for result in result_iterator: 186 for result in result_iterator:
184 self.__ProcessResult(result) 187 self.__ProcessResult(result)
185 sys.stdout.write('\n') 188 sys.stdout.write('\n')
186 sys.stdout.flush() 189 sys.stdout.flush()
187 190
188 def __ProcessResult(self, result): 191 def __ProcessResult(self, result):
189 """Handles result processing. 192 """Handles result processing.
190 193
191 Args: 194 Args:
192 result: The result dictionary returned by _ExecuteTool. 195 result: The result dictionary returned by _ExecuteTool.
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
292 '--generate-compdb', 295 '--generate-compdb',
293 action='store_true', 296 action='store_true',
294 help='regenerate the compile database before running the tool') 297 help='regenerate the compile database before running the tool')
295 parser.add_argument( 298 parser.add_argument(
296 'compile_database', 299 'compile_database',
297 help='path to the directory that contains the compile database') 300 help='path to the directory that contains the compile database')
298 parser.add_argument( 301 parser.add_argument(
299 'path_filter', 302 'path_filter',
300 nargs='*', 303 nargs='*',
301 help='optional paths to filter what files the tool is run on') 304 help='optional paths to filter what files the tool is run on')
305 parser.add_argument(
306 '--tool-params', type=str,
307 help='parameters passed to the tool')
battre 2016/10/26 14:29:18 please fix indentation
Ramin Halavati 2016/10/27 09:40:08 Done.
302 args = parser.parse_args() 308 args = parser.parse_args()
303 309
304 os.environ['PATH'] = '%s%s%s' % ( 310 os.environ['PATH'] = '%s%s%s' % (
305 os.path.abspath(os.path.join( 311 os.path.abspath(os.path.join(
306 os.path.dirname(__file__), 312 os.path.dirname(__file__),
307 '../../../third_party/llvm-build/Release+Asserts/bin')), 313 '../../../third_party/llvm-build/Release+Asserts/bin')),
308 os.pathsep, 314 os.pathsep,
309 os.environ['PATH']) 315 os.environ['PATH'])
310 316
311 if args.generate_compdb: 317 if args.generate_compdb:
312 compile_db.GenerateWithNinja(args.compile_database) 318 compile_db.GenerateWithNinja(args.compile_database)
313 319
314 if args.all: 320 if args.all:
315 filenames = set(_GetFilesFromCompileDB(args.compile_database)) 321 filenames = set(_GetFilesFromCompileDB(args.compile_database))
316 source_filenames = filenames 322 source_filenames = filenames
317 else: 323 else:
318 filenames = set(_GetFilesFromGit(args.path_filter)) 324 filenames = set(_GetFilesFromGit(args.path_filter))
319 # Filter out files that aren't C/C++/Obj-C/Obj-C++. 325 # Filter out files that aren't C/C++/Obj-C/Obj-C++.
320 extensions = frozenset(('.c', '.cc', '.cpp', '.m', '.mm')) 326 extensions = frozenset(('.c', '.cc', '.cpp', '.m', '.mm'))
321 source_filenames = [f 327 source_filenames = [f
322 for f in filenames 328 for f in filenames
323 if os.path.splitext(f)[1] in extensions] 329 if os.path.splitext(f)[1] in extensions]
324 dispatcher = _CompilerDispatcher(args.tool, args.compile_database, 330 dispatcher = _CompilerDispatcher(args.tool, args.tool_params,
331 args.compile_database,
325 source_filenames) 332 source_filenames)
326 dispatcher.Run() 333 dispatcher.Run()
327 # Filter out edits to files that aren't in the git repository, since it's not 334 # Filter out edits to files that aren't in the git repository, since it's not
328 # useful to modify files that aren't under source control--typically, these 335 # useful to modify files that aren't under source control--typically, these
329 # are generated files or files in a git submodule that's not part of Chromium. 336 # are generated files or files in a git submodule that's not part of Chromium.
330 _ApplyEdits({k: v 337 _ApplyEdits({k: v
331 for k, v in dispatcher.edits.iteritems() 338 for k, v in dispatcher.edits.iteritems()
332 if os.path.realpath(k) in filenames}) 339 if os.path.realpath(k) in filenames})
333 return -dispatcher.failed_count 340 return -dispatcher.failed_count
334 341
335 342
336 if __name__ == '__main__': 343 if __name__ == '__main__':
337 sys.exit(main()) 344 sys.exit(main())
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698