I'm trying to statically analyze my code via Clang's static code analyzer tool scan-build
and when I run the code with scan-build g++
command, it provides me a bug report, but when I'm trying to do same thing with CMake and the scan-build make
command, it tells me that no bugs were found.
I've already tried to substitute CC
and CXX
variables by bash export command, used --use_cc
and --use_c++
flags and built separate targets using scan-build make TARGET
. All of this did not lead me to the correct solution and I'm afraid that scan-build
could not work with CMake/make.
Here is a simple example.
CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
set(CMAKE_C_COMPILER "usr/bin/clang")
set(CMAKE_CXX_COMPILER "usr/bin/clang++")
set(CMAKE_AR "usr/bin/llvm-ar")
set(CMAKE_LINKER "usr/bin/llvm-ld")
set(CMAKE_NM "usr/bin/llvm-nm")
set(CMAKE_OBJDUMP "usr/bin/llvm-objdump")
set(CMAKE_RANLIB "usr/bin/llvm-ranlib")
project(scan-build-test)
add_executable(${PROJECT_NAME} main.cpp)
main.cpp
#include <iostream>
int main()
{
int *a;
std::cout << a << std::endl;
}
scan-build g++ main.cpp -o main
scan-build: Using 'usr/bin/clang-8' for static analysis main.cpp:6:2: warning: 1st function call argument is an uninitialized value
std::cout << a << std::endl;
^~~~~~~~~~~~~~
1 warning generated.
scan-build: 1 bug found.
scan-build: Run 'scan-view /tmp/scan-build-2019-05-30-134021-30676-1' to examine bug reports.`
cmake .
scan-build make
scan-build: Using 'usr/bin/clang-8' for static analysis
[ 50%] Building CXX object CMakeFiles/scan-build-test.dir/main.cpp.o
[100%] Linking CXX executable scan-build-test
[100%] Built target scan-build-test
scan-build: Removing directory '/tmp/scan-build-2019-05-30-134302-30720-1' because it contains no reports.
scan-build: No bugs found.
All static analysis (and other source code related) instruments for C/C++ need to replicate the compilation process for each source file in your project. In order to get everything right, they need to have all the compilation options (like macro definitions and include directories) that were used during the real compilation.
There are a few ways to do it. Without getting into much details about other approaches, here's how scan-build
does it.
It substitutes the real compiler with its wrapper executable, receives all the compiler commands from the build system, does its job and forwards all the same options to the real compiler.
That's why direct SET commands for compiler in your CMakeLists.txt
file prevented scan-build
from doing its trick. It will work with both gcc and clang, but you should not hardcode them and use CC
and CXX
environment variables instead.