Данная статья посвящена особенностям проверки Unreal Engine проектов с помощью статического анализатора PVS-Studio на операционной системе Windows: как установить анализатор, как проверить проект, где и как посмотреть отчёт об ошибках.
Наиболее актуальную информацию о том, как проанализировать Unreal Engine проект с помощью PVS-Studio, вы можете найти по данной ссылке.
Неотъемлемой частью цикла наших статей являются темы, так или иначе связанные с игровой индустрией. Проверить физический движок, используемый в AAA-играх - пожалуйста, составить топ ошибок в игровой индустрии – на здоровье, найти баги в одном из самых популярных игровых движков - Unreal Engine (UE) – легко. При разработке игр, как и при написании любых других приложений, важно качество кода. Ошибки лучше всего находить как можно раньше и желательно делать это автоматизировано – именно здесь на помощь программистам приходят статические анализаторы кода.
В данной статье я попытаюсь кратко рассказать о том, как вы можете использовать статический анализатор PVS-Studio для анализа проектов, создаваемых в UE. PVS-Studio поможет сделать код ваших проектов лучше, находя в нём ошибки, тем самым позволяя вам сократить время, затраченное на code review.
Обратите внимание, что данная статья является дополнением к существующей документации об анализе UE проектов и не служит цели заменить её, во многом заимствуя содержимое документации.
Самый лёгкий способ установить анализатор PVS-Studio - это скачать его установочный файл. Для того чтобы иметь возможность анализировать проекты, создаваемые в UE, при установке PVS-Studio вам необходимо выбрать следующие компоненты: "C and С++ Compiler Monitoring" и "Integration with Microsoft Visual Studio (Visual C++/C#)". Последний пункт отвечает за интеграцию PVS-Studio плагина в IDE Visual Studio, через который удобно работать с журналом ошибок и с общими настройками самого анализатора.
Для полноценной работы с PVS-Studio необходимо ввести лицензию. Это можно сделать, открыв IDE Visual Studio (VS) и введя лицензию в окне 'PVS-Studio|Options...|Registration'. В VS 2019 меню PVS-Studio было убрано в меню 'Extensions', поэтому путь до окна ввода лицензии будет выглядеть следующим образом: 'Extensions'|'PVS-Studio|Options...|Registration'. Лицензию можно получить на нашем сайте.
Для сборки UE проектов применяется не стандартная сборочная система, используемая в VS - MSBuild, а собственная программа от Epic Games, отвечающая за сборку, - UnrealBuildTool (UBT). В связи с этим плагин PVS-Studio не в состоянии осуществить обычный сценарий проверки C++/C# проектов, создаваемых в VS: "PVS-Studio -> Check -> Current Project". Для обхода этого ограничения существует несколько решений.
Первый и самый простой способ проверки UE проекта можно осуществить с помощью программы C and С++ Compiler Monitoring (имеет название Standalone.exe), которая располагается в установочной директории PVS-Studio. Принцип её работы заключается в том, что она отслеживает запуски процессов, соответствующих целевому компилятору (cl.exe в данном случае) и собирает всю необходимую информацию для препроцессирования и дальнейшего анализа исходных файлов. После того как вы открыли C and С++ Compiler Monitoring, воспользуйтесь меню "Tools" и выберете опцию "Analyze Your Files (C and C++)...". Нажмите кнопку "Start Monitoring" и вы увидите, как в левом нижнем углу экрана появится окно, информирующее о том, что происходит отслеживание вызовов компиляторов:
Далее выполните сборку вашего UE проекта и нажмите клавишу "Stop Monitoring".
После этого начнётся анализ исходных файлов, которые были подвергнуты компиляции. Отчёт о найденных предупреждениях будет выведен в окно "Analyzer Output" программы C and С++ Compiler Monitoring.
Аналогичное отслеживание вызовов компилятора и последующий анализ полученных файлов можно осуществить и с помощью консольной программы CLMonitor.exe, расположенной в той же папке, куда была выполнена установка PVS-Studio. У CLMonitor.exe есть два режима работы: режим сервера (когда выполняется отслеживание запусков процессов, соответствующих целевому компилятору) и режим клиента (когда происходит анализ исходных файлов, полученных на этапе отслеживания, и формируется отчёт о результатах анализа). Для того чтобы запустить CLMonitor.exe в режиме сервера, выполните следующую команду:
CLMonitor.exe monitor
После этого осуществите сборку вашего UE проекта и выполните приведённую ниже команду:
CLMonitor.exe analyze -l "c:\ptest.plog"
Команда "analyze" запускает CLMonitor.exe в режиме клиента и закрывает запущенный экземпляр этой программы, работающий в режиме сервера. После выполнения этой команды CLMonitor.exe начнёт выполнять анализ файлов. Параметром для опции "- l" выступает путь до файла, в который будут записаны результаты работы анализатора.
Альтернативным и более удобным подходом к выполнению анализа UE проектов является прямая интеграция со сборочной системой UBT. Для этого в VS откройте окно свойств вашего UE проекта и в списке "Configuration Properties" выберите "NMake". Добавьте флаг -StaticAnalyzer=PVSStudio в текстовое поле свойства "Build Command Line". В качестве примера значение поля "Build Command Line" может выглядеть так:
C:\Program Files\Epic Games\UE_4.22\Engine\Build\BatchFiles\Build.bat"
MyProject Win64 DebugGame
-Project="$(SolutionDir)$(ProjectName).uproject"
-WaitMutex -FromMsBuild -StaticAnalyzer=PVSStudio
Стоит учитывать, что теперь при выполнении сборки проекта, будет произведён только анализ, но не будет осуществлена сама сборка. Сценарий, при котором выполняется и сборка, и последующий анализ будет описан ниже. Также необходимо понимать, что будет произведён анализ только тех исходных файлов, которые были изменены с момента выполнения последней сборки проекта (если был изменён какой-либо подключаемый .h файл, то это не будет являться причиной для выполнения анализа при следующей сборке). Для того, чтобы выполнить полный анализ, вам необходимо добавить всё тот же флаг в текстовое поле свойства "Rebuild All Command Line". Теперь при выполнении пересборки проекта вы получите результат анализа всего проекта.
Теперь давайте рассмотрим ещё один сценарий интеграции анализатора PVS-Studio в сборочную систему UBT, при котором анализ запускается сразу после выполнения сборки/пересборки проекта, то есть на выходе вы получаете и собранный проект, и файл с результатами анализа. Как вы могли заметить, поле Build Command Line содержит путь до пакетного файла Build.bat, который в свою очередь содержит инструкции для запуска UBT с нужными аргументами. Build.bat запускается в самом начале сборки.
Идея заключается в том, чтобы изменить пакетный файл таким образом, чтобы он сначала запускал UBT со стандартными аргументами сборки, а при условии успешного завершения этапа сборки опять запустить всё тот же UBT, но уже с дополнительным флагом -StaticAnalyzer=PVSStudio. Для реализации вышеописанного сценария вы можете изменить пакетный файл Build.bat (а лучше всего создать его копию с названием, к примеру, BuildAndAnalyze.bat) следующим образом. Сразу после команды popd вставьте следующие инструкции:
SET "UBT_ERR_LEVEL=!ERRORLEVEL!"
SET "NEED_TO_PERFORM_ANALYSIS"
IF "!UBT_ERR_LEVEL!"=="0" (
SET "NEED_TO_PERFORM_ANALYSIS=TRUE"
)
IF "!UBT_ERR_LEVEL!"=="2" (
SET "NEED_TO_PERFORM_ANALYSIS=TRUE"
)
IF DEFINED NEED_TO_PERFORM_ANALYSIS (
pushd "%~dp0\..\..\Source"
ECHO Running static analysis
..\..\Engine\Binaries\DotNET\UnrealBuildTool.exe %*
-StaticAnalyzer=PVSStudio -DEPLOY
popd
SET "UBT_ERR_LEVEL=!ERRORLEVEL!"
)
Если ранее был установлен флаг -StaticAnalyzer=PVSStudio в поле Build Command Line в настройках проекта 'Properties|Configuration Properties|NMake', то его необходимо удалить.
Проблема такого подхода заключается в том, что будут анализироваться только те файлы, которые были скомпилированы на этапе сборки. То есть вы не получите файл отчёта с полной проверкой вашего проекта. К тому же какие-либо изменения, внесённые в подключаемые заголовочные .h файлы, также не будут учитываться. Следовательно, мы не можем назвать такой анализ инкрементальным, так как изменения в заголовочных файлах не приведут к выполнению анализа при осуществлении новой сборки. В этом случае вы можете выполнять пересборку проекта, получая результат анализа для всего проекта. Однако осуществление полной сборки может занимать длительное время, поэтому вы имеете возможность пойти по следующему сценарию: осуществить сборку, удалить кэш-файл - ActionHistory.bin, запустить сборку с флагом -StaticAnalyzer=PVSStudio, восстановить кэш-файл. В файле ActionHistory.bin хранится необходимая информация для выполнения инкрементальных сборок, а также история запуска анализатора для проверяемых файлов.
На первый взгляд этот сценарий может казаться не самым простым, поэтому мы предоставим полный набор инструкций того, как вы можете изменить оригинальный Build.bat файл. Стоит отметить, что подобные изменения актуальны только для Unreal Engine версии 4.21 и выше. После команды setlocal enabledelayedexpansion объявите следующие переменные:
SET PROJECT_NAME=%1%
SET PLATFORM=%2%
SET UPROJECT_FILE=%~5
SET ACTIONHISTORY_FOLDER=....
SET ACTION_HISTORY=....
SET ACTION_HISTORY_BAC=%ACTION_HISTORY%.bac
SET ACTIONHISTORY_PATH="%ACTIONHISTORY_FOLDER%\%ACTION_HISTORY%"
SET ACTIONHISTORY_BAC_PATH=
"%ACTIONHISTORY_FOLDER%\%ACTION_HISTORY_BAC%"
Обратите внимание, что переменные ACTIONHISTORY_FOLDER и ACTION_HISTORY инициализированы четырьмя точками. Вы в свою очередь должны присвоить им значения в зависимости от используемой вами версии UE. Для версий 4.21 и 4.22 они должны иметь следующие значения:
SET ACTIONHISTORY_FOLDER=
%UPROJECT_FILE%\..\Intermediate\Build\%PLATFORM%\%PROJECT_NAME%
SET ACTION_HISTORY=ActionHistory.bin
Для версии 4.23 и новее им нужно присвоить эти значения
SET ACTIONHISTORY_FOLDER=
%UPROJECT_FILE%\..\Intermediate\Build\%PLATFORM%\%PLATFORM%\
%PROJECT_NAME%
SET ACTION_HISTORY=ActionHistory.dat
Сразу после инструкции popd вставьте эти команды:
SET "UBT_ERR_LEVEL=!ERRORLEVEL!"
SET "NEED_TO_PERFORM_ANALYSIS="
IF "!UBT_ERR_LEVEL!"=="0" (
SET "NEED_TO_PERFORM_ANALYSIS=TRUE"
)
IF "!UBT_ERR_LEVEL!"=="2" (
SET "NEED_TO_PERFORM_ANALYSIS=TRUE"
)
IF DEFINED NEED_TO_PERFORM_ANALYSIS (
pushd "%~dp0\..\..\Source"
ECHO Running static analysis
IF EXIST %ACTIONHISTORY_PATH% (
ECHO Copying %ACTION_HISTORY% to %ACTION_HISTORY_BAC%
COPY %ACTIONHISTORY_PATH% %ACTIONHISTORY_BAC_PATH%
ECHO Removing %ACTION_HISTORY%: %ACTIONHISTORY_PATH%
DEL %ACTIONHISTORY_PATH%
)
..\..\Engine\Binaries\DotNET\UnrealBuildTool.exe
%* -StaticAnalyzer=PVSStudio -DEPLOY
popd
SET "UBT_ERR_LEVEL=!ERRORLEVEL!"
IF EXIST %ACTIONHISTORY_BAC_PATH% (
ECHO Recovering %ACTION_HISTORY%
COPY %ACTIONHISTORY_BAC_PATH% %ACTIONHISTORY_PATH%
ECHO Removing %ACTION_HISTORY_BAC%: %ACTIONHISTORY_BAC_PATH%
DEL %ACTIONHISTORY_BAC_PATH%
)
)
Обратите внимание, что переменные PROJECT_NAME, PLATFORM и UPROJECT_FILE, необходимые для правильного определения пути к кэш-файлу, получают свои значения из аргументов командной строки запуска Build.bat. Если у вас отличается порядок данных аргументов, то вы должны соответствующим образом изменить инициализацию трёх вышеописанных переменных.
PVS-Studio умеет работать в режиме инкрементального анализа. Инкрементальный анализ предназначен для проверки только тех исходных файлов, которые были изменены с момента последней сборки проекта. В режиме инкрементального анализа PVS-Studio автоматически запускается на машине разработчика в фоновом режиме сразу же после компиляции кода и производит анализ всех затронутых модификациями файлов. Более подробное руководство по использованию PVS-Studio в режиме инкрементального анализа вы можете найти в нашей документации.
С реализацией режима инкрементального анализа для UE проектов всё опять обстоит немного сложнее, чем при стандартном сценарии работы. В данном случае для того, чтобы иметь возможность проводить инкрементальный анализ (с учётом изменений в подключаемых .h файлах), вам придётся самостоятельно внести правки в сборочную систему UBT. Для этого получите доступ к репозиторию UE на github.com и клонируйте его себе на машину. Для дальнейшей настройки склонированного репозитория вам необходимо выполнить пункты, перечисленные в разделе "Getting up and running " подраздел "Windows". Упомянутый раздел вы можете найти на главной странице официального репозитория UE. После того как вы настроили свой репозиторий, можете приступать к внесению изменений в UBT. Для этого перейдите по следующему пути в склонированном репозитории: \UnrealEngine\Engine\Source\Programs\UnrealBuildTool. Откройте solution UnrealBuildTool.sln и в окне Solution Explorer найдите файл PVSToolChain.cs. В этом файле добавьте следующие строки кода в класс PVSApplicationSettings:
/// <summary>
/// Whether need incremental analysis or not
/// </summary>
public bool IncrementalAnalysis;
Данная строка кода позволяет опции IncrementalAnalysis быть десериализованной из файла настроек PVS-Studio. Не забудьте включить сам режим инкрементального анализа PVS-Studio, для этого откройте в VS пункт главного меню "Extensions", подменю "PVS-Studio", "Analysis after Build (Modified Files Only)", "Enabled". Теперь добавьте следующие строчки кода сразу после объявления переменной BaseFileName:
// Get pvslog file
FileReference OutputFileLocation = FileReference.
Combine(OutputDir, BaseFileName + ".pvslog");
FileItem OutputFileItem = FileItem.GetItemByFileReference(OutputFileLocation);
if (ApplicationSettings.IncrementalAnalysis && OutputFileItem.Exists)
{
// Get object file
FileReference ObjectFileLocation = FileReference.
Combine(OutputDir, BaseFileName + ".obj");
FileItem ObjectFileItem = FileItem.GetItemByFileReference(ObjectFileLocation);
if (ObjectFileItem.Exists
&& (ObjectFileItem.LastWriteTimeUtc < OutputFileItem.LastWriteTimeUtc))
{
continue;
}
}
После этого удалите предыдущие объявления переменных OutputFileLocation и OutputFileItem ниже по коду.
В процессе сборки UE проекта для каждого исходного .cpp файла генерируется объектный файл .obj. Идея данного инкрементального анализа состоит в том, чтобы проверять только те исходные .cpp файлы, для которых дата создания/модификации их объектного файла является более новой, чем у файла отчёта .pvslog (для каждого исходного файла генерируется свой .pvslog файл, в дальнейшем все .pvslog файлы будут объединены в один итоговый .pvslog). После того как вы внесли вышеописанные изменения, соберите UBT и скопируйте новособранный бинарный файл в место расположения оригинального UBT.
Всё готово, теперь при выполнении сборки UE проекта вы будете получать журнал отчёта, содержащий результаты работы анализатора только для исходный файлов, подвергшихся компиляции. Помните, что подобная модификация UBT имеет смысл, только если вы модифицировали файл Build.bat таким образом, чтобы он выполнял удаление кэш-файла ActionHistory.bin (подробное описание этого сценария было описано выше). Для отключения режима инкрементального анализа просто установите вышеописанную опцию "Analysis after Build (Modified Files Only)" в режим "Disabled".
Ещё раз напомню: если вы установили флаг -StaticAnalyzer=PVSStudio в поле Build Command Line в настройках проекта 'Properties|Configuration Properties|NMake', то его необходимо удалить при данном сценарии работы.
По умолчанию при выполнении анализа UE проекта файл отчёта не загружается в окно PVS-Studio в VS. Он просто сохраняется относительно папки проекта по следующему пути: \YouProject\Saved\PVS-Studio\. Для того чтобы открыть данный файл в VS, вам необходимо воспользоваться следующей командой: 'PVS-Studio|Open/Save|Open Analysis Report' и в опции выбора типа файла установить 'Unparsed output'. Вы также можете открыть файл отчёта в программе C and С++ Compiler Monitoring, воспользовавшись данной командой: 'File|Open PVS-Studio Log' и также выбрать тип файла 'Unparsed output'.
Существует более удобный вариант для открытия журнала анализа - это его автоматическая загрузка в VS. Для того чтобы он автоматически загружался в окно PVS-Studio в VS после завершения анализа, вам необходимо включить соответствующую опцию: 'PVS-Studio|Options|Specific Analyzer Settings|Save/Load (analyzer report)|AutoloadUnrealEngineLog'.
Я, как автор этой статьи и как один из тех людей, кто непосредственно работает над реализацией и поддержкой функционала PVS-Studio, связанного с анализом проектов, построенных на базе движка UE, готов помочь читателям. Если у вас возникли трудности с использованием PVS-Studio с вашим UE проектом или остались какие-либо вопросы, на которые вы не нашли ответа в данной статье, то я буду рад с вами пообщаться. Пишите к нам в поддержку и мне передадут письма, касающиеся UE и смежных вопросов. Спасибо за ваше внимание.