def format_entry(entry): """ 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', 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('formated as: %s', command) yield { 'directory': entry['directory'], 'command': encode(command), 'file': abspath(entry['directory'], source) }
def format_entry(entry): """ 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', 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('formated as: %s', command) yield { 'directory': entry['directory'], 'command': encode(command), 'file': abspath(entry['directory'], source) }
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: # collect the needed parameters from environment, crash when missing consts = { '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_analyze_debug_code': os.getenv('ANALYZE_BUILD_FORCE_ANALYZE_DEBUG_CODE'), 'directory': os.getcwd(), } # get relevant parameters from command line arguments args = classify_parameters(sys.argv) filenames = args.pop('files', []) for filename in (name for name in filenames if classify_source(name)): parameters = dict(args, file=filename, **consts) logging.debug('analyzer parameters %s', parameters) current = action_check(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 0
def run(opts): """ Entry point to run (or not) static analyzer against a single entry of the compilation database. This complex task is decomposed into smaller methods which are calling each other in chain. If the analyzis is not possibe the given method just return and break the chain. """ try: command = opts.pop('command') logging.debug("Run analyzer against '%s'", command) opts.update(classify_parameters(shlex.split(command))) return action_check(opts) except Exception: logging.error("Problem occured during analyzis.", exc_info=1) return None
def format_entry(entry): """ Generate the desired fields for compilation database entries. """ def join_command(args): return ' '.join([shell_escape(arg) for arg in args]) 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) atoms = classify_parameters(entry['command']) return ({ 'directory': entry['directory'], 'command': join_command(entry['command']), 'file': abspath(entry['directory'], filename) } for filename in atoms.get('files', []) if is_source_file(filename) and atoms['action'] <= Action.Compile)
def run(opts): """ Entry point to run (or not) static analyzer against a single entry of the compilation database. This complex task is decomposed into smaller methods which are calling each other in chain. If the analyzis is not possibe the given method just return and break the chain. The passed parameter is a python dictionary. Each method first check that the needed parameters received. (This is done by the 'require' decorator. It's like an 'assert' to check the contract between the caller and the called method.) """ try: command = opts.pop('command') logging.debug("Run analyzer against '%s'", command) opts.update(classify_parameters(decode(command))) return action_check(opts) except Exception: logging.error("Problem occured during analyzis.", exc_info=1) return None
def wrapper(cplusplus): """ This method implements basic compiler wrapper functionality. """ # initialize wrapper logging logging.basicConfig(format='analyze: %(levelname)s: %(message)s', level=os.getenv('BUILD_ANALYZE_VERBOSE', 'INFO')) # execute with real compiler compiler = os.getenv('BUILD_ANALYZE_CXX', 'c++') if cplusplus \ else os.getenv('BUILD_ANALYZE_CC', 'cc') compilation = [compiler] + sys.argv[1:] logging.info('execute compiler: %s', compilation) result = subprocess.call(compilation) try: # collect the needed parameters from environment, crash when missing consts = { 'clang': os.getenv('BUILD_ANALYZE_CLANG'), 'output_dir': os.getenv('BUILD_ANALYZE_REPORT_DIR'), 'output_format': os.getenv('BUILD_ANALYZE_REPORT_FORMAT'), 'report_failures': os.getenv('BUILD_ANALYZE_REPORT_FAILURES'), 'direct_args': os.getenv('BUILD_ANALYZE_PARAMETERS', '').split(' '), 'directory': os.getcwd(), } # get relevant parameters from command line arguments args = classify_parameters(sys.argv) filenames = args.pop('files', []) for filename in (name for name in filenames if is_source_file(name)): parameters = dict(args, file=filename, **consts) logging.debug('analyzer parameters %s', parameters) current = action_check(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 compiler exit code return result
def test(cmd): opts = sut.classify_parameters(cmd) return opts.get('compile_options', [])
def test(cmd): opts = sut.classify_parameters(cmd) return opts.get('files', [])
def test(cmd): opts = sut.classify_parameters(cmd) return opts.get('archs_seen', [])
def test(cmd): opts = sut.classify_parameters(cmd) return opts.get('output')
def test(cmd): opts = sut.classify_parameters(cmd) return opts.get('language')
def test(expected, cmd): opts = sut.classify_parameters(cmd) self.assertEqual(expected, opts['action'])
def test(flags): cmd = ['clang', 'src.o'] opts = sut.classify_parameters(cmd + flags) self.assertEqual(['src.o'], opts.get('compile_options'))