>
>
>
Нереальный baselining или доработки PVS…

Валерий Комаров
Статей: 12

Нереальный baselining или доработки PVS-Studio для Unreal Engine проектов

Статический анализатор PVS-Studio постоянно развивается: улучшаются различные механизмы, происходит интеграция с игровыми движками, IDE, CI/CD и другими системами и сервисами. Благодаря этому несколько лет назад появилась возможность использования PVS-Studio для анализа Unreal Engine проектов. Однако один из важных механизмов PVS-Studio – подавление сообщений анализатора (baselining, отключение выдачи предупреждений на существующий код) — не работал с UE-проектами. Почему он не был реализован сразу, и как в итоге была решена эта задача – читайте далее.

Baselining

Baselining в PVS-Studio — это механизм, позволяющий провести 'условную черту' для предупреждений анализатора, которые были выданы при анализе проекта. Анализатор использует эту 'черту' и показывает пользователю только те предупреждения, которые не отсечены данной 'чертой'.

Механизм подавления предупреждений реализован при помощи специальных suppress-файлов, в которых сохраняется информация о каждом подавленном сообщении анализатора. Эти файлы учитываются при последующих запусках анализатора, и подавленные предупреждения не попадают в результирующий отчёт.

На практике это позволяет получать в результате анализа только актуальные предупреждения, выданные для нового или изменённого кода. Особенно полезен данный механизм при внедрении PVS-Studio в существующий проект. В этом случае при первом анализе может быть выдано огромное количество предупреждений (обычно количество ошибок зависит от размера кодовой базы). Вместо того чтобы пытаться обработать их все сразу, вы можете просто подавить их. В результате при следующем анализе будут выданы только "свежие" предупреждения анализатора.

Вы всегда можете вернуться к подавленным сообщениям. В плагинах PVS-Studio для IDE также имеются возможности массового подавления и повторного отображения выбранных пользователем срабатываний анализатора.

Рекомендую также прочитать посвящённую описанной выше проблематике статью "Как внедрить статический анализатор кода в legacy проект и не демотивировать команду".

PVS-Studio и Unreal Engine

На данный момент имеется несколько вариантов проверки Unreal Engine проектов при помощи PVS-Studio. Одним из наиболее удобных для регулярного использования является плагин для Visual Studio. Он позволяет прямо в IDE:

  • запускать анализ UE-проекта;
  • выполнять навигацию по сообщениям анализатора;
  • обрабатывать сообщения анализатора, не отрываясь от написания кода.

От такого удобства UE-разработчика отделяет лишь пара несложных настроек:

  • в свойствах UE-проекта на вкладке NMake необходимо добавить флаг '-StaticAnalyzer=PVSStudio' в команду сборки и пересборки проекта. Важно: при добавлении этого флага не будет выполняться сборка/пересборка проекта, а будет запускаться анализ;
  • включить автоматическую загрузку отчёта анализатора для UE-проектов в плагине: PVS-Studio > Options > Specific Analyzer Settings > Save/Load (analyzer report) > AutoloadUnrealEngineLog.

После этого появится возможность анализа UE-проекта в Visual Studio:

  • для анализа всего проекта необходимо пересобрать проект. Результаты анализа будут сохранены в отчёт, путь до которого отобразится в окне вывода. Полученный отчёт автоматически будет загружен плагином PVS-Studio в таблицу сообщений анализатора;
  • для анализа файлов, которые изменились с последнего запуска анализатора, необходимо запустить сборку проекта (Build Solution). Однако стоит учесть, что файл не будет проанализирован, если произошло только изменение подключаемого .h файла.

Аналогичные возможности реализованы и в плагине PVS-Studio for Rider.

Так почему же при всех имеющихся возможностях PVS-Studio baselining сообщений анализатора для UE-проектов не был поддержан вплоть до релиза 7.16? Более того, в версии 7.16 доработки этого механизма были произведены только в command-line утилите PVS-Studio_Cmd.exe. И только в версии анализатора 7.17 baselining был реализован в плагинах для Visual Studio и JetBrains Rider.

Для ответа на этот вопрос необходимо поговорить об особенностях UE-проектов.

Особенности Unreal Engine проектов

На первый взгляд может показаться, что для поддержки baselining-а в UE-проектах было достаточно переиспользовать уже имеющийся механизм. Увы, но не всё так просто. Давайте рассмотрим механизмы, которые используются при анализе в PVS-Studio (не только для UE-проектов):

  • Перед анализом обычных С++ (не UE) проектов анализатор собирает информацию о проекте для наиболее полного и качественного анализа. Эта информация предоставляется сборочной системой. Например, MSBuild.
  • Для сборки UE-проектов используется специализированная сборочная система Unreal Build Tool (UBT), которая интегрируется поверх сборочной системы MSBuild, используемой в Visual Studio и JetBrains Rider.
  • Проекты-обёртки, созданные MSBuild-ом для Unreal Engine, не содержат всей необходимой информации для полного анализа.
  • Из-за предыдущего пункта пришлось интегрировать ядро C++ анализатора (PVS-Studio.exe) напрямую в UBT, чтобы получить всю необходимую информацию от неё для анализа проекта.
  • Механизм baselining-а завязан на MSBuild-проекты и утилиту PVS-Studio_Cmd.exe, а не на PVS-Studio.exe.
  • Плагины для IDE также завязаны на механизм baselining-а в PVS-Studio_Cmd.exe.

Таким образом, значительные отличия UE-проектов не позволили переиспользовать механизм baselining-а не только в консольной утилите, но и плагинах для IDE. Также интеграция С++ ядра (PVS-Studio.exe) в UBT наложила дополнительные ограничения на анализ UE-проектов из PVS-Studio_Cmd.exe. Данные ограничения коснулись и плагинов для IDE, так как они взаимодействуют с этой консольной утилитой.

Однако части ограничений для IDE удалось избежать, а именно:

  • флаг '-StaticAnalyzer=PVSStudio' позволил запускать анализ через PVS-Studio.exe из IDE плагинов при сборке/пересборке проекта;
  • подписка на событие сборки позволила автоматически загружать результаты анализа в IDE плагинах.

Посмотрим, какие изменения потребовалось внести в утилиту PVS-Studio_Cmd.exe, а также в код плагинов для Visual Studio и JetBrains Rider, чтобы поддержать работу механизма baselining-а с UE-проектами.

Доработки механизма baselining-а в PVS-Studio_Cmd.exe для Unreal Engine проектов

В релизе 7.16 был расширен механизм baselining-а в PVS-Studio_Cmd.exe. Во-первых, добавлена возможность фильтрации сообщений анализатора из отчёта (plog-файла) при помощи suppress-файла. Во-вторых, расширен режим подавления сообщений, который теперь можно использовать и с отчётами для UE-проектов. Эта доработка позволила использовать baselining в случаях, когда нет необходимости (или возможности) использования UI. Например, при интеграции PVS-Studio в различные CI/CD (Travis Ci, Circle CI, Gitlab, Azure).

Режим подавления сообщений напрямую из отчётов (plog-файлов) PVS-Studio уже существовал до описываемых доработок. Его суть в добавлении в suppress-файлы проекта/решения сообщений из отчётов анализатора без запуска анализа. Пример команды для подавления всех сообщений из отчёта:

PVS-Studio_Cmd.exe -t path/to/solution/file -a SuppressOnly -o path/to/report 
-u path/to/suppress/file

Активируется данный режим при помощи флага '-a SuppressOnly'. Также имеется возможность указать в необязательном аргументе '-u' путь до suppress-файла, не относящегося к проекту. В результате suppress-файл будет (пере)записан по этому пути, и в него так же, как и в suppress-файлы проекта/решения, будут добавлены все сообщения из отчёта, переданного в аргументе '-o'.

Кроме этого, был добавлен режим фильтрации сообщений из отчёта анализатора. Отличается он от режима SuppressOnly тем, что создаёт отфильтрованный отчёт, на основе переданного в аргументе '-o'. В отфильтрованном отчёте остаются только те предупреждения, которые не были найдены в suppress-файлах решения, проектов и suppress-файла из аргумента '-u'. Этот отчёт сохраняется в формате .plog с постфиксом '_filtered' рядом с отчётом из аргумента '-o'. Пример команды для фильтрации отчёта:

PVS-Studio_Cmd.exe -t path/to/solution/file -a FilterFromSuppress ^ 
                   -o path/to/report -u path/to/suppress/file

Аргументы, использованные для этого режима работы, аналогичны режиму SuppressOnly. Для его активации необходимо указать флаг '-a FilterFromSuppress'.

Оба описанных выше режима добавляют дополнительные возможности для работы с отчётами анализатора, причём не только для UE-проектов. Однако и здесь всё оказалось не так просто, потому что механизм baselining-а не может создавать и использовать suppress-файлы уровня UE-проектов. Учитывая эту особенность, для работы baselining-а приходится либо добавлять suppress-файл уровня решения, либо передавать его в аргументе '-u' при использовании режимов SuppressOnly или FilterFromSuppress.

Более подробно об этих и других особенностях работы механизма baselining-а для UE-проектов можно узнать из документации (раздел "Подавление предупреждений анализатора в Unreal Engine проектах").

Данные доработки позволяют использовать механизм подавления для UE-проектов на постоянной основе. Алгоритм использования механизма подавления для UE-проектов теперь выглядит так:

  • получить отчёт для UE-проекта одним из способов, описанным в документации (раздел "Проверка проектов");
  • используя PVS-Studio_Cmd.exe в режиме SuppressOnly, подавить все сообщения из полученного отчёта;
  • при следующем анализе отфильтровать сообщения из нового отчёта при помощи полученного ранее suppress-файла и режима FilterFromSuppress в PVS-Studio_Cmd.exe.

Использование механизма подавления сообщений анализатора для Unreal Engine проектов в плагинах Visual Studio и JetBrains Rider

В плагины для Visual Studio и JetBrains Rider возможность подавления сообщений PVS-Studio для UE-проектов была добавлена, начиная с версии 7.17. Первое, что необходимо сделать, – добавить suppress-файл уровня решения.

Microsoft Visual Studio

В Visual Studio для этого необходимо нажать правой кнопкой мыши на решении в контекстном меню Solution Explorer и создать новый suppress-файл при помощи Add > New Item... > PVS-Studio Suppression File:

Далее для подавления всех сообщений необходимо нажать кнопку 'Suppress All Messages' в окне с результатами анализа (это будет работать в случае, если для сборки UE-проектов задействована автоподгрузка логов):

Возможно подавлять только выбранные сообщения при помощи контекстного меню:

Просмотреть список всех suppress-файлов, которые используются для открытого в Visual Studio проекта/решения, возможно в специальном окне Extensions > PVS-Studio > Suppress Messages:

В этом окне имеется несколько кнопок:

  • Suppress All – подавляет все сообщения в окне результатов анализа;
  • Suppress Filtered – подавляет только отфильтрованные сообщения;
  • Un-suppress from Selected – позволяет удалять suppress-файлы, выбранные в окне. При этом все сообщения из удалённых suppress-файлов появятся в таблице с результатами анализа.

JetBrains Rider

Плагин для Rider является более молодым, а также имеет другой механизм взаимодействия с ядром анализатора PVS-Studio. Из-за этого в нём на данный момент (релиз 7.17) возможно только подавить все сообщения, полученные при анализе UE-проекта. Для этого в окне с результатами анализа, аналогично с Visual Studio, имеется кнопка 'Suppress All Messages':

Совместное использование новых возможностей baselining-а для UE-проектов в CI и Visual Studio

Учитывая все описанные выше доработки механизма baselining-а для UE-проектов, теперь можно быстро интегрировать PVS-Studio в новый проект, настроить его автоматическую ежедневную проверку в CI и одновременно постепенно разбираться с подавленными предупреждениями в Visual Studio.

Выглядеть это будет примерно так:

  • Интегрируя анализатор PVS-Studio в новый UE-проект, вы получите первый отчёт анализатора.
  • Далее вы подавите все найденные предупреждения через PVS-Studio_Cmd.exe в режиме SuppressOnly или через интерфейс плагинов PVS-Studio для IDE. При подавлении всех предупреждений в IDE необходимо добавить солюшен suppress-файл, в который будут записаны все подавленные предупреждения. В результате у вас появится suppress-файл, который далее будет использоваться для фильтрации предупреждений из отчётов анализатора.
  • Этот suppress-файл вы коммитите в систему контроля версий или сохраняете любым удобным вам способом.
  • Следующим шагом вы настраиваете задачу в CI, которая запускает анализ проекта при помощи PVS-Studio и фильтрует предупреждения из полученного отчёта. В фильтрации используется полученный ранее suppress-файл. Фильтрация происходит при помощи PVS-Studio_Cmd.exe в режиме FilterFromSuppress. В результате выполнения задачи вы получаете отчёт с предупреждениями только на новый или изменённый код.
  • После этого отчёт отправляется членам команды при помощи утилиты BlameNotifier.exe.
  • Каждый член команды исправляет код с учётом полученного отчёта.
  • Также постепенно ваша команда может разбираться с подавленными сообщениями. Для этого необходимо включить отображение подавленных предупреждений в Visual Studio. Обработав подавленное предупреждение, вы удаляете его из suppress-файла и коммитите изменение, чтобы это сообщение не мешало в дальнейшем при фильтрации следующих отчётов анализатора при помощи suppress-файла.
  • Кроме удаления возможно и добавление новых предупреждений в suppress-файл при помощи интерфейса плагина PVS-Studio для Visual Studio или через PVS-Studio_Cmd.exe в режиме SuppressOnly с указанием в аргументе '-u' пути до ранее созданного suppress-файла. Таким образом возможно откладывать обработку предупреждений (чем я злоупотреблять не советую), и при этом они не будут мешать в отчёте анализатора.

Заключение

Описанные доработки механизма baselining-а предупреждений повысили удобство использования статического анализатора PVS-Studio при работе с Unreal Engine проектами. Теперь будет намного проще внедрять анализатор в существующие проекты и использовать PVS-Studio на регулярной основе при работе с UE-проектами как в IDE, так и в CI/CD. Вы сами можете убедиться в этом, запросив триальную лицензию.