1
- #!/usr/bin/env python
1
+ #!/usr/bin/env python3
2
2
#
3
3
#===- run-clang-tidy.py - Parallel clang-tidy runner --------*- python -*--===#
4
4
#
41
41
import json
42
42
import multiprocessing
43
43
import os
44
+ import queue
44
45
import re
45
46
import shutil
46
47
import subprocess
54
55
except ImportError :
55
56
yaml = None
56
57
57
- is_py2 = sys .version [0 ] == '2'
58
-
59
- if is_py2 :
60
- import Queue as queue
61
- else :
62
- import queue as queue
63
-
64
58
65
59
def strtobool (val ):
66
60
"""Convert a string representation of truth to a bool following LLVM's CLI argument parsing."""
@@ -158,20 +152,29 @@ def merge_replacement_files(tmpdir, mergefile):
158
152
open (mergefile , 'w' ).close ()
159
153
160
154
161
- def check_clang_apply_replacements_binary (args ):
162
- """Checks if invoking supplied clang-apply-replacements binary works."""
163
- try :
164
- subprocess .check_call ([args .clang_apply_replacements_binary , '--version' ])
165
- except :
166
- print ('Unable to run clang-apply-replacements. Is clang-apply-replacements '
167
- 'binary correctly specified?' , file = sys .stderr )
168
- traceback .print_exc ()
169
- sys .exit (1 )
155
+ def find_binary (arg , name , build_path ):
156
+ """Get the path for a binary or exit"""
157
+ if arg :
158
+ if shutil .which (arg ):
159
+ return arg
160
+ else :
161
+ raise SystemExit (
162
+ "error: passed binary '{}' was not found or is not executable"
163
+ .format (arg ))
164
+
165
+ built_path = os .path .join (build_path , "bin" , name )
166
+ binary = shutil .which (name ) or shutil .which (built_path )
167
+ if binary :
168
+ return binary
169
+ else :
170
+ raise SystemExit (
171
+ "error: failed to find {} in $PATH or at {}"
172
+ .format (name , built_path ))
170
173
171
174
172
- def apply_fixes (args , tmpdir ):
175
+ def apply_fixes (args , clang_apply_replacements_binary , tmpdir ):
173
176
"""Calls clang-apply-fixes on a given directory."""
174
- invocation = [args . clang_apply_replacements_binary ]
177
+ invocation = [clang_apply_replacements_binary ]
175
178
if args .format :
176
179
invocation .append ('-format' )
177
180
if args .style :
@@ -180,11 +183,12 @@ def apply_fixes(args, tmpdir):
180
183
subprocess .call (invocation )
181
184
182
185
183
- def run_tidy (args , tmpdir , build_path , queue , lock , failed_files ):
186
+ def run_tidy (args , clang_tidy_binary , tmpdir , build_path , queue , lock ,
187
+ failed_files ):
184
188
"""Takes filenames out of queue and runs clang-tidy on them."""
185
189
while True :
186
190
name = queue .get ()
187
- invocation = get_tidy_invocation (name , args . clang_tidy_binary , args .checks ,
191
+ invocation = get_tidy_invocation (name , clang_tidy_binary , args .checks ,
188
192
tmpdir , build_path , args .header_filter ,
189
193
args .allow_enabling_alpha_checkers ,
190
194
args .extra_arg , args .extra_arg_before ,
@@ -210,15 +214,13 @@ def main():
210
214
parser = argparse .ArgumentParser (description = 'Runs clang-tidy over all files '
211
215
'in a compilation database. Requires '
212
216
'clang-tidy and clang-apply-replacements in '
213
- '$PATH.' )
217
+ '$PATH or in your build directory .' )
214
218
parser .add_argument ('-allow-enabling-alpha-checkers' ,
215
219
action = 'store_true' , help = 'allow alpha checkers from '
216
220
'clang-analyzer.' )
217
221
parser .add_argument ('-clang-tidy-binary' , metavar = 'PATH' ,
218
- default = 'clang-tidy' ,
219
222
help = 'path to clang-tidy binary' )
220
223
parser .add_argument ('-clang-apply-replacements-binary' , metavar = 'PATH' ,
221
- default = 'clang-apply-replacements' ,
222
224
help = 'path to clang-apply-replacements binary' )
223
225
parser .add_argument ('-checks' , default = None ,
224
226
help = 'checks filter, when not specified, use clang-tidy '
@@ -278,8 +280,18 @@ def main():
278
280
# Find our database
279
281
build_path = find_compilation_database (db_path )
280
282
283
+ clang_tidy_binary = find_binary (args .clang_tidy_binary , "clang-tidy" ,
284
+ build_path )
285
+
286
+ tmpdir = None
287
+ if args .fix or (yaml and args .export_fixes ):
288
+ clang_apply_replacements_binary = find_binary (
289
+ args .clang_apply_replacements_binary , "clang-apply-replacements" ,
290
+ build_path )
291
+ tmpdir = tempfile .mkdtemp ()
292
+
281
293
try :
282
- invocation = get_tidy_invocation ("" , args . clang_tidy_binary , args .checks ,
294
+ invocation = get_tidy_invocation ("" , clang_tidy_binary , args .checks ,
283
295
None , build_path , args .header_filter ,
284
296
args .allow_enabling_alpha_checkers ,
285
297
args .extra_arg , args .extra_arg_before ,
@@ -306,11 +318,6 @@ def main():
306
318
if max_task == 0 :
307
319
max_task = multiprocessing .cpu_count ()
308
320
309
- tmpdir = None
310
- if args .fix or (yaml and args .export_fixes ):
311
- check_clang_apply_replacements_binary (args )
312
- tmpdir = tempfile .mkdtemp ()
313
-
314
321
# Build up a big regexy filter from all command line arguments.
315
322
file_name_re = re .compile ('|' .join (args .files ))
316
323
@@ -323,7 +330,8 @@ def main():
323
330
lock = threading .Lock ()
324
331
for _ in range (max_task ):
325
332
t = threading .Thread (target = run_tidy ,
326
- args = (args , tmpdir , build_path , task_queue , lock , failed_files ))
333
+ args = (args , clang_tidy_binary , tmpdir , build_path ,
334
+ task_queue , lock , failed_files ))
327
335
t .daemon = True
328
336
t .start ()
329
337
@@ -357,7 +365,7 @@ def main():
357
365
if args .fix :
358
366
print ('Applying fixes ...' )
359
367
try :
360
- apply_fixes (args , tmpdir )
368
+ apply_fixes (args , clang_apply_replacements_binary , tmpdir )
361
369
except :
362
370
print ('Error applying fixes.\n ' , file = sys .stderr )
363
371
traceback .print_exc ()
0 commit comments