This article focuses on the specifics of checking Unreal Engine projects with the PVS-Studio static analyser on the Windows operating system: how to install the analyser, check a project, where and how to view an error report.
The most recent information about how you can analyze Unreal Engine project using PVS-Studio can be found here.
An integral part of the series of our articles are topics related to the gaming industry. Check an actual engine used in AAA-games - you're welcome, come up with top errors in the gaming industry - go ahead, find bugs in one of the most popular game engines Unreal Engine (UE) - easy enough. In game development, as well as with any other application, the quality of the code does matter. Errors are best found as early as possible and the best option is to do it automatically - this is where static code analysers come to the aid of programmers.
In this article, I'll try to briefly talk about how you can use the PVS-Studio static analyser to check projects created in UE. PVS-Studio can help you make your project's code better by finding bugs in it, thereby allowing you to reduce the time you spend on code review.
Please note that this article is an addition to existing documentation on UE projects analysis and doesn't serve the purpose of replacing it, largely borrowing the contents of the documentation.
The easiest way to install the PVS-Studio analyser is to download its installation file. In order to be able to analyse projects created in UE, you need to select the following components when installing PVS-Studio: "C and C++ Compiler Monitoring" and "Integration with Microsoft Visual Studio (Visual C++/C#)". The last point is responsible for integrating the PVS-Studio plugin into the Visual Studio IDE, through which it is convenient to work with the error log and with the general settings of the analyser itself.
To work fully with PVS-Studio, you need to enter a license. You can do this by opening Visual Studio (VS) IDE and entering the license in the 'PVS-Studio|Options...|Registration'. In VS 2019, the PVS-Studio menu has been moved to the 'Extensions' menu, the path to the license entry window looks like this: 'Extensions'|'PVS-Studio|Options...|Registration'. The license is available on our website.
To build UE projects a custom UnrealBuildTool (UBT) program from Epic Games is used, not a standard build system, used in VS (MSBuild). In this regard, the PVS-Studio plugin isn't able to implement a usual scenario of checking C++/C# projects, created in VS: "PVS-Studio -> Check -> Current Project". There are several solutions to avoid this limitation.
The first and the easiest way to check a UE project is to use the program C and C++ Compiler Monitoring (named Standalone.exe), located in the PVS-Studio installation directory. The principle of its work is that it monitors compiler processes that correspond to the target compiler (in this case, cl.exe) and gathers all needed information for preprocessing and further analysis of source files. After you have opened C and C++ Compiler Monitoring, use the menu "Tools" and choose the option "Analyze Your Files (C and C++)...". Press "Start Monitoring" and you'll see the window in the bottom left corner telling you that compiler calls monitoring is in process:
Next, build your UE project and press "Stop Monitoring".
After that, the analysis of compiled source files will start. The report of the warnings found will be shown in the window "Analyzer Output" of the program C and C++ Compiler Monitoring.
Similar compiler calls monitoring and subsequent analysis of detected files can be made using the CLMonitor.exe console program, located in the same folder, where PVS-Studio was installed. CLMonitor.exe has two operating modes: a server mode when launches of processes (corresponding to the target compiler) are monitored and a client mode (when source files, detected at the monitoring stage, are analysed, followed by a report of analysis results). In order to run CLMonitor.exe in the server mode, perform the following command:
CLMonitor.exe monitor
After that, build your UE project and perform the command below:
CLMonitor.exe analyze -l "c:\ptest.plog"
The "analyze" command runs CLMonitor.exe in the client mode and closes the running instance of this program, working in the server mode. After performing this command, CLMonitor.exe will start executing files analysis. A parameter for the "- l" option is a path to the file, in which the analyser's results will be written.
A different and more convenient approach to analysing UE projects is a direct integration with the UBT built system. To do this, open the property window of your UE project in VS and choose "NMake" in the list "Configuration Properties". Add the -StaticAnalyzer=PVSStudio in text field of the property "Build Command Line". As an example, the value of the field "Build Command Line" might look as follows:
C:\Program Files\Epic Games\UE_4.22\Engine\Build\BatchFiles\Build.bat"
MyProject Win64 DebugGame
-Project="$(SolutionDir)$(ProjectName).uproject"
-WaitMutex -FromMsBuild -StaticAnalyzer=PVSStudio
It should be taken into account that when performing a project build, it will only be analysed, not built. The scenario in which a project is both built and analysed will be described below. It also should be noted that only those source files that have been changed since the last project build will be analysed. Changing of any included .h file is not a reason to perform the analysis during the next build. In order to perform full analysis, you need to add the same flag in the text field of the property "Rebuild All Command Line". Now when rebuilding the project, you'll get the result of analyzing the entire project.
Now let's consider another scenario of the PVS-Studio analyser integrating into the UBT build system. While doing it, the analysis starts right after performing a project build/rebuild. In other words, you get both a built project and a file with analysis results. You might have noted that the field Build Command Line contains the path to the batch file Build.bat, which, in turns, contains instructions to run UBT with needed arguments. Build.bat runs in the very beginning of the build.
The point is to change the batch file so that it could first run UBT with standard build arguments and then, if a build successfully completes, run the same UBT, but already with an additional flag -StaticAnalyzer=PVSStudio. To implement the above scenario, you can change the batch file Build.bat. It's even better to create its copy named, for example, BuildAndAnalyze.bat. Here's what you need to do to implement the described scenario. Right after the popd command, insert the following instructions:
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!"
)
If the flag -StaticAnalyzer=PVSStudio was previously installed in the Build Command Line field in the project 'Properties|Configuration Properties|NMake' settings, it has to be removed.
The problem with this approach is that only files that were compiled during build will be analyzed. That is, you won't receive a report file with a full check of your project. In addition, any changes made to included .h files will also not be taken into account. Therefore, we cannot call this analysis incremental, as changes in the header files won't trigger the analysis during the next build. In this case, you can rebuild the project, getting the result of the analysis for the entire project. However, full build can take a long time, so you can follow this scenario: make a build, delete the cache file ActionHistory.bin, run the build with the flag -StaticAnalyzer=PVSStudio, restore the cache file. The ActionHistory.bin file contains information needed to perform incremental build as well as the history of running the analyzer for checked files.
At a first glance, this scenario may not seem the easiest, so we'll provide a complete set of instructions on how you can change the original Build.bat file. It is worth noting that such changes are only relevant to Unreal Engine version 4.21 and later. After the setlocal enabledelayedexpansion command, declare the following variables:
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%"
Note that ACTIONHISTORY_FOLDER and ACTION_HISTORY variables are initialized with four points. You have to assign them values depending on the UE version you are using. For versions 4.21 and 4.22 values have to be the following:
SET ACTIONHISTORY_FOLDER=
%UPROJECT_FILE%\..\Intermediate\Build\%PLATFORM%\%PROJECT_NAME%
SET ACTION_HISTORY=ActionHistory.bin
For versions 4.24 and later values have to be the following:
SET ACTIONHISTORY_FOLDER=
%UPROJECT_FILE%\..\Intermediate\Build\%PLATFORM%\%PLATFORM%\
%PROJECT_NAME%
SET ACTION_HISTORY=ActionHistory.dat
Right after the popd instruction, insert these commands:
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%
)
)
Note, that variables PROJECT_NAME, PLATFORM and UPROJECT_FILE, needed for correct determination of the path to the cache file, get their values from the arguments of the Build.bat's command line. If you have a different order of these arguments, you have to appropriately change initialization of the three variables, described above.
PVS-Studio is able to work in the incremental analysis mode. Incremental analysis is meant to check only those files that have been changed since the last build. In the incremental analysis mode, PVS-Studio is automatically run on a developer's computer in the background mode right after code compilation and analyzes all modified files. You can find a more detailed guide on using PVS-Studio in the incremental analysis mode in our documentation.
With the implementation of the incremental analysis mode for UE projects, everything is again a bit more complicated than in a standard scenario. In this case, to be able to perform the incremental analysis (taking into account changes in included .h files), you'll have to introduce edits in the build UBT system yourself. To do this, get access to the UE repository on github.com and clone it to your machine. To further customize the cloned repository, you'll need to complete the steps, listed in the section "Getting up and running ", subsection "Windows". You can find this section on the front page of the official UE repository. Once you've set up your repository, you can start making changes in UBT. To do this, follow this path to the cloned repository: \UnrealEngine\Engine\Source\Programs\UnrealBuildTool. Open solution UnrealBuildTool.sln and find the file PVSToolChain.cs in Solution Explorer. In this file, add the following lines of code in the class PVSApplicationSettings:
/// <summary>
/// Whether need incremental analysis or not
/// </summary>
public bool IncrementalAnalysis;
This line of code enables the IncrementalAnalysis option to be deserialized from the PVS-Studio settings files. Don't forget to enable the PVS-Studio incremental analysis mode itself. To do this, in VS open "Extensions" in the main menu, submenu "PVS-Studio", "Analysis after Build (Modified Files Only)", "Enabled". Now add the following lines of code right after declaration of the variable 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;
}
}
Then remove previous declarations of variables OutputFileLocation and OutputFileItem below.
While building the UE project, an object .obj file is generated for each source .cpp file. This incremental analysis is all about checking only those source .cpp files for which the date of creation/modification of their object file is later than the one of the .pvslog report file. A separate .pvslog file is generated for each source file, in the future all .pvslog files will be merged in one final .pvslog). Once you've made the above changes, build UBT and copy the newly built binary file to the location of the original UBT.
Now it's all ready, you'll be receiving a report log when performing the build of your UE project, containing analyzer's results only for compiled source files. Keep in mind that such modification of UBT makes sense only if you have modified the Build.bat file in such a way that it performed removing of the cache file ActionHistory.bin (detailed description of this scenario was given above). To disable the incremental analysis mode, just install the option "Analysis after Build (Modified Files Only)" described above in the mode "Disabled".
Let me remind you once again: if you installed the flag -StaticAnalyzer=PVSStudio in the field Build Command Line in the settings of the project 'Properties|Configuration Properties|NMake', it has to be removed in this scenario.
By default when performing the UE project analysis, a report file won't be shown in the PVS-Studio window in VS. It's just stored relatively to the project folder by the following path: \YouProject\Saved\PVS-Studio\. To open this file in VS, you need to use the following command: 'PVS-Studio|Open/Save|Open Analysis Report' and select the 'Unparsed output' file type. You can also open the file report in the program C and C++ Compiler Monitoring, by using the following command: 'File|Open PVS-Studio Log' and also choose the file type 'Unparsed output'.
There's another more convenient option to open the analysis report log, which is its automatic loading in VS. In order for it to automatically load into the PVS-Studio window in VS after the analysis is complete, you need to enable the appropriate option: 'PVS-Studio|Options|Specific Analyzer Settings|Save/Load (analyzer report)|AutoloadUnrealEngineLog'.
As the author of this article, as well as one of those people who is directly working on the implementation and support of PVS-Studio's functionality related to the analysis of projects, built on the basis of the UE engine, I am ready to help readers. If you're having trouble using PVS-Studio with your UE project or have any questions after reading this article, I'd be happy to chat with you. Write to our support, I'll get mails on UE and related issues. Thank you for your attention.