def analyze_compiler_wrapper_impl(result, execution): """ Implements analyzer compiler wrapper functionality. """ # don't run analyzer when compilation fails. or when it's not requested. if result or not os.getenv('ANALYZE_BUILD_CLANG'): return # check is it a compilation? compilation = split_command(execution.cmd) if compilation is None: return # collect the needed parameters from environment, crash when missing parameters = { 'clang': os.getenv('ANALYZE_BUILD_CLANG'), 'output_dir': os.getenv('ANALYZE_BUILD_REPORT_DIR'), 'output_format': os.getenv('ANALYZE_BUILD_REPORT_FORMAT'), 'output_failures': os.getenv('ANALYZE_BUILD_REPORT_FAILURES'), 'direct_args': os.getenv('ANALYZE_BUILD_PARAMETERS', '').split(' '), 'force_debug': os.getenv('ANALYZE_BUILD_FORCE_DEBUG'), 'directory': execution.cwd, 'command': [execution.cmd[0], '-c'] + compilation.flags, 'ctu': get_ctu_config_from_json(os.getenv('ANALYZE_BUILD_CTU')) } # call static analyzer against the compilation for source in compilation.files: parameters.update({'file': source}) logging.debug('analyzer parameters %s', parameters) current = run(parameters) # display error message from the static analyzer if current is not None: for line in current['error_output']: logging.info(line.rstrip())
def analyze_build_wrapper(**kwargs): """ Entry point for `analyze-cc` and `analyze-c++` compiler wrappers. """ # don't run analyzer when compilation fails. if kwargs['result'] or not os.getenv('ANALYZE_BUILD_CLANG'): return # don't run analyzer when the command is not a compilation # (can be preprocessing or a linking only execution of the compiler) compilation = split_command(kwargs['command']) if compilation is None: return # collect the needed parameters from environment, crash when missing env = os.environ.copy() parameters = { 'clang': env['ANALYZE_BUILD_CLANG'], 'output_dir': env['ANALYZE_BUILD_REPORT_DIR'], 'output_format': env['ANALYZE_BUILD_REPORT_FORMAT'], 'output_failures': env.get('ANALYZE_BUILD_REPORT_FAILURES', False), 'direct_args': env.get('ANALYZE_BUILD_PARAMETERS', '').split(' '), 'force_debug': env.get('ANALYZE_BUILD_FORCE_DEBUG', False), 'directory': os.getcwd(), 'command': [kwargs['compiler'], '-c'] + compilation.flags } # call static analyzer against the compilation for source in compilation.files: current = run(dict(parameters, file=source)) # display error message from the static analyzer logging_analyzer_output(current)
def analyze_compiler_wrapper_impl(result, execution): """ Implements analyzer compiler wrapper functionality. """ # don't run analyzer when compilation fails. or when it's not requested. if result or not os.getenv('ANALYZE_BUILD_CLANG'): return # check is it a compilation? compilation = split_command(execution.cmd) if compilation is None: return # collect the needed parameters from environment, crash when missing parameters = { 'clang': os.getenv('ANALYZE_BUILD_CLANG'), 'output_dir': os.getenv('ANALYZE_BUILD_REPORT_DIR'), 'output_format': os.getenv('ANALYZE_BUILD_REPORT_FORMAT'), 'output_failures': os.getenv('ANALYZE_BUILD_REPORT_FAILURES'), 'direct_args': os.getenv('ANALYZE_BUILD_PARAMETERS', '').split(' '), 'force_debug': os.getenv('ANALYZE_BUILD_FORCE_DEBUG'), 'directory': execution.cwd, 'command': [execution.cmd[0], '-c'] + compilation.flags } # call static analyzer against the compilation for source in compilation.files: parameters.update({'file': source}) logging.debug('analyzer parameters %s', parameters) current = run(parameters) # display error message from the static analyzer if current is not None: for line in current['error_output']: logging.info(line.rstrip())
def test_source_file(self): def test(expected, cmd): self.assertEqual(expected, sut.split_command(cmd).files) test(['src.c'], ['clang', 'src.c']) test(['src.c'], ['clang', '-c', 'src.c']) test(['src.C'], ['clang', '-x', 'c', 'src.C']) test(['src.cpp'], ['clang++', '-c', 'src.cpp']) test(['s1.c', 's2.c'], ['clang', '-c', 's1.c', 's2.c']) test(['s1.c', 's2.c'], ['cc', 's1.c', 's2.c', '-ldep', '-o', 'a.out']) test(['src.c'], ['clang', '-c', '-I', './include', 'src.c']) test(['src.c'], ['clang', '-c', '-I', '/opt/me/include', 'src.c']) test(['src.c'], ['clang', '-c', '-D', 'config=file.c', 'src.c']) self.assertIsNone( sut.split_command(['cc', 'this.o', 'that.o', '-o', 'a.out'])) self.assertIsNone( sut.split_command(['cc', 'this.o', '-lthat', '-o', 'a.out']))
def test_source_file(self): def test(expected, cmd): self.assertEqual(expected, sut.split_command(cmd).files) test(['src.c'], ['clang', 'src.c']) test(['src.c'], ['clang', '-c', 'src.c']) test(['src.C'], ['clang', '-x', 'c', 'src.C']) test(['src.cpp'], ['clang++', '-c', 'src.cpp']) test(['s1.c', 's2.c'], ['clang', '-c', 's1.c', 's2.c']) test(['s1.c', 's2.c'], ['cc', 's1.c', 's2.c', '-ldep', '-o', 'a.out']) test(['src.c'], ['clang', '-c', '-I', './include', 'src.c']) test(['src.c'], ['clang', '-c', '-I', '/opt/me/include', 'src.c']) test(['src.c'], ['clang', '-c', '-D', 'config=file.c', 'src.c']) self.assertIsNone( sut.split_command(['cc', 'this.o', 'that.o', '-o', 'a.out'])) self.assertIsNone( sut.split_command(['cc', 'this.o', '-lthat', '-o', 'a.out']))
def test_action(self): self.assertIsNotNone(sut.split_command(['clang', 'source.c'])) self.assertIsNotNone(sut.split_command(['clang', '-c', 'source.c'])) self.assertIsNotNone(sut.split_command(['clang', '-c', 'source.c', '-MF', 'a.d'])) self.assertIsNone(sut.split_command(['clang', '-E', 'source.c'])) self.assertIsNone(sut.split_command(['clang', '-c', '-E', 'source.c'])) self.assertIsNone(sut.split_command(['clang', '-c', '-M', 'source.c'])) self.assertIsNone( sut.split_command(['clang', '-c', '-MM', 'source.c']))
def test_action(self): self.assertIsNotNone(sut.split_command(['clang', 'source.c'])) self.assertIsNotNone(sut.split_command(['clang', '-c', 'source.c'])) self.assertIsNotNone( sut.split_command(['clang', '-c', 'source.c', '-MF', 'a.d'])) self.assertIsNone(sut.split_command(['clang', '-E', 'source.c'])) self.assertIsNone(sut.split_command(['clang', '-c', '-E', 'source.c'])) self.assertIsNone(sut.split_command(['clang', '-c', '-M', 'source.c'])) self.assertIsNone(sut.split_command(['clang', '-c', '-MM', 'source.c']))
def analyze_build_wrapper(cplusplus): """ Entry point for `analyze-cc` and `analyze-c++` compiler wrappers. """ # initialize wrapper logging logging.basicConfig(format='analyze: %(levelname)s: %(message)s', level=os.getenv('ANALYZE_BUILD_VERBOSE', 'INFO')) # execute with real compiler compiler = os.getenv('ANALYZE_BUILD_CXX', 'c++') if cplusplus \ else os.getenv('ANALYZE_BUILD_CC', 'cc') compilation = [compiler] + sys.argv[1:] logging.info('execute compiler: %s', compilation) result = subprocess.call(compilation) # exit when it fails, ... if result or not os.getenv('ANALYZE_BUILD_CLANG'): return result # ... and run the analyzer if all went well. try: # check is it a compilation compilation = split_command(sys.argv) if compilation is None: return result # collect the needed parameters from environment, crash when missing parameters = { 'clang': os.getenv('ANALYZE_BUILD_CLANG'), 'output_dir': os.getenv('ANALYZE_BUILD_REPORT_DIR'), 'output_format': os.getenv('ANALYZE_BUILD_REPORT_FORMAT'), 'output_failures': os.getenv('ANALYZE_BUILD_REPORT_FAILURES'), 'direct_args': os.getenv('ANALYZE_BUILD_PARAMETERS', '').split(' '), 'force_debug': os.getenv('ANALYZE_BUILD_FORCE_DEBUG'), 'directory': os.getcwd(), 'command': [sys.argv[0], '-c'] + compilation.flags } # call static analyzer against the compilation for source in compilation.files: parameters.update({'file': source}) logging.debug('analyzer parameters %s', parameters) current = run(parameters) # display error message from the static analyzer if current is not None: for line in current['error_output']: logging.info(line.rstrip()) except Exception: logging.exception("run analyzer inside compiler wrapper failed.") return result
def analyze_build_wrapper(cplusplus): """ Entry point for `analyze-cc` and `analyze-c++` compiler wrappers. """ # initialize wrapper logging logging.basicConfig(format='analyze: %(levelname)s: %(message)s', level=os.getenv('ANALYZE_BUILD_VERBOSE', 'INFO')) # execute with real compiler compiler = os.getenv('ANALYZE_BUILD_CXX', 'c++') if cplusplus \ else os.getenv('ANALYZE_BUILD_CC', 'cc') compilation = [compiler] + sys.argv[1:] logging.info('execute compiler: %s', compilation) result = subprocess.call(compilation) # exit when it fails, ... if result or not os.getenv('ANALYZE_BUILD_CLANG'): return result # ... and run the analyzer if all went well. try: # check is it a compilation compilation = split_command(sys.argv) if compilation is None: return result # collect the needed parameters from environment, crash when missing parameters = { 'clang': os.getenv('ANALYZE_BUILD_CLANG'), 'output_dir': os.getenv('ANALYZE_BUILD_REPORT_DIR'), 'output_format': os.getenv('ANALYZE_BUILD_REPORT_FORMAT'), 'output_failures': os.getenv('ANALYZE_BUILD_REPORT_FAILURES'), 'direct_args': os.getenv('ANALYZE_BUILD_PARAMETERS', '').split(' '), 'force_debug': os.getenv('ANALYZE_BUILD_FORCE_DEBUG'), 'directory': os.getcwd(), 'command': [sys.argv[0], '-c'] + compilation.flags } # call static analyzer against the compilation for source in compilation.files: parameters.update({'file': source}) logging.debug('analyzer parameters %s', parameters) current = run(parameters) # display error message from the static analyzer if current is not None: for line in current['error_output']: logging.info(line.rstrip()) except Exception: logging.exception("run analyzer inside compiler wrapper failed.") return result
def format_entry(exec_trace): """ Generate the desired fields for compilation database entries. """ def abspath(cwd, name): """ Create normalized absolute path from input filename. """ fullname = name if os.path.isabs(name) else os.path.join(cwd, name) return os.path.normpath(fullname) 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': exec_trace['directory'], 'command': encode(command), 'file': abspath(exec_trace['directory'], source) }
def format_entry(exec_trace): """ Generate the desired fields for compilation database entries. """ def abspath(cwd, name): """ Create normalized absolute path from input filename. """ fullname = name if os.path.isabs(name) else os.path.join(cwd, name) return os.path.normpath(fullname) 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': exec_trace['directory'], 'command': encode(command), 'file': abspath(exec_trace['directory'], source) }
def test(expected, flags): command = ['clang', '-c', 'src.c'] + flags self.assertEqual(expected, sut.split_command(command).flags)
def test(expected, cmd): self.assertEqual(expected, sut.split_command(cmd).files)
def test(cmd): result = sut.split_command([cmd, '-c', 'src.c']) self.assertIsNotNone(result, "wrong input for test") return result.compiler == 'c++'
def test(expected, flags): command = ['clang', '-c', 'src.c'] + flags self.assertEqual(expected, sut.split_command(command).flags)
def test(expected, cmd): self.assertEqual(expected, sut.split_command(cmd).files)
def test(cmd): result = sut.split_command([cmd, '-c', 'src.c']) self.assertIsNotNone(result, "wrong input for test") return result.compiler == 'c++'