C/C++/Objective-C analysis is officially registered as CWE Compatible.
- Any version of Clang, clang-cl, GCC, and Microsoft C/C++ compilers
- Any version of the Intel compiler for Linux and macOS
- ARM5 and ARM6 compilers
- IAR compilers for ARM, Atmel AVR32, Atmel AVR, Renesas H8, Renesas RL78, Renesas RX, Renesas V850, Texas Instruments MSP430, and for 8051
- QNX compilers
- Texas Instruments compilers for ARM (
tiarmclang), C2000, C6000, C7000, MSP430, and PRU
- Wind River Diab and GCC compilers
- Microchip MPLAB XC8, XC16, and XC32 Compilers
- Compilers based wholly on GCC, including Linaro GCC
Note that statically linked compilers on Linux and macOS are only supported through Compilation Database. For example, some versions of Texas Instruments compilers on Linux.
Supported Language Standards
- C89, C99, C11, C18, C++03, C++11, C++14, C++17, and C++20 standards
- GNU extensions
Supported Runtime Environments
- Microsoft Windows on x86-64
- Linux on x86-64
- macOS with version 10.14.3 and later on x86-64, and Apple Silicon
Analysis of C/C++/Objective-C projects requires the SonarScanner CLI.
For a C/C++/Objective-C analysis to be accurate, the analyzer needs to understand how the code is meant to be compiled. Compilation options, like macro definitions and include directories, can have a huge impact on the generated code and consequently on the analysis results.
There are two alternative ways to provide the build configuration to the analyzer:
- SonarSource Build Wrapper
- Compilation Database
Choosing The Right Tool
The general recommendation is to use Build Wrapper unless you have a good reason not to.
Reasons To Use Build Wrapper
- Build Wrapper enforces running the build before the analysis, which ensures that the code is in a good shape for analysis: the code is compilable, the configuration file is not outdated, and the generated source files are available during the analysis.
- In case your build relies on environment variables, Build Wrapper, unlike Compilation Database, stores these variables and uses them during the analysis.
Reasons To Use Compilation Database
- Your build system is not supported by Build Wrapper.
- You don't want to run a clean build of your project, which is required by Build Wrapper, before the analysis.
- You are on macOS (any version) with Apple Silicon hardware (ARM architecture).
- You are on macOS >= 13 with Intel hardware (x86-64 architecture).
Analysis Steps Using Build Wrapper
Analysis configuration example projects with Build Wrapper are available on GitHub.
Build Wrapper is a tool developed by SonarSource to collect information in a JSON file about your build configuration during build time. To run Build Wrapper, you should prepend your clean build command with the Build Wrapper executable.
When you wrap your build command with the Build Wrapper, it will run the given command and gather all the configuration required for a correct analysis of C/C++/Objective-C projects, such as macro definitions and include directories. The Build Wrapper does not impact your build; it merely monitors it and writes what it learns into files in a directory you specify.
If you are using the GitHub Action for C and C++, the build wrapper files will be automatically installed.
You should download the Build Wrapper directly from SonarCloud:
- Download Build Wrapper for Linux
- Download Build Wrapper for macOS
- Download Build Wrapper for Windows
Unzip the downloaded Build Wrapper and configure it in your
PATH because doing so is just more convenient.
- Execute Build Wrapper as a prefix to your usual clean build command. A clean build command should always build the project from scratch. The examples below use
MSBuild, but any build tool that performs a full build can be used:
// example for linux build-wrapper-linux-x86-64 --out-dir build_wrapper_output_directory make clean all // example for macOS build-wrapper-macosx-x86 --out-dir build_wrapper_output_directory xcodebuild clean build // example for Windows build-wrapper-win-x86-64.exe --out-dir build_wrapper_output_directory MSBuild.exe /t:Rebuild /nodeReuse:False
At the end of your build, a build-wrapper-dump.json file should be generated in the specified output directory. This file contains information about the translation units that were built by your build command. Any file that doesn't end up in a compiled translation unit will not be analyzed. As a consequence, source files that are not compiled and header files that are not included in any compiled source file will not be analyzed.
Executing build-wrapper doesn't interfere with your build command. There is no need to build a second time without a build-wrapper. Just make one build and wrap it up.
* Add the property
sonar.cfamily.build-wrapper-output in the
sonar-project.properties file at the root of your project. You should set it to the path of the *Build Wrapper* output directory relative to the project directory (`build_wrapper_output_directory` in these examples).
sonar.projectKey=myFirstProject sonar.projectName=My First C++ Project sonar.projectVersion=1.0 sonar.sources=src sonar.cfamily.build-wrapper-output=build_wrapper_output_directory sonar.sourceEncoding=UTF-8 sonar.host.url=YourSonarCloud/SonarQubeURL
It is recommended to gather all your code trees in a subdirectory of your project to avoid analyzing irrelevant source files like files generated by your build tool. You can specify this subdirectory by setting the property
sonar.sources accordingly. In this example, we named it
- Execute the SonarScanner (
sonar-scanner) from the root directory of your project.
For more SonarScanner related options, consult SonarScanner CLI.
- Follow the link provided at the end of the analysis to browse your project's quality metrics in the UI.
- The Build Wrapper collects information about the build, including absolute file paths (source files, standard headers, libraries, etc...). Later on, SonarScanner uses this information and needs to access those paths. While this is straightforward while running these two steps on the same host, it is worth considering when using any sort of containerization. A consequence of this is that C / C++ / Objective-C analysis is NOT supported by SonarScanner CLI Docker image.
- The Build Wrapper generates the files build-wrapper.log and build-wrapper-dump.json in its output directory. Both these files contain a dump of the environment. In some contexts, it can be a security concern. Whereas the former is a log file and is not needed for the analysis to run, the latter is necessary and can be neither displaced nor discarded.
Building with Bazel
Bazel recommends that you use the --batch parameter when running in a continuous build context. When using the BuildWrapper, you are in such context.
Also, you need to deactivate the sandbox mechanism of Bazel so that the compiled file paths can be retrieved after the compilation phase.
Here is an example of the BuildWrapper command with Bazel parameters on macOS:
build-wrapper-macosx-x86 --out-dir bw bazel --batch build --spawn_strategy=local --strategy=Genrule=local --bazelrc=/dev/null //main:hello-world
Building with MsBuild
Instead of starting new nodes when building your code, MsBuild can reuse previously launched build nodes. In that case, the Build Wrapper will not be able to monitor files compiled on these nodes. Therefore, we advise disabling this feature by using the nodeReuse:False command-line option.
Analysis Steps Using Compilation Database
Compilation Database is a JSON file format introduced by the LLVM project. It contains the compile commands used to build a project. It can be generated by tools like CMake and Ninja.
First, generate the Compilation Database file.
Then, add the property
sonar.cfamily.compile-commands in the sonar-project.properties file at the root of your project. You should set it to the path of the Compilation Database file relatively to the project directory (
compile_commands.json in these examples).
Here is an example sonar-project.properties file:
sonar.projectKey=myFirstProject sonar.projectName=My First C++ Project sonar.projectVersion=1.0 sonar.sources=src sonar.cfamily.compile-commands=compile_commands.json sonar.sourceEncoding=UTF-8 sonar.host.url=YourSonarCloud/SonarQubeURL
It is recommended to gather all your code trees in a subdirectory of your project to avoid analyzing irrelevant source files like third-party dependencies. You can specify this subdirectory by setting the property
sonar.sources accordingly. In this example, we named it
Execute the SonarScanner (
sonar-scanner) from the root directory of your project:
sonar-scanner. For more SonarScanner related options, consult SonarScanner CLI. Follow the link provided at the end of the analysis to browse your project's quality metrics in the UI.
- The analysis environment should be the same as the build environment; the analyzer may need to access the build-related environment variables. For example, when using Microsoft Visual C++ compiler, make sure to execute the analysis from the same Visual Studio Developer Command Prompt you use to build your project. The command prompt sets some environment variables, like
INCLUDE, that need to be set during the analysis.
- Make sure that the tool you are using generates the right compile commands. To do so, you should verify that the Compilation Database contains your actual build commands. Also, you can run one of the compilation commands and verify that it succeeds.
Discover and update the C/C++/Objective-C specific properties in: Project Administration > General Settings > C / C++ / Objective-C
sonar.tests property is used to identify the directories containing test source files. Identifying test files helps the analyzers to tune their rules. For example, the analyzers can enable test-specific rules and disable rules that don't make sense in the context of testing.
The C/C++/Objective-C analyzer currently analyzes main and test source files in the same way. Consequently,
sonar.tests is not yet supported; the analyzer ignores it.
If you wish to analyze test source files, you should include them in the
The C/C++/Objective-C analyzer automatically caches the analysis results on the server. The cached analysis results speed up subsequent analyses by analyzing the only things that have changed between the two analyses.
- For branch analysis, an analysis cache is stored on the server per branch.
- For pull request analysis, the cache of the base branch is used and not persisted.
- If no cache is found, the cache of the Main branch is used.
However, in some cases, the analyzer can be configured to store the analysis results on the filesystem. You should consider changing the cache storage to the filesystem when the server cache size becomes a concern or when you want to optimize the cache lifecycle based on your project workflow.
You can customize the analysis cache storage with the following properties:
serverset the cache storage to the server, this is the default value.
fsset the cache storage to the local filesystem.
sonar.cfamily.analysisCache.path=relative_or_absolute_path_to_cache_location, this property should only be declared when the mode is set to
fs. Please note that each project should use a dedicated path. To fully benefit from this feature, you should configure your CI system to persist the cache path between runs.
Deprecated analysis cache properties
The old analysis properties
sonar.cfamily.cache.path are deprecated and are scheduled for removal in SonarQube 10.0. You should use the new properties instead.
Parallel Code Scan
By default, the analyzer tries to parallelize the analysis of compilation units; it spawns as many jobs as logical CPUs available on the machine.
If required, it is possible to customize the number of scheduled parallel jobs by configuring the property
sonar.cfamily.threads=n at the scanner level, where
n is an integer indicating the maximum number of parallel jobs.
You should consider setting the
sonar.cfamily.threads property only when the automatic detection of the number of logical CPUs cannot detect the desired number. A typical example is when the analysis should not consume all the available computing resources to leave room for other tasks running in parallel on the same machine.
When setting the
sonar.cfamily.threads property, you should set it to a value less or equal to the number of logical CPUs available. Over-committing doesn't accelerate the analysis and can even slow it down.
Targeted C++ standard
The analyzer targets a specific version of the C++ language to tune the rules in the activated quality profile. This reporting standard is used to:
- Suppress rules that cannot be applied. For example, rules that suggest using
c++20features while the code is compiled with
- Adjust rules' messages to suggest the proper fix according to the standard used. For example, a rule that suggests using
c++20will be tuned to suggest using
std::any_ofwith an older standard.
By default, the reporting standard version is the version that is used to compile the code. This is ideal for most projects. However, there are some edge cases where there is a need to use a reporting standard that is different from the compilation standard. For this reason, we provide the following scanner property to adjust the reporting standard:
This property is only recommended to be used in the case where a project has to comply with a standard older than the one it is compiled with. This can happen if:
- The compiler doesn't allow to set a specific standard. For example, MSVC doesn't allow specifying a standard older than
- The project wants to be compiled with the latest standard while still being compliant with an older standard.
Solution with a Mix of C# and C++
When you have a Solution made of C++ and C#, in order to both use the Build Wrapper and have an accurate analysis of the C# code, you must use the SonarScanner for MSBuild. The SonarScanner for MSBuild does not handle the
sonar-project.properties files, so the Build Wrapper output directory will have to be set during the MSBuild
Note that in this scenario, source code stored in shared folders, not considered as a "Project" by Visual Studio, won't be scanned.
- Download and install both the SonarScanner for MSBuild and the Build Wrapper (see Prerequisites section).
- Execute the SonarScanner for MSBuild
beginstep with the Build Wrapper output parameter
- Add execution of Build Wrapper to your normal MSBuild build command
- Execute the SonarScanner for MSBuild
endstep to complete the analysis
SonarScanner.MSBuild.exe begin /k:"cs-and-cpp-project-key" /n:"My C# and C++ project" /v:"1.0" /d:sonar.cfamily.build-wrapper-output="build_wrapper_output_directory" build-wrapper-win-x86-64.exe --out-dir build_wrapper_output_directory MSBuild.exe /t:Rebuild /nodeReuse:False SonarScanner.MSBuild.exe end
Measures for Header Files
Each time we analyze a header file as part of a compilation unit, we compute for this header the measures: statements, functions, classes, cyclomatic complexity, and cognitive complexity. That means that each measure may be computed more than once for a given header. In that case, we store the largest value for each measure.
Language-Specific Rule Tags
On top of the built-in rule tags, a few additional rule tags are specific to C/C++/Objective-C rules.
C++ Standard Version Related Rule Tags
Some rules are relevant only since a specific version of the C++ standard. These rules will run only when analyzing a C++ code compiled against a later or equal standard version. Tags
since-c++20 mark these rules for the corresponding C++ standard version. C++ rules not carrying any of these three tags have been running since C++98.
Implementation Related Rule Tags
full-project: this tag is for rules that do cross translation units analysis. For these rules to work properly, it is important to analyze the entire project. Excluding part of the project from the analysis will impact the accuracy of these rules: it might lead to false positives or false negatives.
symbolic-execution: this tag is for rules that reason about the state of the program. They usually work together to find path-sensitive bugs and vulnerabilities. Once a fatal state of the program is reached, one issue will be raised, and the symbolic execution analysis of the current path will stop. For that reason, it is not recommended to evaluate these rules independently of each other as it might give a false sense of undetected issues. It is important to keep in mind that we are always working on improving these rules, as symbolic execution can never be perfect.
External standard Rule Tags
- based-on-misra: this tag is for rules that address the same kind of issues as MISRA rules, but that do not entirely correspond to what MISRA specifies (usually to make them less strict).
- C and C++ sample projects for SonarCloud and GitHub
- C and C++ sample projects for SonarCloud and GitLab
- Test Coverage (CPPUnit, GCOV, llvm-cov, Visual Studio, Bullseye)
- Test Coverage sample projects