Анализ C и C++ проектов на основе JSON Compilation Database
- Основные положения
- Запуск анализа и получение отчета
- Генерация compile_commands.json
- CMake-проект
- Ninja-проект
- QBS-проект
- Использование утилиты Text Toolkit
- Использование утилиты Bear (только для Linux и macOS)
- Использование утилиты intercept-build (только для Linux и macOS)
- Использование утилиты Compilation Database Generator (только для Linux и macOS)
- Xcode-проект (только для macOS)
- qmake-проект
- SCons-проект
- Bazel-проект
Основные положения
Одним из способов представления структуры C++ проекта является формат JSON Compilation Database. Это файл, в котором записаны параметры компиляции, необходимые для создания объектных файлов из исходного кода проекта. Обычно он имеет имя 'compile_commands.json'. База данных компиляции в JSON-формате состоит из массива "командных объектов", где каждый объект определяет один из способов компиляции единицы трансляции в проекте.
Файл 'compile_commands.json' может использоваться для компиляции проекта или для анализа сторонними утилитами. C и C++ анализатор PVS-Studio тоже умеет работать с этим форматом.
Запуск анализа и получение отчета
Анализ проекта на Linux и macOS выполняется с помощью утилиты 'pvs-studio-analyzer'. Анализ на Windows – c помощью утилиты 'CompileCommandsAnalyzer.exe', которая обычно размещена в папке 'C:\Program Files (x86)\PVS-Studio'. Дополнительную информацию о CompileCommandsAnalyzer и pvs-studio-analyzer можно узнать тут.
Важно: Проект должен успешно компилироваться и быть собран перед запуском анализа.
Для запуска анализа и получения отчета необходимо выполнить две команды.
Пример команд для Linux и macOS:
pvs-studio-analyzer analyze -f path_to_compile_commands.json \
-o pvs.log -e excludepath -j<N>
plog-converter -a GA:1,2 -t tasklist -o project.tasks pvs.log
Пример команд для Windows:
CompilerCommandsAnalyzer.exe analyze
-f path_to_compile_commands.json ^
-o pvs.log -e exclude-path -j<N>
PlogConverter.exe -a GA:1,2 -t Plog -o path_to_output_directory ^
-n analysis_report pvs.log
Если анализ выполняется из директории с файлом 'compile_commands.json', флаг '-f' можно опустить.
Чтобы исключить из анализа директории с third-party библиотеками и/или тестами, можно использовать флаг '-e'. Если путей несколько, необходимо писать флаг '-e' для каждого пути:
-e third-party -e tests
Анализ может быть распараллелен на несколько потоков с помощью флага '-j'.
Более подробные инструкции по утилитам на Linux/macOS и Windows доступны здесь и здесь.
Генерация compile_commands.json
Если проект по умолчанию не содержит 'compile_commands.json', то можно воспользоваться одним из способов генерации такого файла.
CMake-проект
Для генерации 'compile_commands.json необходимо добавить один флаг к вызову CMake:
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=On .
Создание 'compile_commands.json' происходит только в том случае, если генератор поддерживает JSON-формат. Такими генераторами являются, например, Makefile и Ninja:
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=On -G Ninja .
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=On -G "NMake Makefiles" .
Для использования генератора Ninja под Windows часто требуется выполнять команды из командной строки разработчика от Visual Studio (например, 'x64 Native Tools Command Prompt for VS', и т.п.).
Ninja-проект
Если сборка проекта осуществляется напрямую с помощью Ninja и в папке проекта есть файл 'build.ninja', то можно воспользоваться следующей командой для генерации 'compile_commands.json':
ninja -t compdb > compile_commands.json
QBS-проект
Для генерации 'compile_commands.json' в проекте, использующем Qt Build System, необходимо выполнить следующую команду:
qbs generate --generator clangdb
Использование утилиты Text Toolkit
Когда сборка проекта происходит с использованием GNU make, и получить 'compile_commands.json' не получается, то следует попробовать инструмент Text Toolkit. Сгенерировать базу данных компиляции можно либо через Web-интерфейс (только для Linux и macOS), либо запустив скрипт на Python. Для генерации online нужно:
- выполнить команду 'make -nwi > output.txt';
- скопировать содержимое файла 'output.txt' в окно на сайте Text Toolkit;
- нажать кнопку 'Generate' для генерации базы данных компиляции в формате JSON;
- скопировать полученные команды в файл 'compile_commands.json'.
Для генерации 'compile_commands.json' с помощью Python, нужно клонировать репозиторий с GitHub и выполнить следующую команду:
ninja -nv | python path_to_texttoolkit_dir\cdg.py
Использование утилиты Bear (только для Linux и macOS)
Утилита Bear (версии 2.4 или выше) собирает параметры компиляции, перехватывая вызовы компилятора во время сборки проекта. Для генерации 'compile_commands.json' используется следующая команда
bear -- <build_command>
В качестве 'build_command' может быть любая команда для сборки, например 'make all' или './build.sh'.
Использование утилиты intercept-build (только для Linux и macOS)
Утилита 'intercept-build' в scan-build аналогична утилите Bear. Команда для генерации 'compile_commands.json':
intercept-build <build_command>
Использование утилиты Compilation Database Generator (только для Linux и macOS)
Compile Database Generator (compiledb) – это утилита для генерации базы данных компиляции для Makefile-based сборочных систем. Пример генерации 'compile_commands.json':
compiledb -n make
Флаг '-n' означает, что сборка не произойдет (dry run).
Xcode-проект (только для macOS)
С помощью утилиты xcpretty можно сгенерировать 'compile_commands.json'. Для этого необходимо выполнить следующую команду:
xcodebuild [flags] | xcpretty -r json-compilation-database
qmake-проект
Для генерации 'compile_commands.json' в проекте, использующем qmake, можно воспользоваться IDE QtCreator версии 4.8 и выше. Для этого необходимо открыть в ней нужный проект и выбрать в строке меню пункт 'Сборка -> Создать базу данных компиляции для %название_проекта%' ('Build->Generate Compilation Database for %название_проекта%'):
Сгенерированный файл 'compile_commands.json' появится в директории сборки проекта.
Примечание: данный способ получения 'compile_commands.json' не предусматривает автоматизации и рекомендуется к использованию только в целях тестирования.
SCons-проект
Для генерации 'compile_commands.json' в проекте, использующем систему сборки SCons, необходимо в файл SConstruct (аналог Makefile файла для утилиты Make) в директории проекта добавить следующие строчки:
env = Environment(COMPILATIONDB_USE_ABSPATH=True)
env.Tool('compilation_db')
env.CompilationDatabase()
env.Program('programm_for_build.c')
После этого для создания файла 'compile_commands.json' необходимо запустить в директории проекта (где расположен файл SConstruct) команду:
scons -Q
Более подробное описание создания 'compile_commands.json' в SCons находится в соответствующем разделе документации SCons.
Bazel-проект
Для генерации 'compile_commands.json' в проекте, использующем систему сборки Bazel, используйте утилиту bazel-compile-commands-extractor (это утилита, которая не требует полной сборки проекта, и основана на Action Graph Query (aquery)). Инструкция по её настройке расположена здесь.
Есть несколько других вариантов создания файла 'compile_commands.json' для Bazel проекта кроме bazel-compile-commands-extractor:
- github.com/google/kythe: tools/cpp/generate_compilation_database.sh - Использует experimental_action_listener для создания базы данных компиляции;
- github.com/grailbio/bazel-compilation-database – Быстрее, чем experimental_action_listener от Kythe, проще в настройке и не требует полной сборки, но менее точен. Этот репозиторий заморожен с 17 марта 2024;
- github.com/stackb/bazel-stack-vscode-cc – Расширение для VS Code, которое добавляет команду для создания 'compile_commands.json' для проекта.