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.

83 lines
2.8 KiB

# Copyright (c) 2015 - present Facebook, Inc.
# All rights reserved.
#
# This source code is licensed under the BSD style license found in the
# LICENSE file in the root directory of this source tree. An additional grant
# of patent rights can be found in the PATENTS file in the same directory.
import logging
import os
import subprocess
import traceback
import util
from inferlib import config, utils
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'''
ALIASED_COMMANDS = ['clang', 'clang++', 'cc', 'gcc', 'g++']
BUILD_COMMANDS = ['make', 'waf']
SUPPORTED_COMMANDS = ALIASED_COMMANDS + BUILD_COMMANDS
def gen_instance(*args):
return MakeCapture(*args)
create_argparser = \
util.clang_frontend_argparser(MODULE_DESCRIPTION, MODULE_NAME)
class MakeCapture:
def __init__(self, args, cmd):
self.args = args
self.cmd = cmd
command_name = os.path.basename(cmd[0])
if command_name in ALIASED_COMMANDS:
# remove absolute paths for these commands as we want to
# substitue our own wrappers instead using a PATH trick
cmd[0] = command_name
def get_envvars(self):
env_vars = dict(os.environ)
wrappers_path = config.WRAPPERS_DIRECTORY
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'],
)
frontend_env_vars = util.get_clang_frontend_envvars(self.args)
env_vars.update(frontend_env_vars)
return env_vars
def capture(self):
try:
env = self.get_envvars()
logging.info('Running command %s with env:\n%s' % (self.cmd, env))
subprocess.check_call(self.cmd, env=env)
capture_dir = os.path.join(self.args.infer_out, 'captured')
if len(os.listdir(capture_dir)) < 1:
# Don't return with a failure code unless we're
# running make. It could be normal to have captured
# nothing (eg, empty source file). Further output will
# alert the user that there was nothing to analyze.
if self.cmd[0] == 'make':
# reuse code from gradle, etc. integration
return util.run_compilation_commands([], 'make clean')
return os.EX_OK
except subprocess.CalledProcessError as exc:
if self.args.debug:
traceback.print_exc()
return exc.returncode