﻿# Анализ C и C\+\+ проектов на основе JSON Compilation Database

## Основные положения

Одним из способов представления структуры C\+\+ проекта является формат [JSON Compilation Database](https://clang.llvm.org/docs/JSONCompilationDatabase.html)\. Это файл, в котором записаны параметры компиляции, необходимые для создания объектных файлов из исходного кода проекта\. Обычно он имеет имя `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` можно узнать [тут](https://pvs-studio.ru/ru/docs/manual/6615/)\.

![Analyze_Cpp_Projects_with_JSON_Compilation_DB_ru/image1.png](https://import.viva64.com/docx/blog/Analyze_Cpp_Projects_with_JSON_Compilation_DB_ru/image1.png)

**Важно**: Проект должен успешно компилироваться и быть собран перед запуском анализа\.

Для запуска анализа и получения отчета необходимо выполнить две команды\.

Пример команд для Linux и macOS:

```cpp
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:

```cpp
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` для каждого пути:

```cpp
-e third-party -e tests
```

Анализ может быть распараллелен на несколько потоков с помощью флага `-j`\.

Более подробные инструкции по утилитам на Linux/macOS и Windows доступны [здесь](https://pvs-studio.ru/ru/docs/manual/0036/) и [здесь](https://pvs-studio.ru/ru/docs/manual/0038/)\.

## Генерация compile\_commands\.json

Если проект по умолчанию не содержит `compile_commands.json`, то можно воспользоваться одним из способов генерации такого файла\.

### CMake\-проект

Для генерации `compile_commands.json` необходимо добавить один флаг к вызову CMake:

```cpp
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=On .
```

Создание `compile_commands.json` происходит только в том случае, если генератор поддерживает JSON\-формат\. Такими генераторами являются, например, [Makefile](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html) и [Ninja](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html):

```cpp
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](https://ninja-build.org/) и в папке проекта есть файл `build.ninja`, то можно воспользоваться следующей командой для генерации `compile_commands.json`:

```cpp
ninja -t compdb > compile_commands.json
```

### QBS\-проект

Для генерации `compile_commands.json` в проекте, использующем Qt Build System, необходимо выполнить следующую команду:

```cpp
qbs generate --generator clangdb
```

### Использование утилиты Text Toolkit

Когда сборка проекта происходит с использованием GNU make, и получить `compile_commands.json` не получается, то следует попробовать инструмент [Text Toolkit](https://texttoolkit.com/compilation-database-generator)\. Сгенерировать базу данных компиляции можно либо через Web\-интерфейс \(только для Linux и macOS\), либо запустив скрипт на Python\. Для генерации online нужно:

1. выполнить команду `make -nwi > output.txt`;
1. скопировать содержимое файла `output.txt` в окно на сайте Text Toolkit;
1. нажать кнопку **Generate** для генерации базы данных компиляции в формате JSON;
1. скопировать полученные команды в файл `compile_commands.json`\.

Для генерации `compile_commands.json` с помощью Python, нужно клонировать [репозиторий](https://github.com/viva64/texttoolkit) с GitHub и выполнить следующую команду:

```cpp
ninja -nv | python path_to_texttoolkit_dir\cdg.py
```

### Использование утилиты Bear \(только для Linux и macOS\)

Утилита [Bear](https://github.com/rizsotto/Bear) \(версии 2\.4 или выше\) собирает параметры компиляции, перехватывая вызовы компилятора во время сборки проекта\. Для генерации `compile_commands.json` используется следующая команда

```cpp
bear -- <build_command>
```

В качестве `build_command` может быть любая команда для сборки: например, `make all` или `./build.sh`\.

### Использование утилиты intercept\-build \(только для Linux и macOS\)

Утилита `intercept-build` в [scan\-build](https://github.com/rizsotto/scan-build) аналогична утилите Bear\. Команда для генерации `compile_commands.json`:

```cpp
intercept-build <build_command>
```

### Использование утилиты Compilation Database Generator \(только для Linux и macOS\)

[Compile Database Generator](https://github.com/nickdiego/compiledb) \(compiledb\) – это утилита для генерации базы данных компиляции для Makefile\-based сборочных систем\. Пример генерации `compile_commands.json`:

```cpp
compiledb -n make
```

Флаг `-n` означает, что сборка не произойдет \(dry run\)\.

### Xcode\-проект \(только для macOS\)

С помощью утилиты [xcpretty](https://github.com/xcpretty/xcpretty) можно сгенерировать `compile_commands.json`\. Для этого необходимо выполнить следующую команду:

```cpp
xcodebuild [flags] | xcpretty -r json-compilation-database
```

### qmake\-проект

Для генерации `compile_commands.json` в проекте, использующем qmake, можно воспользоваться IDE Qt Creator версии 4\.8 и выше\. Для этого необходимо открыть в ней нужный проект и выбрать в строке меню пункт **Сборка \> Создать базу данных компиляции для %название\_проекта%** **\(Build \> Generate Compilation Database for %название\_проекта%\)**:

![Analyze_Cpp_Projects_with_JSON_Compilation_DB_ru/image2.png](https://import.viva64.com/docx/blog/Analyze_Cpp_Projects_with_JSON_Compilation_DB_ru/image2.png)

Сгенерированный файл `compile_commands.json` появится в директории сборки проекта\.

Примечание: данный способ получения `compile_commands.json` не предусматривает автоматизации и рекомендуется к использованию только в целях тестирования\.

### SCons\-проект

Для генерации `compile_commands.json` в проекте, использующем систему сборки [SCons](https://scons.org/), необходимо в файл [SConstruct](https://www.scons.org/doc/0.96/HTML/scons-user/x325.html) \(аналог [Makefile](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html) файла для утилиты [Make](https://www.gnu.org/software/make/)\) в директории проекта добавить следующие строчки:

```cpp
env = Environment(COMPILATIONDB_USE_ABSPATH=True)
env.Tool('compilation_db')
env.CompilationDatabase()
env.Program('programm_for_build.c')
```

После этого для создания файла `compile_commands.json` необходимо запустить в директории проекта \(где расположен файл [SConstruct](https://www.scons.org/doc/0.96/HTML/scons-user/x325.html)\) команду:

```cpp
scons -Q
```

Более подробное описание создания `compile_commands.json` в [SCons](https://scons.org/) находится в [соответствующем разделе документации SCons](https://scons.org/doc/production/HTML/scons-user/ch27.html)\.

### Bazel\-проект

Для генерации `compile_commands.json` в проекте, использующем систему сборки [Bazel](https://bazel.build/), используйте утилиту [bazel\-compile\-commands\-extractor](https://github.com/hedronvision/bazel-compile-commands-extractor) \(это утилита, которая не требует полной сборки проекта, и основана на [Action Graph Query \(aquery\)](https://bazel.build/query/aquery)\)\. Инструкция по её настройке расположена [здесь](https://github.com/hedronvision/bazel-compile-commands-extractor/blob/main/README.md)\.

Есть несколько других вариантов создания файла `compile_commands.json` для [Bazel](https://bazel.build/) проекта кроме [bazel\-compile\-commands\-extractor](https://github.com/hedronvision/bazel-compile-commands-extractor):

* [github\.com/google/kythe: tools/cpp/generate\_compilation\_database\.sh](https://github.com/kythe/kythe/blob/f215df07e18d1d99535a2839b197a81130fcfd90/tools/cpp/generate_compilation_database.sh) \- Использует experimental\_action\_listener для создания базы данных компиляции;
* [github\.com/grailbio/bazel\-compilation\-database](https://github.com/grailbio/bazel-compilation-database) – Быстрее, чем experimental\_action\_listener от Kythe, проще в настройке и не требует полной сборки, но менее точен\. Этот репозиторий заморожен с 17 марта 2024;
* [github\.com/stackb/bazel\-stack\-vscode\-cc](https://github.com/stackb/bazel-stack-vscode-cc) – [Расширение для VS Code](https://marketplace.visualstudio.com/items?itemName=StackBuild.bazel-stack-vscode-cc), которое добавляет команду для создания `compile_commands.json` для проекта\.