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

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