You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
132 lines
4.2 KiB
132 lines
4.2 KiB
10 years ago
|
import argparse
|
||
|
import os
|
||
|
import subprocess
|
||
|
import traceback
|
||
|
|
||
|
MODULE_NAME = 'make/cc/clang/gcc'
|
||
|
MODULE_DESCRIPTION = '''Run analysis of code built with commands like:
|
||
|
make [target]
|
||
|
clang [compiler_options] <filename>
|
||
|
gcc [compiler_options] <filename>
|
||
|
cc [compiler_options] <filename>
|
||
|
|
||
|
Analysis examples:
|
||
|
infer -- make all
|
||
|
infer -- clang -c srcfile.m
|
||
|
infer -- gcc -c srcfile.c'''
|
||
|
|
||
|
|
||
|
def gen_instance(*args):
|
||
|
return MakeCapture(*args)
|
||
|
|
||
|
|
||
|
def mkdir_if_not_exists(path):
|
||
|
if not os.path.exists(path):
|
||
|
os.mkdir(path)
|
||
|
|
||
|
|
||
|
def create_argparser(group_name=MODULE_NAME):
|
||
|
"""This defines the set of arguments that get added by this module to the
|
||
|
set of global args defined in the infer top-level module
|
||
|
Do not use this function directly, it should be invoked by the infer
|
||
|
top-level module"""
|
||
|
parser = argparse.ArgumentParser(add_help=False)
|
||
|
group = parser.add_argument_group(
|
||
|
"{grp} module".format(grp=MODULE_NAME),
|
||
|
description=MODULE_DESCRIPTION,
|
||
|
)
|
||
|
group.add_argument(
|
||
|
'-hd', '--headers',
|
||
|
action='store_true',
|
||
|
help='Analyze code in header files',
|
||
|
)
|
||
|
group.add_argument(
|
||
|
'--models_mode',
|
||
|
action='store_true',
|
||
|
dest='models_mode',
|
||
|
help='Mode for computing the models',
|
||
|
)
|
||
|
group.add_argument(
|
||
|
'--no_failures_allowed',
|
||
|
action='store_true',
|
||
|
dest='no_failures_allowed',
|
||
|
help='Fail if at least one of the translations fails',
|
||
|
)
|
||
|
group.add_argument(
|
||
|
'-tm', '--testing_mode',
|
||
|
dest='testing_mode',
|
||
|
action='store_true',
|
||
|
help='Testing mode for the translation: Do not translate libraries'
|
||
|
' (including enums)')
|
||
|
group.add_argument(
|
||
|
'-fs', '--frontend-stats',
|
||
|
dest='frontend_stats',
|
||
|
action='store_true',
|
||
|
help='Output statistics about the capture phase to *.o.astlog')
|
||
|
group.add_argument(
|
||
|
'-fd', '--frontend-debug',
|
||
|
dest='frontend_debug',
|
||
|
action='store_true',
|
||
|
help='Output debugging information to *.o.astlog during capture')
|
||
|
return parser
|
||
|
|
||
|
|
||
|
class MakeCapture:
|
||
|
def __init__(self, args, cmd):
|
||
|
self.args = args
|
||
|
self.cmd = [os.path.basename(cmd[0])] + cmd[1:]
|
||
|
|
||
|
def create_results_dir(self):
|
||
|
results_dir = self.args.infer_out
|
||
|
mkdir_if_not_exists(results_dir)
|
||
|
mkdir_if_not_exists(os.path.join(results_dir, 'specs'))
|
||
|
mkdir_if_not_exists(os.path.join(results_dir, 'captured'))
|
||
|
mkdir_if_not_exists(os.path.join(results_dir, 'sources'))
|
||
|
|
||
|
def get_envvars(self):
|
||
|
env_vars = dict(os.environ)
|
||
|
env_vars['INFER_RESULTS_DIR'] = self.args.infer_out
|
||
|
wrappers_path = os.path.join(
|
||
|
os.path.dirname(os.path.realpath(__file__)), '..', 'wrappers')
|
||
|
env_vars['INFER_OLD_PATH'] = env_vars['PATH']
|
||
|
env_vars['PATH'] = '{wrappers}{sep}{path}'.format(
|
||
|
wrappers=wrappers_path,
|
||
|
sep=os.pathsep,
|
||
|
path=env_vars['PATH'],
|
||
|
)
|
||
|
return env_vars
|
||
|
|
||
|
def capture(self):
|
||
|
self.create_results_dir()
|
||
|
|
||
|
env_vars = self.get_envvars()
|
||
|
frontend_args = []
|
||
|
|
||
|
if self.args.headers:
|
||
|
frontend_args.append('-headers')
|
||
|
if self.args.models_mode:
|
||
|
frontend_args.append('-models_mode')
|
||
|
if self.args.project_root:
|
||
|
frontend_args += ['-project_root', self.args.project_root]
|
||
|
if self.args.testing_mode:
|
||
|
frontend_args.append('-testing_mode')
|
||
|
if self.args.frontend_debug:
|
||
|
frontend_args += ['-debug']
|
||
|
env_vars['FCP_DEBUG_MODE'] = '1'
|
||
|
if self.args.frontend_stats:
|
||
|
frontend_args += ['-stats']
|
||
|
env_vars['FCP_DEBUG_MODE'] = '1'
|
||
|
if self.args.no_failures_allowed:
|
||
|
env_vars['FCP_REPORT_FRONTEND_FAILURE'] = '1'
|
||
|
|
||
|
# export an env variable with all the arguments to pass to InferClang
|
||
|
env_vars['FCP_INFER_FRONTEND_ARGS'] = ' '.join(frontend_args)
|
||
|
|
||
|
try:
|
||
|
subprocess.check_call(self.cmd, env=env_vars)
|
||
|
return os.EX_OK
|
||
|
except subprocess.CalledProcessError as exc:
|
||
|
if self.args.debug:
|
||
|
traceback.print_exc()
|
||
|
return exc.returncode
|