Cross-platform analysis of C and C++ projects in PVS-Studio
- Introduction
- How to activate the license
- How to prepare the project for analysis
- How to analyze the project
- How to use the configuration file
- Baselining analysis results and filtering reports according to suppression rules
- Exit codes
Introduction
PVS-Studio supports cross-platform project checks in C and C++ regardless of the build system used. Such projects can be checked with a special utility. It has different names depending on the target platform: pvs-studio-analyzer
for Linux and macOS, and CompilerCommandsAnalyzer.exe
for Windows. All examples of launching the analyzer described here use the pvs-studio-analyzer
executable file.
To check Visual Studio projects, use the following documentation:
- Get started with PVS-Studio in Visual Studio
- Analyzing Visual Studio / MSBuild / .NET projects from the command line using PVS-Studio
On Windows, you can also use a compilation monitoring server.
Note: pvs-studio-analyzer
and CompilerCommandsAnalyzer.exe
are the same cross-platform utility and have minor differences. This document describes platform-dependent features of these utilities. All pvs-studio-analyzer
launch examples are cross-platform, unless the description says otherwise.
How to activate the license
To make the analyzer work, activate the license using one of the ways described in the documentation.
If you do not have the license, you can request it on our website.
How to prepare the project for analysis
To analyze the project, the pvs-studio-analyzer
utility has to know the compilation launch parameters for each translation unit. These parameters can be obtained from JSON Compilation Database (compile_commands.json
) or from the build trace file.
Important: The project must be successfully built to be analyzed.
Using the compilation database (Windows, Linux, macOS)
Many build systems (CMake, Ninja, etc.) allow you to generate the compile_commands.json
file. For build systems that do not allow you to obtain compile_commands.json
directly, there are various utilities (Bear, Text Toolkit, intercept-build, etc.) that allow you to generate it.
The JSON Compilation Database generation and analysis are described here.
Creating a compilation trace file (Linux only)
If you cannot generate compile_commands.json
for your project, you can use the compilation trace mode. This mode works only under Linux and uses the strace
utility to intercept compiler calls.
Note: To monitor compilation on Windows, use CLMonitor, the compilation monitoring server.
Important: To trace the compilation, install strace
4.11 or newer and enable the PTRACE
system call. Before starting the compilation tracing, the project should be cleaned. This will provide the most complete information about the structure of the project.
Note: in many distributions, PTRACE
is enabled by default. However, there are exceptions. To enable PTRACE
, change the value of the kernel.yama.ptrace_scope
parameter in the /etc/sysctl.d/10-ptrace.conf
file to 1.
The trace result is written to a file named strace_out
(by default) located in the current directory. Later, the analyzer will use this file to obtain compilation parameters. You can specify an arbitrary path to the result file with the -o
flag.
Before tracing, make sure that there are no artifacts of the previous build in the build directory. Otherwise, the build system may omit compiler calls for unmodified files if it uses incremental build mode.
To start tracing compilation, run the following command:
pvs-studio-analyzer trace [-o <FILE>] -- build_command
build_command
is a command used to build the project.
Example:
pvs-studio-analyzer trace -- cmake build .
How to analyze the project
After forming the JSON Compilation Database or the compilation trace file, you can finally start analyzing the project.
In general, run the following command to start the analysis:
pvs-studio-analyzer analyze [-o /path/to/PVS-Studio.log] \
[-e /path/to/exclude-path]... \
[-j <N>]
Below is the description of all command-line flags.
General flags description
‑‑cfg [FILE] (-c [FILE])
specifies the configuration file (*.cfg
), in which you can put some parameters of the analyzer launch (for example, exclude-path, lic-file, etc.). The next section will describe the configuration file settings. You can put the general parameters for checking various projects in this configuration file.
‑‑lic-file [FILE] (-l [FILE])
is a path to the license file. There is a corresponding setting for this parameter in the configuration file.
‑‑threads [N] (-j [N])
specifies the number of threads to which the analysis will be parallelized.
‑‑output-file [FILE] (-o [FILE])
is a path to the file to which the analysis report will be written. By default, if this flag is not specified, the report will be written to the PVS-Studio.log
file in the current directory. You can specify this parameter in the configuration file (*.cfg
).
‑‑exclude-path [DIR] (-e [DIR])
specifies a path where files should be excluded from the analysis. You can specify an absolute or relative path. You can also use templates (glob
) to exclude a set of files. If there are several directories that you want to exclude from the check, add each directory via this flag or write them in the configuration file.
‑‑analysis-paths [MODE=PATH|GLOB]
defines the behavior of the analysis on the specified paths.
The available modes:
skip-analysis
specifies the directory from which files do not need to be checked. These are usually directories of system files or included libraries.skip-settings
ignores the settings located in the source files and.pvsconfig
files by the specified path.isolate-settings
sets the directory for which the settings should be isolated. When this mode is enabled, the configuration files of diagnostic rules (.pvsconfig
) from parent directories will not be applied to translation units in the specified directory and its subdirectories. Both absolute and relative paths are supported. Relative paths are expanded via the current directory. Theglob
patterns cannot be used for this mode.skip
ignores the settings located in the source files and.pvsconfig
files by the specified path. Warnings generated for source code files by the specified path or mask will also be filtered.
‑‑analysis-mode [MODE]
(-a [MODE]
) specifies the group of warnings that will be activated during the analysis.
- 64: Diagnostic rules for 64-bit errors.
- GA: General analysis diagnostic rules.
- OP: Diagnostic rules for micro-optimizations.
- CS: Diagnostic rules for specific user requests.
- MISRA: Diagnostic rules for checking the code for compliance with the MISRA standards.
- AUTOSAR: Diagnostic rules for checking the code for compliance with the AUTOSAR standards.
- OWASP: Diagnostic rules for checking the code for compliance with the OWASP standards.
You can read more about MISRA, AUTOSAR, and OWASP here.
If you want to specify several groups of warnings, separate them with the ;
or +
character. For example: GA;OP;64
or GA+OP+64
. You can omit single quotes if you use +
as a separator. If you use the ;
character as a separator, then you should wrap the expression in single quotes or escape each semicolon. In shells, the ;
character usually means a command separator.
By default, the analyzer uses the GA group.
You can specify this parameter in the configuration file (*.cfg
).
‑‑sourcetree-root [DIR] (-r [DIR])
indicates that the root part of the path (DIR) should be replaced with a special character in the report. Thus, the path to the file with the analyzer warning will become relative. By default, PVS-Studio, when generating diagnostic messages, outputs absolute paths to files that triggered the analyzer. With this setting, you can specify the root part of the path, which the analyzer will automatically replace with a special marker. The replacement will occur if the path to the file begins with the specified root part ([DIR]
). Next, the report with relative paths can be used to view the analysis results in an environment with a different location of the source files.
‑‑project-root
specifies the path to the project root directory. Both absolute and relative paths are supported. Relative paths are expanded via the current directory. If the flag is not specified, the current directory will be considered the project root.
‑‑apply-pvs-configs
enables the mode for searching and applying configuration files of diagnostic rules (.pvsconfig
) for each translation unit. The configuration files are searched in the translation unit directory and all parent directories (up to the project root). To use this mode, the project root directory should be specified with the ‑‑project-root
flag.
‑‑disableLicenseExpirationCheck
sets the exit code to zero if the license expires soon. This flag should be used when you're integrating the analyzer in continuous integration systems (Travis CI, CircleCI, GitLab CI/CD) or automating the verification of commits and Pull Requests and your license expires soon (less than 30 days left).
Note: If you renew the license and forget to remove this flag, then pvs-studio-analyzer replaces the possible zero exit code with code 6.
‑‑file [FILE] (-f [FILE])
specifies a path to the compilation trace file or JSON Compilation Database. By default, if this flag is not specified, PVS-Studio searches for the strace_out
or compile_commands.json
file in the current directory. Note that PVS-Studio first searches for compile_commands.json
and only then strace_out
. If you have these two files in your directory, then the analyzer chooses the first one. If you use JSON Compilation DB, make sure to specify the .json
file extension, otherwise this file will be treated as a trace file.
Specify this flag if the compilation trace file or JSON Compilation Database is saved in a non-default path.
‑‑quiet
is used to hide the analysis process.
‑‑preprocessor [NAME]
specifies the preprocessor type that the analyzer will expect when parsing preprocessed files (*.PVS-Studio.i
). Possible values:
- visualcpp
- clang
- gcc
- bcc
- bcc_clang64
- iar
- keil5
- keil5_gnu
- c6000.
While the preprocessor is running, macros are expanded and the contents of files included via #include
are substituted into the resulting preprocessed file. To make compilers and various utilities correctly navigate such a file, a preprocessor inserts special #line
directives. They point to the file, the contents of which were inserted in this location.
The PVS-Studio needs to know the preprocessor type so the analyzer can correctly process the #line
directives specific for different compilers.
By default, if this flag is not specified, the analyzer tries to determine the preprocessor type on its own. However, there are situations when the analyzer may incorrectly determine it. In this case the preprocessor can be specified explicitly.
This parameter can be specified in the configuration file (*.cfg
).
‑‑platform [NAME]
allows you to specify the target platform for which the project is compiled.
This flag expects the following parameters:
- for Windows:
win32
,x64
,Itanium
,arm
; - for Linux:
linux32
,linux64
,Itanium
,arm
; - for macOS:
macOS
; - For Embedded:
pic8
,tms
(Texas instruments).
The analyzer needs information about the platform to correctly determine the data model.
By default, if you do not specify this flag, PVS-Studio will try to determine the platform based on the compiler launch parameters.
This parameter can be also specified in the configuration file.
‑‑ignore-ccache
enables analysis of all source files regardless of the ccache
state. If your project uses a wrapper over the compiler call (ccache
) to speed up the build, the analysis will not find the compilation files. This flag allows you to omit the ccache
call and process the compiler command wrapped in it.
‑‑incremental (-i)
enables incremental analysis of the project.
‑‑source-files [FILE] (-S [FILE])
specifies a list of source files for file list checking mode. This list is a text file where the path to each source file is located on a new line. You can use absolute and relative paths. Relative paths will be expanded relative to the directory from which you want to run the analysis.
This approach is convenient to use when you analyze commits and Pull Requests.
‑‑regenerate-depend-info [OPTION]
updates information about compilation dependencies for each source file. Information about dependencies is stored in the depend_info.json
file.
This flag supports the following modes:
run-analysis
is used to update the dependency information and run the analysis,skip-analysis
is used to update information about dependencies without running the analysis.
The analyzer needs the dependencies file to correctly perform the file list checking mode or incremental analysis. You can read more about it here.
‑‑suppress-file [FILE] (-s [FILE])
specifies a path to the file with suppressed warnings. Warnings included in the suppression file are ignored when the analyzer report is generated. You can read more about it here. By default, the suppress file is named suppress_file.suppress.json
.
‑‑analyze-specified-system-paths
includes files from custom system directories (specified via compilation flags: isystem
, isysroot
, system_include_dir
, etc.) in the analysis.
‑‑compiler [COMPILER_NAME[=COMPILER_TYPE]] (-C [COMPILER_NAME[=COMPILER_TYPE]])
allows you to specify the compiler name and type.
Use this flag when PVS-Studio cannot recognize compiler calls (when analyzing from a trace file) or starts the compiler with incorrect preprocessing flags, because it sets the wrong compiler type.
COMPILE_NAME
is used to filter compiler commands when you parse a trace file (strace_out
).
COMPILE_TYPE
specifies the compiler's type. This allows the analyzer to to run the file preprocessing command correctly. Possible values: gcc
, clang
, keil5
, keil5gnu
, keil6
, tiarmcgt
, cl
, clangcl
, gccarm
, iararm_v7_orolder
, iararm
, qcc
, xc8
. If the compiler type is not specified, the analyzer tries to determine it by name or via the version information. If it is impossible to determine the type, the analyzer will consider it as GCC (on Linux, macOS) or cl (on Windows).
For example, the following command tells the analyzer that there is an unknown CustomCompiler compiler in the strace_out file and it should be considered as GCC:
pvs-studio-analyzer analyzer -f /path/to/strace_out \
-C CustomCompiler=gcc
‑‑env [VAR=VALUE] (-E [VAR=VALUE])
specifies the environment variable to be preprocessed with.
‑‑rules-config [FILE] (-R [FILE])
is a configuration file of diagnostic rules (*.pvsconfig
). Find more information about the configuration of diagnostic rules here.
‑‑intermodular
enables the intermodular analysis mode. In this mode, the analyzer performs a deeper code analysis by increasing the analysis time.
How to use the configuration file
The configuration file allows you to set general parameters for running the analyzer.
You can create a separate configuration file for the project and put specific parameters in this file.
The parameters are written as the "key=value" pair. You can use the #
symbol to comment on lines.
Possible values in the configuration file:
exclude-path
specifies a path (absolute or relative) to files or directories that should be excluded from the analysis. The relative path is expanded relative to the directory containing the configuration file. You can also use the command shell templates (glob) ?
and *
to specify the path.
analysis-paths defines the behavior of the analysis on the specified paths. The available modes:
skip-analysis
specifies the directory from which files do not need to be checked. These are usually directories of system files or included libraries.skip-settings
ignores the settings located in the source files and.pvsconfig
files by the specified path.isolate-settings
sets the directory for which the settings should be isolated. When this mode is enabled, the configuration files of diagnostic rules (.pvsconfig
) from parent directories will not be applied to translation units in the specified directory and its subdirectories. Both absolute and relative paths are supported. Relative paths are expanded via the current directory. Theglob
patterns cannot be used for this mode.skip
ignores the settings located in the source files and.pvsconfig
files by the specified path. Warnings generated for source code files by the specified path or mask will also be filtered.
timeout
specifies the time (in seconds) after which the analysis of a translation unit will be terminated. By default, one file should be analyzed for no more than 10 minutes (600 seconds). If you pass here the 0 value, the time limit will be removed. Please note: removing the time limit may cause the analysis to hang.
platform
specifies the platform to use. Possible options: win32
, x64
, Itanium
, linux32
, linux64
, macOS
, pic8
, tms
.
preprocessor
specifies the preprocessor to use. Possible options: visualcpp
, clang
, gcc
, bcc
, bcc_clang64
, iar
, keil5
, keil5_gnu
, c6000
.
lic-file
specifies an absolute or relative path to the license file. The path is expanded relative to the directory containing configuration file.
analysis-mode
specifies the type of warnings to be issued. The type is a bit mask. Using the bitwise OR, you can specify several groups of diagnostic rules that will be used in the analysis.
Possible values:
0
: Full analysis;1
: 64-bit diagnostic rules;4
: General analysis diagnostic rules (recommended and used by default);8
: Diagnostic rules of micro-optimizations;16
: Diagnostic rules for customer specific requests;32
: Diagnostic rules for code compliance with MISRA recommendations;64
: Diagnostic rules for code compliance with AUTOSAR recommendations;128
: Diagnostic rules for code compliance with OWASP recommendations.
output-file
is an absolute or relative path to the file to which the analyzer operation report should be written. By default, the report will be written to the PVS-Studio.log
file. Relative paths will be expanded relative to the directory from which you want to run the analysis. When the analysis is parallelized, all PVS-Studio core processes write a report in a single file. Therefore, this file remains locked until the last process writes information to it.
funsigned-char
specifies the signedness of the char type. If it is true—the analyzer treats char
as an unsigned type, otherwise it treats it as signed.
rules-config
specifies the path to the diagnostics configuration file (*.pvsconfig
). The path is expanded relative to the directory containing configuration file.
no-noise
allows you to exclude all warnings of the 3rd level of certainty. If it is true, warnings of this level will not appear in the analyzer's report. By default, it is false.
errors-off specifies the list of deactivated diagnostic rules. The list is separated by a space or comma: V1024 V591
or V1024, V591
. The diagnostic rule in this list will be excluded from the analysis.
analyzer-errors
specifies the list of active diagnostic rule. The list is separated by a space or comma: V1024 V591
or V1024, V591
. Only the diagnostic rule in this list will be used during the analysis.
Note: The list of deactivated diagnostic rules specified in errors-off
has a higher priority than the list of activated ones.
Example: Let's specify the basic parameters for running PVS-Studio in the configuration file and run the project analysis by passing our *.cfg
file to the analyzer.
File MyProject.cfg
:
lic-file=~/.config/PVS-Studio/PVS-Studio.lic
exclude-path=*/tests/*
exclude-path=*/lib/*
exclude-path=*/third-party/*
platform=linux64
preprocessor=clang
analysis-mode=4
output-file=~/MyProject/MyProject.PVS-Studio.log
Let's start the analysis (assuming that there is strace_out
or compile_commands.json
in the current directory):
pvs-studio-analyzer analyze --cfg ./MyProject.cfg ....
Using the configuration file makes it easier to integrate the analyzer with CI/CD systems.
Baselining analysis results and filtering reports according to suppression rules
The PVS-Studio analyzer has the message suppression mechanism that can be used in the following scenarios:
- when you introduce the analyzer into your project and PVS-Studio issues a lot of warnings on the code. You can suppress these warnings and return to them when you have time. In this case, PVS-Studio will issue warnings only on new code during regular checks;
- when you want to suppress the analyzer's false positives without modifying source code files.
The pvs-studio-analyzer
allows you to suppress analyzer messages and filter a report by excluding suppressed messages.
How to baseline messages
To baseline messages, the analyzer creates a special file (by default, it is named suppress_file.suppress.json
). This file contains analyzer warnings that should be ignored.
The general syntax for running the baselining mode is as follows:
pvs-studio-analyzer suppress [-a <TYPES>] [-f <FILE...>] \
[-v <NUMBER...>] [-o <FILE>] [log]
[log]
is a path to the report created by the analyzer. By default, the analyzer searches for the PVS-Studio.log
file in the current directory.
‑‑analyzer [TYPES] (-a [TYPES])
allows you to specify groups and levels of warnings to move to the suppress file. This parameter takes a string of the Diagnostic group: Diagnostic level [, Diagnostic level]*
form. Diagnostic group defines a specific group (possible groups: GA, 64, OP, CS, MISRA, AUTOSAR, OWASP), and Diagnostic level, the level of certainty (possible levels: 1, 2, 3). You can combine various groups and levels via the ;
or +
character.
For example: the GA:1;OP:1
string tells the analyzer to suppress only diagnostic rules with the first level of certainty from general analysis and micro-optimization groups. By default, the analyzer filters warnings by all groups and levels.
‑‑file [FILE...] (-f [FILE...])
allows you to suppress all warnings for a specific file:
pvs-studio-analyzer suppress -f test.cpp -f test2.cpp /path/to/PVS-Studio.log
or for a specific line in a specific file:
pvs-studio-analyzer suppress -f test.cpp:15 /path/to/PVS=Studio.log
‑‑warning [NUMBER...] (-v[NUMBER...])
specifies the number of diagnostic rules, warnings of which should be suppressed:
pvs-studio-analyzer suppress -v512 /path/to/PVS-Studio.log
‑‑output [FILE], (-o[FILE])
specifies a path and a name for the suppress file. By default, PVS-Studio writes all information about suppressed warnings to the suppress_file.suppress.json
file in the current directory.
Note: You can combine the ‑‑file
, ‑‑warning
, and ‑‑analyzer
flags. For example, the following command will suppress all V1040 warnings on line 12:
pvs-studio-analyzer suppress -f test.cpp:12 -v1040 /path/to/PVS-Studio.log
The following command suppresses all GA diagnostic rules of the 3rd level for the file:
pvs-studio-analyzer suppress -f test.cpp -a 'GA:3' /path/to/PVS-Studio.log
How to filter a report by the suppress file
You can filter out warnings that were previously placed in the suppress file from the analyzer's report. To do this, execute the following command:
pvs-studio-analyzer filter-suppressed [-o <FILE>] [-s <FILE>] [log]
‑‑output [FILE] (-o [FILE])
is a name of the file to write the filtered report. By default, if the flag is not set, pvs-studio-analyzer
will overwrite the existing report file.
‑‑suppress-file [FILE] (-s [FILE])
is a message suppression file. By default, pvs-studio-analyzer
searches for the suppress_file.suppress.json
file in the startup directory.
[log]
is a report file from which warnings should be filtered
The pvs-studio-analyzer
utility always searches for the suppress file in the analysis mode to create a filtered report. If the file has a non-standard path, you can specify it via the -s
flag:
pvs-studio-analyzer analyze -s /path/to/suppress_file.suppress.json ....
Exit codes
The utility can return the following values:
0: Analysis completed successfully;
1: Various internal errors. For example, file preprocessing failed or an error occurred during trace file parsing. Usually, a crash with such code is followed by an error description in stdout
.
2: The license expires in less than a month;
3: An internal error occurred during the analysis of some files;
5:The license has expired;
6: The utility was started with the –disableLicenseExpirationCheck
flag, and received a new license valid for more than 30 days.
7: No compilation units were accepted for the analysis. For example, all files have been excluded from the analysis by user settings or by marking all source code directories as system header paths.
8: No compiler invocations were detected. For example, an unknown compiler is used or the generated project structure file (strace_out
or compile commands database) is corrupted.
In the trace mode, by default, the analyzer returns the same code it received from the executed program. If you want the analyzer to ignore the real exit code and always return 0, you can use the -i
flag or -- ignoreTraceReturnCode
, for example:
pvs-studio-analyzer trace -i -- ....