Анализ 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 помощью утилиты CompilerCommandsAnalyzer.exe, которая обычно размещена в папке C:\Program Files (x86)\PVS-Studio. Дополнительную информацию о CompilerCommandsAnalyzer и 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 Qt Creator версии 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для проекта.