We recommend utilizing PVS-Studio analyzer through the Microsoft Visual Studio development environments, into which the tool is perfectly integrated. But sometimes you can face situations when command line launch is required, for instance in case of the cross-platform build system based on makefiles.
In case you possess project (.vcproj/.vcxproj) 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 "Analyzing Visual C++ (.vcxproj) and Visual C# (.csproj) projects from the command line".
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.
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. Operation of any code analyzer includes at least two steps: preprocessing and analysis itself.
It is possible that C++ sources 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 GNU Make 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. 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.
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, including the path to source file (or files).
%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 the compiler, i.e. the full path to the source file should be passed twice, in each param.
%cfgPath% — path to PVS-Studio.cfg 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/Open Analysis Report' menu command (selecting 'Unparsed output' as a file type). 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.
Consider this example for starting the analyzer in independent mode for a single file, utilizing the Visual C++ preprocessor (cl.exe):
PVS-Studio.exe --cl-params "C:\Test\test.cpp" /D"WIN32" /I"C:\Test\" --source-file "C:\Test\test.cpp" --cfg "C:\Test\PVS-Studio.cfg" --output-file "C:\Test\test.log"
The PVS-Studio.cfg (the --cfg parameter) 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 preprocessor = visualcpp language = C++
Let's review these parameters:
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.
Also there is a possibility to pass the analyzer a ready-made prepossessed file (i-file), by missing the preprocessing phase and by getting to the analysis. To do this, use the parameter skip-cl-exe, specifying yes. In this mode there is no need to use cl-params parameter. Instead, specify the path to the file (--i-file) and set the type of the preprocessor, used to create this i-file. Specifying the path to the source file (--source file) is also necessary. Despite the fact that the i-file already contains the necessary information for analysis, it may be needed to compare the i-file with the file of the source code, for example, when the analyzer has to look at unexpanded macro. Thus, the call of the analyzer in the independent mode with the specified i-file for the preprocessor Visual C++ (cl.exe) could be:
PVS-Studio.exe --source-file "C:\Test\test.cpp" --cfg "C:\Test\PVS-Studio.cfg" --output-file "C:\Test\test.log"
The configuration file PVS-Studio.cfg (parameter --cfg) should contain 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 preprocessor = visualcpp language = C++ skip-cl-exe = yes i-file = C:\Test\test.i
The full list of command line switches will be displayed with this argument:
For example let's take the Makefile 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.
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.
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 IDE toolwindow using 'Open 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.
The users who are familiar with PVS-Studio incremental analysis mode within the IDE naturally will miss this feature in the command line mode. 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.
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
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.
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.
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. Please refer to our customer support.