diff options
author | Philip Withnall <philip@tecnocode.co.uk> | 2019-12-20 16:07:58 +0000 |
---|---|---|
committer | Philip Withnall <philip@tecnocode.co.uk> | 2019-12-20 16:07:58 +0000 |
commit | 9cff7877516a42d26ba890e3c42acb24458713f4 (patch) | |
tree | 12e7eb30b048cb6f6f501b1acb9cce1923582e63 | |
parent | 53dfdbe970966966b208a034c91f9fb43bf7596b (diff) | |
parent | 3c8c729c4c6d19a44e7b39c49d79dc5aafd7b9b6 (diff) |
Merge branch '39-compile-commands-json' into 'master'
Add a script for processing compile_commands.json
Closes #39
See merge request tartan/tartan!5
-rw-r--r-- | Makefile.am | 1 | ||||
-rw-r--r-- | clang-plugin/plugin.cpp | 21 | ||||
-rwxr-xr-x | scripts/tartan | 6 | ||||
-rwxr-xr-x | scripts/tartan-json | 67 |
4 files changed, 87 insertions, 8 deletions
diff --git a/Makefile.am b/Makefile.am index 764ca8c..319e3d7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -74,6 +74,7 @@ clang_plugin_libtartan_la_LDFLAGS = \ dist_bin_SCRIPTS = \ scripts/tartan \ scripts/tartan-build \ + scripts/tartan-json \ $(NULL) # Code coverage diff --git a/clang-plugin/plugin.cpp b/clang-plugin/plugin.cpp index 1a94e0f..5e49c71 100644 --- a/clang-plugin/plugin.cpp +++ b/clang-plugin/plugin.cpp @@ -204,15 +204,16 @@ private: } while ((typelib_filename = g_dir_read_name (dir)) != NULL) { - /* Load the typelib. Ignore failure. */ - - std::string _typelib_filename (typelib_filename); - std::string::size_type last_dot = _typelib_filename.find_last_of ("."); - if (last_dot == std::string::npos) { + if (!g_str_has_suffix (typelib_filename, ".typelib")) { /* No ‘.typelib’ suffix — ignore. */ continue; } + /* Load the typelib. Ignore failure. */ + std::string _typelib_filename (typelib_filename); + std::string::size_type last_dot = _typelib_filename.find_last_of ("."); + g_assert (last_dot != std::string::npos); + std::string gi_namespace_and_version = _typelib_filename.substr (0, last_dot); this->_load_typelib (CI, gi_namespace_and_version); } @@ -230,9 +231,6 @@ protected: ParseArgs (const CompilerInstance &CI, const std::vector<std::string>& args) { - /* Load all typelibs. */ - this->_load_gi_repositories (CI); - /* Enable the default set of checkers. */ for (std::vector<std::string>::const_iterator it = args.begin(); it != args.end (); ++it) { @@ -254,9 +252,14 @@ protected: } else if (arg == "--disable-checker") { const std::string checker = *(++it); this->_disabled_checkers.get ()->insert (std::string (checker)); + } else if (arg == "--typelib-path") { + g_irepository_prepend_search_path ((++it)->c_str ()); } } + /* Load all typelibs. */ + this->_load_gi_repositories (CI); + /* Listen to the V environment variable (as standard in automake) too. */ const char *v_value = getenv ("V"); if (v_value != NULL && strcmp (v_value, "0") == 0) { @@ -308,6 +311,8 @@ protected: " Disable the given Tartan checker, which may be " "‘all’. All checkers are\n" " enabled by default.\n" + " --typelib-path [path]\n" + " Add the given path to the search path for typelibs.\n" " --quiet\n" " Disable all plugin output except code " "diagnostics (remarks,\n" diff --git a/scripts/tartan b/scripts/tartan index 3dcf012..ba6cbcf 100755 --- a/scripts/tartan +++ b/scripts/tartan @@ -149,6 +149,12 @@ if [ "$escape_plugin_flags" = "1" ]; then _add_plugin+=( "-Xanalyzer" "$arg" ) done add_plugin=( "${_add_plugin[@]}" ) + + _plugin_options=() + for arg in "${plugin_options[@]}"; do + _plugin_options+=( "-Xanalyzer" "$arg" ) + done + plugin_options=( "${_plugin_options[@]}") fi if [ "$include_plugin_flags" = "1" ]; then diff --git a/scripts/tartan-json b/scripts/tartan-json new file mode 100755 index 0000000..560413a --- /dev/null +++ b/scripts/tartan-json @@ -0,0 +1,67 @@ +#!/usr/bin/env python3 +# coding: utf8 +# +# This file is part of Tartan. +# Copyright © 2019 Philip Chimento +# +# Tartan is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Tartan is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Tartan. If not, see <http://www.gnu.org/licenses/>. + +# Use this script to analyze a whole project by passing it the compilation +# database file generated by Meson or CMake. An example with Meson would be: +# +# $ meson _build +# $ tartan-json _build/compile_commands.json + +import argparse +import json +import os +import shlex +import subprocess +import sys + +parser = argparse.ArgumentParser( + description='''Run the Tartan analyzer on a whole compilation database, in +the compile_commands.json format such as generated by Meson or CMake.''') +parser.add_argument('json', type=argparse.FileType('r'), metavar='FILE', + help='path to compile_commands.json') +parser.add_argument('-q', '--quiet', action='store_true', + help="don't print progress messages") +parser.add_argument('tartan_options', nargs=argparse.REMAINDER, metavar='...', + help='extra options to pass on to Tartan') + +args = parser.parse_args() + +compile_db = json.load(args.json) +had_error = False + +for index, entry in enumerate(compile_db): + if not args.quiet: + full_path = os.path.normpath(os.path.join(entry['directory'], + entry['file'])) + print('[{}/{}] Processing {}'.format(index + 1, len(compile_db), + full_path)) + + new_env = dict(os.environ) + existing_tartan_options = new_env.get('TARTAN_OPTIONS', '') + new_env['TARTAN_OPTIONS'] = (existing_tartan_options + ' ' + + ' '.join(args.tartan_options)) + # -Wno-unused-command-line-argument is because linker arguments will be + # ignored and produce a warning with --analyze. + invocation = (['tartan', '--analyze', '-Wno-unused-command-line-argument'] + + shlex.split(entry['command'])) + result = subprocess.run(invocation, cwd=entry['directory'], env=new_env) + if result.returncode != 0: + had_error = True + +sys.exit(1 if had_error else 0) |