Using PVS-Studio from the command line (without Visual Studio solution file)

Abstract

PVS-Studio code analyzer used to develop modern 64-bit and parallel applications perfectly integrates into Microsoft Visual Studio environment. But sometimes, there are situations when using the tool in the environment is impossible or inconvenient. The article provides guidelines and examples from practice on using the analyzer in the command line-launch mode. The article describes the 4.30 version of PVS-Studio analyzer.

Introduction

PVS-Studio is a static code analyzer intended for developers of modern resource-intensive applications in C and C++ languages. By "modern applications" we understand 64-bit and/or parallel applications. Development of these programs implies some difficulties different from those of traditional programming. Because besides common errors known to everyone like uninitialized pointers, detected by the compiler, there are new types of issues.

In this article, we won't dwell upon description of PVS-Studio tool and its purposes. To learn this, refer to the review article "Getting acquainted with PVS-Studio code analyzer" and a more solid "PVS-Studio Tutorial". This article's purpose is to discuss the use of the tool from the command-line.

We recommend that everyone should use PVS-Studio in Microsoft Visual Studio development environment into which the tool is perfectly integrated. But sometimes you can face situations when you should launch it using the command line. In case you possess project (.vcproj) and solution (.sln) files, and command line execution is required for the sake of daily code checks, for instance, we advise you to examine the article "Checking code with PVS-Studio from the command line (with a Visual Studio solution file present)". Otherwise you should consider using this article.

What should you know before launching the tool from the command line?

To be able to launch the tool from the command line successfully it is extremely important to understand the code analyzer's working principles. When working in Visual Studio, much of this stays hidden (and it is better for the user this way). But when launching the tool from the command line one must understand all the details and peculiarities.

So, how does a code analyzer work (be it PVS-Studio or any other tool)?

When the analyzer user gives a command to check some file (for example, file.cpp), the analyzer performs preprocessing of this file at first. As a result, all the macros are defined and #include-files are arranged. Preprocessing during code analysis is necessary for the analyzer to be able to "see" definitions of functions, types and classes which will be used in the analyzed file then. Some code analyzers have an internal preprocessor. Others (like PVS-Studio) use an external one. We use the preprocessor from Visual Studio compiler. The result of preprocessing is the file with the extension ".i". As a rule, this file is rather large as it contains the bodies of all the header files used in the module.

The preprocessed i-file can now be parsed by the code analyzer. Pay attention that the analyzer cannot parse a file which has not been preprocessed, for it won't have information about the types, functions and classes being used.

So, operation of any code analyzer includes at least two steps: preprocessing and analysis itself.

Specifics of using PVS-Studio while launching from command line

PVS-Studio tool has been developed to work within the framework of Visual Studio environment. And launching it from the command line is the function that is additional to the main working mode. However, all of analyzer's diagnostic capabilities are available. The only significant difference between operating within Visual Studio and launching from the command line is the following.

Suppose we have a project consisting of three files: file.h, file1.cpp and file2.cpp. And file.h is included both in file1.cpp and file2.cpp through #include directive. Suppose PVS-Studio analyzer found an error inside file.h when analyzing file1.cpp and informed about it. When analyzing file2.cpp, the same error will be found inside file.h (for file.h is included into the both files). But when launching the tool in Visual Studio, the error won't be shown for the second time as there is a mechanism filtrating repeating warnings. When launching the analyzer from the command line, this mechanism doesn't work and the warning will be shown in the both cases - when analyzing file1.cpp and file2.cpp.

Also, when launching from the command line, the mechanisms of error-warning filtration are not available (see: diagnosable errors and suppression of separate warnings).

However the error messages generated in this mode could be easily redirected into the external file with the help of --output-file command line switch. This file will contain the unprocessed and unfiltered analyzer output.

Such a file could be viewed in PVS-Studio toolwindow of Visual Studio IDE using 'Load Analysis Report' menu command (selecting 'Unparsed output' as a file type) and afterwards it could be saved in a standard PVS-Studio log file (plog) format. This allows you to avoid the duplication of error messages and also to use all of the standard filtering mechanisms for them.

Please note, that starting from PVS-Studio version 4.52, the analyzer supports multi-process (PVS-Studio.exe) output into a single file (specified through --output-file) in command line independent mode. This allows several analyzer processes to be launched simultaneously during the compilation performed by a makefile based system. The output file will not be rewritten and lost, as file blocking mechanism had been utilized.

PVS-Studio analyzer independent mode

Usually the programs' sources developed with Visual C++ do possess project files (files with vcproj/vcxproj extensions) which in turn contain metadata about their respective structures and build configurations as well as their building parameters. Such sources can be easily analyzed with PVS-Studio using Visual Studio extension plug-in. But it is possible that sources written for Visual C++ compiler do not have project files associated with them, for example it is possible in case of multiplatform software or old projects which are built using command line batch utilities. Various Make systems are often employed to control building process in such cases, Microsoft NMake or GNUMake for instance.

To analyze such projects it is necessary to embed the direct call for the analyzer (the 'programfiles%\PVS-Studio\x64\PVS-Studio.exe' file) into building process and to pass all arguments required for preprocessing to it. The PVS-Studio analyzer should be called in batch mode for each C/C++ file or for a whole group of files (files with c/cpp/cxx etc. extensions, the analyzer shouldn't be called for header h files) with the following arguments:

PVS-Studio.exe --cl-params  %ClArgs%
--source-file %cppFile% --cfg %cfgPath%  --output-file %ExtFilePath%

%ClArgs% — arguments which are passed to cl.exe compiler during regular compilation.

%cppFile% — path to analyzed C/C++ file or paths to a collection of C/C++ files (the filenames should be separated by spaces)

%ClArgs% and %cppFile% parameters should be passed to PVS-Studio analyzer in the same way in which they are passed to Visual C++ compiler.

%cfgPath% — path to PVS-Studio configuration file. This file is shared between all C/C++ files and can be created manually (the example will be presented below)

%ExtFilePath% — optional argument, a path to the external file in which the results of analyzer's work will be stored. In case this argument is missing, the analyzer will output the error messages into stdout. The results generated here can be viewed in Visual Studio's 'PVS-Studio' toolwindow using 'PVS-Studio/Load Analysis Report' menu command (selecting 'Unparsed output' as a file type).

In fact the analyzer should be called for the same files for which the compiler (cl.exe in case of Visual C++) is being called. It is important to remember that PVS-Studio analyzer works only with Microsoft Visual C++ preprocessed C/C++ files at this moment and therefore can be embedded into building process only if the support for this compiler is present.

The analysis results for each file will be egested into stdout/stderr.

Using Microsoft IntelliSense with analyzer in independent mode.

Although it is possible to open the unfiltered text file containing analyzer diagnostic messages from within the IDE into PVS-Studio Output window (which itself will allow you to use file navigation and filtering mechanisms), you will only be able to use the code text editor inside the Visual Studio itself, as the additional IntelliSense functionality will be unavailable (that is, autocompletion, type declarations and function navigation, etc.). And all this is quite inconvenient, especially while you are handling the analysis results, even more so with the large projects, forcing you to search class and method declarations manually. As a result the time for handling a single diagnostic message will be greatly increased.

To solve this issue, you need to create an empty Visual C++ project (Makefile based one for instance) in the same directory with C++ files being verified by the analyzer (vcproj/vcxproj file should be created in the root folder which is above every file verified). After creating an empty project you should enable the 'Show All Files' mode for it (the button is in the upper part of the Solution Explorer window), which will display all the underlying files in the Solution Explorer tree view. Then you will be able to use the 'Include in Project' context menu command to add all the necessary c, cpp and h files into your project (You will also probably have to add include directory paths for some files, for instance the ones containing third-party library includes). If including only a fraction of the files verified, you also should remember that IntelliSense possibly will not recognize some of the types from within these files, as these types could be defined right in the missing files which were not included by you.

Figure 1 — including files into the project

Figure 1 — including files into the project

The project file we created could not be used to build or verify the sources with PVS-Studio, but still it will substantially simplify handling of the analysis results. Such a project could also be saved and then used later with the next iteration of analyzer diagnostics results in independent mode.

An example of using the analyzer independent mode with Microsoft NMake project

For example let's take Microsoft Nmake project which is build using VisualC++ compiler and it is declared in the project's makefile like this:

$(CC) $(CFLAGS) $<

The $(CC) macro calls cl.exe, the compilation parameters $(CFLAGS) are passed to it and finally all C/C++ files on which the current build target is dependent are inserted using the $< macro. Thereby the cl.exe compiler will be called with required compilation parameters for all source files.

Let's modify this script in such a way that every file is analyzed with PVS-Studio before the compiler is called:

$(PVS) --source-file $< --cl-params $(CFLAGS)  $<
--cfg "C:\CPP\PVS-Studio.cfg"
$(CC) $(CFLAGS) $<

$(PVS) – path to analyzer's executable (%programfiles%\PVS-Studio\x64\PVS-Studio.exe). Take into account that the Visual C++ compiler is being called after the analyzer on the next line with the same arguments as before. This is done to allow for all targets to be built correctly so the build would not stop because of the lack of .obj-files.

The PVS-Studio.cfg configuration file should include the following lines:

exclude-path = C:\Program Files (x86)\Microsoft Visual Studio 10.0
vcinstalldir = C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\ 
platform = Win32
output-file = c:\results.log

Let's review these parameters:

  • The exclude-path parameter contains the directories for which the analysis will not be performed. If the Visual Studio directory is not included here, the analyzer will generate error messages for its' header .h-files. But you of course cannot modify them. Therefore we recommend you to always add this path to the exclusions. It is also possible to set multiple exclude-path parameters.
  • The vcinstalldir parameter indicates the directory in which the Microsoft Visual C++ compiler is located. This is required to be able to locate the cl.exe compiler and use it for preprocessing.
  • The platform parameter points us to the correct version of the compiler — Win32, x64, Itanium or ARMV4. It is usually Win32 or x64.
  • The output-file parameter indicates the path to a file which will be used to store the analyzer's output.

You can filter diagnostics messages generated by analyzer using analyzer-errors and analysis-mode parameters (set them in cfg file of pass through command line). These parameters are optional.

  • The analyzers-errors parameter allows you to set the codes for errors in which you are interested. For example: analyzer-errors=V112 V111. We do not recommend setting this parameter.
  • The analysis-mode parameter allows you to control the analyzers being used. Values: 0 – full analysis (by default), 1 – only 64 bit analysis, 2 – only OpenMP analysis, 4 – only general-purpose analysis, 8 – only optimization analysis. The recommended value is 4.

The full list of command line switches will be displayed with this argument:

PVS-Studio.exe –-help

Incremental analysis in independent command line mode

The users who are familiar with PVS-Studio incremental analysis mode within Visual Studio IDE naturally will not wish to miss this feature in the command line mode either. But fortunately, almost any build system could provide an incremental analysis just "out of the box", because by invoking "make" we recompile only file which were modified. So the incremental analysis will be automatically provided by using the independent command line version.

Differences in behavior of PVS-Studio.exe console version while processing one file or several files at once.

The cl.exe compiler is able to process source files as either one at a time or as a whole group of files at once. In the first case the compiler is called several times for each file:

cl.exe ... file1.cpp
cl.exe ... file2.cpp
cl.exe ... file2.cpp

In the second case it is called just once:

cl.exe ... file1.cpp file2.cpp file3.cpp

Both of these modes are supported by the PVS-Studio.exe console version as demonstrated above in the examples.

It could be helpful for a user to understand the analyzer's logics behind theses two modes. If launched individually, PVS-Studio.exe will firstly invoke the preprocessor for each file and the preprocessed file will be analyzed after it. But when processing several files at once, PVS-Studio.exe will firstly preprocess all these files and then separate instances of PVS-Studio.exe will be invoked individually for each one of the resulting preprocessed files.

Conclusion

Although the abilities included into PVS-Studio are enough to use the tool from the command line, of course it can be greatly improved. We are ready to improve the mechanism of launching PVS-Studio from the command line to the level allowing making it convenient for you to use the tool in your particular project. Write to us.