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 don't 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 don't 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 can't 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.
'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 — diagnostics for 64-bit errors.
- GA — general analysis diagnostics.
- OP – diagnostics for micro-optimizations.
- CS — diagnostics for specific user requests.
- MISRA — diagnostics for checking the code for compliance with the MISRA standards.
- AUTOSAR — diagnostics for checking the code for compliance with the AUTOSAR standards.
- OWASP — diagnostics 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.
‑‑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 — do not show 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 isn't 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 don't 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 – update the dependency information and run the analysis,
- skip-analysis – 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's 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's 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 diagnostics configuration file (*.pvsconfig). Find more information about the configuration of diagnostics 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.
'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 diagnostics that will be used in the analysis.
Possible values:
- '0' – full analysis;
- '1' – 64-bit diagnostics;
- '4' – general analysis diagnostics (recommended and used by default);
- '8' – diagnostics of micro-optimizations;
- '16' – diagnostics for customer specific requests;
- '32' – diagnostics for code compliance with MISRA recommendations;
- '64' – diagnostics for code compliance with AUTOSAR recommendations;
- '128' – diagnostics 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's 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 3-rd level of certainty. If it's true — warnings of this level won't appear in the analyzer's report. By default, it's false.
errors-off specifies the list of deactivated diagnostics. The list is separated by a space or comma: 'V1024 V591' or 'V1024, V591'. The diagnostics in this list will be excluded from the analysis.
analyzer-errors specifies the list of active diagnostics. The list is separated by a space or comma: 'V1024 V591' or 'V1024, V591'. Only the diagnostics in this list will be used during the analysis.
Please note: the list of deactivated diagnostics 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's 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 diagnostics 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, 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 diagnostics of the 3-rd 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 -- ....