def test_link_only_multiple_files(self): """ Should be link if only object files are in the command. """ build_cmd = "g++ -o fubar foo.o main.o bar.o -lm" res = option_parser.parse_options(build_cmd) print(res) self.assertEquals(ActionType.LINK, res.action)
def test_build_multiplefiles(self): """ Test the build command of multiple files. """ source_files = ["lib.cpp", "main.cpp"] build_cmd = "g++ -o main " + ' '.join(source_files) res = option_parser.parse_options(build_cmd) print(res) self.assertTrue(set(source_files) == set(res.files)) self.assertEquals(ActionType.COMPILE, res.action)
def test_compile_onefile(self): """ Test the compiler command of one file. """ source_files = ["main.cpp"] build_cmd = "g++ -c " + ' '.join(source_files) res = option_parser.parse_options(build_cmd) print(res) self.assertTrue(set(source_files) == set(res.files)) self.assertEquals(ActionType.COMPILE, res.action)
def test_build_onefile(self): """ Test the build command of a simple file. """ source_files = ["main.cpp"] build_cmd = "g++ -o main " + ' '.join(source_files) res = option_parser.parse_options(build_cmd) print(res) self.assertTrue(set(source_files) == set(res.files)) self.assertTrue(ActionType.COMPILE, res.action) self.assertEquals(0, len(res.compile_opts))
def test_preprocess_onefile(self): """ Test the preprocess command of one file. """ source_files = ["main.c"] build_cmd = "gcc -E " + ' '.join(source_files) print(build_cmd) res = option_parser.parse_options(build_cmd) print(res) self.assertTrue(set(source_files) == set(res.files)) self.assertEqual(ActionType.PREPROCESS, res.action)
def parse_compile_commands_json(logfile): import json actions = [] filtered_build_actions = {} logfile.seek(0) data = json.load(logfile) counter = 0 for entry in data: sourcefile = entry['file'] lang = option_parser.get_language(sourcefile[sourcefile.rfind('.'):]) if not lang: continue action = build_action.BuildAction(counter) command = entry['command'] results = option_parser.parse_options(command) action.original_command = command action.analyzer_options = results.compile_opts action.lang = results.lang action.target = results.arch if results.action == option_parser.ActionType.COMPILE or \ results.action == option_parser.ActionType.LINK: action.skip = False # TODO: check arch action.directory = entry['directory'] action.sources = sourcefile action.lang = lang # filter out duplicate compilation commands unique_key = action.cmp_key if filtered_build_actions.get(unique_key) is None: filtered_build_actions[unique_key] = action del action counter += 1 for ba_hash, ba in filtered_build_actions.iteritems(): actions.append(ba) return actions
def test_compile_optimized(self): """ Test if the compilation arguments is detected correctly from the command line. """ source_files = ["main.cpp"] compiler_options = ["-O3"] build_cmd = "g++ -c " + \ ' '.join(compiler_options) + ' ' + \ ' '.join(source_files) res = option_parser.parse_options(build_cmd) print(res) self.assertTrue(set(compiler_options) == set(res.compile_opts)) self.assertEqual(ActionType.COMPILE, res.action)
def test_compile_lang(self): """ Test if the compilation language is detected correctly from the command line. """ source_files = ["main.c"] lang = 'c' build_cmd = "gcc -c -x " + lang + " " + ' '.join(source_files) print(build_cmd) res = option_parser.parse_options(build_cmd) print(res) self.assertTrue(set(source_files) == set(res.files)) self.assertEqual(lang, res.lang) self.assertEqual(ActionType.COMPILE, res.action)
def test_compile_arch(self): """ Test if the compilation architecture is detected correctly from the command line. """ source_files = ["main.c"] arch = 'x86_64' build_cmd = "gcc -c -arch " + arch + " " + ' '.join(source_files) print(build_cmd) res = option_parser.parse_options(build_cmd) print(res) self.assertTrue(set(source_files) == set(res.files)) self.assertEqual(arch, res.arch) self.assertEqual(ActionType.COMPILE, res.action)
def test_link_with_include_paths(self): """ Should be link if only object files are in the command. """ object_files = ["foo.o", "main.o", "bar.o"] compiler_options = [ "-sysroot", "/home/sysroot", "-isysroot", "/home/isysroot", "-I/home/test" ] linker_options = ["-L/home/test_lib", "-lm"] build_cmd = "g++ -o fubar " + \ ' '.join(compiler_options) + ' ' + \ ' '.join(linker_options) + ' ' + \ ' '.join(object_files) res = option_parser.parse_options(build_cmd) print(res) self.assertTrue(set(object_files) == set(res.files)) self.assertTrue(set(compiler_options) == set(res.compile_opts)) self.assertTrue(set(linker_options) == set(res.link_opts)) self.assertEqual(ActionType.LINK, res.action)
def test_compile_with_include_paths(self): """ sysroot should be detected as compiler option because it is needed for the analyzer too to search for headers. """ source_files = ["main.cpp", "test.cpp"] compiler_options = ["-sysroot", "/home/sysroot", "-isysroot", "/home/isysroot", "-I/home/test"] linker_options = ["-L/home/test_lib", "-lm"] build_cmd = "g++ -o myapp " + \ ' '.join(compiler_options) + ' ' + \ ' '.join(linker_options) + ' ' + \ ' '.join(source_files) res = option_parser.parse_options(build_cmd) print(res) self.assertTrue(set(source_files) == set(res.files)) self.assertTrue(set(compiler_options) == set(res.compile_opts)) self.assertTrue(set(linker_options) == set(res.link_opts)) self.assertEqual(ActionType.COMPILE, res.action)
def test_compile_with_include_paths(self): """ sysroot should be detected as compiler option because it is needed for the analyzer too to search for headers. """ source_files = ["main.cpp", "test.cpp"] compiler_options = [ "-sysroot", "/home/sysroot", "-isysroot", "/home/isysroot", "-I/home/test" ] linker_options = ["-L/home/test_lib", "-lm"] build_cmd = "g++ -o myapp " + \ ' '.join(compiler_options) + ' ' + \ ' '.join(linker_options) + ' ' + \ ' '.join(source_files) res = option_parser.parse_options(build_cmd) print(res) self.assertTrue(set(source_files) == set(res.files)) self.assertTrue(set(compiler_options) == set(res.compile_opts)) self.assertTrue(set(linker_options) == set(res.link_opts)) self.assertEqual(ActionType.COMPILE, res.action)
def test_link_with_include_paths(self): """ Should be link if only object files are in the command. """ object_files = ["foo.o", "main.o", "bar.o"] compiler_options = ["-sysroot", "/home/sysroot", "-isysroot", "/home/isysroot", "-I/home/test"] linker_options = ["-L/home/test_lib", "-lm"] build_cmd = "g++ -o fubar " + \ ' '.join(compiler_options) + ' ' + \ ' '.join(linker_options) + ' ' + \ ' '.join(object_files) res = option_parser.parse_options(build_cmd) print(res) self.assertTrue(set(object_files) == set(res.files)) self.assertTrue(set(compiler_options) == set(res.compile_opts)) self.assertTrue(set(linker_options) == set(res.link_opts)) self.assertEqual(ActionType.LINK, res.action)
def parse_compile_commands_json(logfile, add_compiler_defaults=False): import json LOG.debug('parse_compile_commands_json: ' + str(add_compiler_defaults)) actions = [] filtered_build_actions = {} logfile.seek(0) data = json.load(logfile) compiler_defines = {} compiler_includes = {} counter = 0 for entry in data: sourcefile = entry['file'] lang = option_parser.get_language(sourcefile[sourcefile.rfind('.'):]) if not lang: continue action = build_action.BuildAction(counter) command = entry['command'] results = option_parser.parse_options(command) action.original_command = command action.analyzer_options = results.compile_opts action.lang = results.lang action.target = results.arch # store the compiler built in include paths # and defines if add_compiler_defaults and results.compiler: if not (results.compiler in compiler_defines): compiler_defines[results.compiler] = \ get_compiler_defines(results.compiler) compiler_includes[results.compiler] = \ get_compiler_includes(results.compiler) action.compiler_defines = compiler_defines[results.compiler] action.compiler_includes = compiler_includes[results.compiler] if results.action == option_parser.ActionType.COMPILE or \ results.action == option_parser.ActionType.LINK: action.skip = False # TODO: check arch. action.directory = entry['directory'] action.sources = sourcefile # Filter out duplicate compilation commands. unique_key = action.cmp_key if filtered_build_actions.get(unique_key) is None: filtered_build_actions[unique_key] = action del action counter += 1 for ba_hash, ba in filtered_build_actions.items(): actions.append(ba) return actions