diff options
author | Laszlo Nagy <rizsotto.mailinglist@gmail.com> | 2016-04-19 12:03:03 +0000 |
---|---|---|
committer | Laszlo Nagy <rizsotto.mailinglist@gmail.com> | 2016-04-19 12:03:03 +0000 |
commit | 8bd63e5518f12352387e0e4a183dc331b657c4d1 (patch) | |
tree | 92f1d02a11d6815affa4160032773b80cd0bd376 /clang/tools/scan-build-py/libscanbuild/intercept.py | |
parent | 79b25d5ea4fd31267a163a9862f153d20e4fdbfe (diff) | |
download | bcm5719-llvm-8bd63e5518f12352387e0e4a183dc331b657c4d1.tar.gz bcm5719-llvm-8bd63e5518f12352387e0e4a183dc331b657c4d1.zip |
D17487: [analyzer][scan-build-py] flag filter modification for compilation database creation
llvm-svn: 266726
Diffstat (limited to 'clang/tools/scan-build-py/libscanbuild/intercept.py')
-rw-r--r-- | clang/tools/scan-build-py/libscanbuild/intercept.py | 58 |
1 files changed, 19 insertions, 39 deletions
diff --git a/clang/tools/scan-build-py/libscanbuild/intercept.py b/clang/tools/scan-build-py/libscanbuild/intercept.py index 6062e2ea8ca..6a9f75349fb 100644 --- a/clang/tools/scan-build-py/libscanbuild/intercept.py +++ b/clang/tools/scan-build-py/libscanbuild/intercept.py @@ -31,9 +31,9 @@ import argparse import logging import subprocess from libear import build_libear, TemporaryDirectory -from libscanbuild import duplicate_check, tempdir, initialize_logging from libscanbuild import command_entry_point -from libscanbuild.command import Action, classify_parameters +from libscanbuild import duplicate_check, tempdir, initialize_logging +from libscanbuild.compilation import split_command from libscanbuild.shell import encode, decode __all__ = ['capture', 'intercept_build_main', 'intercept_build_wrapper'] @@ -72,23 +72,23 @@ def capture(args, bin_dir): from the arguments. And do shell escaping on the command. To support incremental builds, it is desired to read elements from - an existing compilation database from a previous run. These elemets + an existing compilation database from a previous run. These elements shall be merged with the new elements. """ # create entries from the current run current = itertools.chain.from_iterable( # creates a sequence of entry generators from an exec, - # but filter out non compiler calls before. - (format_entry(x) for x in commands if is_compiler_call(x))) + format_entry(command) for command in commands) # read entries from previous run - if 'append' in args and args.append and os.path.exists(args.cdb): + if 'append' in args and args.append and os.path.isfile(args.cdb): with open(args.cdb) as handle: previous = iter(json.load(handle)) else: previous = iter([]) # filter out duplicate entries from both duplicate = duplicate_check(entry_hash) - return (entry for entry in itertools.chain(previous, current) + return (entry + for entry in itertools.chain(previous, current) if os.path.exists(entry['file']) and not duplicate(entry)) with TemporaryDirectory(prefix='intercept-', dir=tempdir()) as tmp_dir: @@ -98,14 +98,14 @@ def capture(args, bin_dir): exit_code = subprocess.call(args.build, env=environment) logging.info('build finished with exit code: %d', exit_code) # read the intercepted exec calls - commands = itertools.chain.from_iterable( + exec_traces = itertools.chain.from_iterable( parse_exec_trace(os.path.join(tmp_dir, filename)) for filename in sorted(glob.iglob(os.path.join(tmp_dir, '*.cmd')))) # do post processing only if that was requested if 'raw_entries' not in args or not args.raw_entries: - entries = post_processing(commands) + entries = post_processing(exec_traces) else: - entries = commands + entries = exec_traces # dump the compilation database with open(args.cdb, 'w+') as handle: json.dump(list(entries), handle, sort_keys=True, indent=4) @@ -209,7 +209,7 @@ def parse_exec_trace(filename): } -def format_entry(entry): +def format_entry(exec_trace): """ Generate the desired fields for compilation database entries. """ def abspath(cwd, name): @@ -217,40 +217,20 @@ def format_entry(entry): fullname = name if os.path.isabs(name) else os.path.join(cwd, name) return os.path.normpath(fullname) - logging.debug('format this command: %s', entry['command']) - atoms = classify_parameters(entry['command']) - if atoms['action'] <= Action.Compile: - for source in atoms['files']: - compiler = 'c++' if atoms['c++'] else 'cc' - flags = atoms['compile_options'] - flags += ['-o', atoms['output']] if atoms['output'] else [] - flags += ['-x', atoms['language']] if 'language' in atoms else [] - flags += [elem - for arch in atoms.get('archs_seen', []) - for elem in ['-arch', arch]] - command = [compiler, '-c'] + flags + [source] + logging.debug('format this command: %s', exec_trace['command']) + compilation = split_command(exec_trace['command']) + if compilation: + for source in compilation.files: + compiler = 'c++' if compilation.compiler == 'c++' else 'cc' + command = [compiler, '-c'] + compilation.flags + [source] logging.debug('formated as: %s', command) yield { - 'directory': entry['directory'], + 'directory': exec_trace['directory'], 'command': encode(command), - 'file': abspath(entry['directory'], source) + 'file': abspath(exec_trace['directory'], source) } -def is_compiler_call(entry): - """ A predicate to decide the entry is a compiler call or not. """ - - patterns = [ - re.compile(r'^([^/]*/)*intercept-c(c|\+\+)$'), - re.compile(r'^([^/]*/)*c(c|\+\+)$'), - re.compile(r'^([^/]*/)*([^-]*-)*[mg](cc|\+\+)(-\d+(\.\d+){0,2})?$'), - re.compile(r'^([^/]*/)*([^-]*-)*clang(\+\+)?(-\d+(\.\d+){0,2})?$'), - re.compile(r'^([^/]*/)*llvm-g(cc|\+\+)$'), - ] - executable = entry['command'][0] - return any((pattern.match(executable) for pattern in patterns)) - - def is_preload_disabled(platform): """ Library-based interposition will fail silently if SIP is enabled, so this should be detected. You can detect whether SIP is enabled on |