I currently try to integrate the C++ Core Guidelines Checker (CppCoreCheck) of Visual Studio 2017 with the meta build system CMake using the Visual Studio 15 2017 Win64
generator.
The following example illustrates my approach (I've tried to strip down the CMake source code to a minimum).
First I've added all compiler switches to the build target to analyze with CppCoreCheck:
cmake_minimum_required(VERSION 3.12)
project(cppcorecheck-example)
find_package(Boost REQUIRED MODULE)
add_executable(app main.cpp)
target_link_libraries(app PRIVATE Boost::boost)
target_compile_options(app
PRIVATE
"/analyze"
"/analyze:WX-"
"/analyze:log" "cppcorecheck.xml"
"/analyze:stacksize" 16384
"/analyze:max_paths" 256
"/analyze:ruleset" "CppCoreCheckRules.ruleset"
"/analyze:plugin EspXEngine.dll"
)
I'm using the following main.cpp
:
#include <boost/system/error_code.hpp>
int main() {
int arr[10]; // warning C26494
int* p = arr; // warning C26485
{
int* q = p + 1; // warning C26481
p = q++; // warning C26481
}
}
That example alone is sufficient to invoke CppCoreCheck during target compilation:
cmake -G"Visual Studio 15 2017 Win64" -H. -B_build -DBOOST_ROOT="C:/boost-1.68.0-x64" -DBoost_USE_STATIC_LIBS=ON
cmake --build _build --target app
The following warnings are generated:
"c:\dev\cppcorecheck-example\_build\app.vcxproj" (Standardziel) (1) ->
(ClCompile Ziel) ->
c:\boost-1.68.0-x64\include\boost-1_68\boost\system\error_code.hpp(237): warning C26440: Function 'boost::system::error_category::std_category::std_category' can be declared 'noexcept' (f.6: http://go.microsoft.com/fwlink/?linkid=853927). [c:\dev\cppcorecheck-example\_build\app.vcxproj]
c:\boost-1.68.0-x64\include\boost-1_68\boost\system\error_code.hpp(244): warning C26412: Do not dereference an invalid pointer (lifetimes rule 1). 'return of name' was invalidated at line 243 by '(unknown)'.: Lines: 241, 243, 244 [c:\dev\cppcorecheck-example\_build\app.vcxproj]
c:\boost-1.68.0-x64\include\boost-1_68\boost\system\error_code.hpp(319): warning C26432: If you define or delete any default operation in the type 'class boost::system::error_category', define or delete them all (c.21: http://go.microsoft.com/fwlink/?linkid=853922). [c:\dev\cppcorecheck-example\_build\app.vcxproj]
c:\boost-1.68.0-x64\include\boost-1_68\boost\system\error_code.hpp(494): warning C26412: Do not dereference an invalid pointer (lifetimes rule 1). 'return of system_category' was invalidated at line 493 by '(unknown)'.: Lines: 491, 493, 494 [c:\dev\cppcorecheck-example\_build\app.vcxproj]
c:\boost-1.68.0-x64\include\boost-1_68\boost\system\error_code.hpp(499): warning C26412: Do not dereference an invalid pointer (lifetimes rule 1). 'return of generic_category' was invalidated at line 498 by '(unknown)'.: Lines: 496, 498, 499 [c:\dev\cppcorecheck-example\_build\app.vcxproj]
c:\boost-1.68.0-x64\include\boost-1_68\boost\system\error_code.hpp(763): warning C26490: Don't use reinterpret_cast (type.1: http://go.microsoft.com/fwlink/p/?LinkID=620417). [c:\dev\cppcorecheck-example\_build\app.vcxproj]
c:\boost-1.68.0-x64\include\boost-1_68\boost\system\error_code.hpp(753): warning C26440: Function 'boost::detail::throws' can be declared 'noexcept' (f.6: http://go.microsoft.com/fwlink/?linkid=853927). [c:\dev\cppcorecheck-example\_build\app.vcxproj]
c:\boost-1.68.0-x64\include\boost-1_68\boost\system\error_code.hpp(768): warning C26412: Do not dereference an invalid pointer (lifetimes rule 1). 'return of throws' was invalidated at line 768 by '(unknown)'.: Lines: 767, 768 [c:\dev\cppcorecheck-example\_build\app.vcxproj]
c:\boost-1.68.0-x64\include\boost-1_68\boost\system\error_code.hpp(824): warning C26472: Don't use a static_cast for arithmetic conversions. Use brace initialization, gsl::narrow_cast or gsl::narow (type.1: http://go.microsoft.com/fwlink/p/?LinkID=620417). [c:\dev\cppcorecheck-example\_build\app.vcxproj]
c:\boost-1.68.0-x64\include\boost-1_68\boost\system\error_code.hpp(825): warning C26490: Don't use reinterpret_cast (type.1: http://go.microsoft.com/fwlink/p/?LinkID=620417). [c:\dev\cppcorecheck-example\_build\app.vcxproj]
c:\boost-1.68.0-x64\include\boost-1_68\boost\system\error_code.hpp(822): warning C26440: Function 'boost::system::hash_value' can be declared 'noexcept' (f.6: http://go.microsoft.com/fwlink/?linkid=853927). [c:\dev\cppcorecheck-example\_build\app.vcxproj]
c:\boost-1.68.0-x64\include\boost-1_68\boost\system\error_code.hpp(889): warning C26499: Could not find any lifetime tracking information for '*pc2': Lines: 896, 869, 872, 874, 875, 877, 878, 880, 881, 880, 883, 886, 887, 886, 889 [c:\dev\cppcorecheck-example\_build\app.vcxproj]
c:\boost-1.68.0-x64\include\boost-1_68\boost\system\error_code.hpp(874): warning C26496: The variable 'bn' is assigned only once, mark it as const (con.4: https://go.microsoft.com/fwlink/p/?LinkID=784969). [c:\dev\cppcorecheck-example\_build\app.vcxproj]
c:\boost-1.68.0-x64\include\boost-1_68\boost\system\error_code.hpp(880): warning C26496: The variable 'bn' is assigned only once, mark it as const (con.4: https://go.microsoft.com/fwlink/p/?LinkID=784969). [c:\dev\cppcorecheck-example\_build\app.vcxproj]
c:\boost-1.68.0-x64\include\boost-1_68\boost\system\error_code.hpp(889): warning C26496: The variable 'bn' is assigned only once, mark it as const (con.4: https://go.microsoft.com/fwlink/p/?LinkID=784969). [c:\dev\cppcorecheck-example\_build\app.vcxproj]
c:\boost-1.68.0-x64\include\boost-1_68\boost\system\error_code.hpp(919): warning C26499: Could not find any lifetime tracking information for '*pc2': Lines: 930, 899, 902, 904, 905, 907, 908, 910, 911, 910, 913, 916, 917, 916, 919 [c:\dev\cppcorecheck-example\_build\app.vcxproj]
c:\boost-1.68.0-x64\include\boost-1_68\boost\system\error_code.hpp(904): warning C26496: The variable 'bc' is assigned only once, mark it as const (con.4: https://go.microsoft.com/fwlink/p/?LinkID=784969). [c:\dev\cppcorecheck-example\_build\app.vcxproj]
c:\boost-1.68.0-x64\include\boost-1_68\boost\system\error_code.hpp(910): warning C26496: The variable 'bc' is assigned only once, mark it as const (con.4: https://go.microsoft.com/fwlink/p/?LinkID=784969). [c:\dev\cppcorecheck-example\_build\app.vcxproj]
c:\boost-1.68.0-x64\include\boost-1_68\boost\system\error_code.hpp(919): warning C26496: The variable 'bc' is assigned only once, mark it as const (con.4: https://go.microsoft.com/fwlink/p/?LinkID=784969). [c:\dev\cppcorecheck-example\_build\app.vcxproj]
c:\dev\cppcorecheck-example\main.cpp(6): warning C26494: Variable 'arr' is uninitialized. Always initialize an object (type.5: http://go.microsoft.com/fwlink/p/?LinkID=620421). [c:\dev\cppcorecheck-example\_build\app.vcxproj]
c:\dev\cppcorecheck-example\main.cpp(7): warning C26485: Expression 'arr': No array to pointer decay (bounds.3: http://go.microsoft.com/fwlink/p/?LinkID=620415). [c:\dev\cppcorecheck-example\_build\app.vcxproj]
c:\dev\cppcorecheck-example\main.cpp(10): warning C26481: Don't use pointer arithmetic. Use span instead (bounds.1: http://go.microsoft.com/fwlink/p/?LinkID=620413). [c:\dev\cppcorecheck-example\_build\app.vcxproj]
c:\dev\cppcorecheck-example\main.cpp(11): warning C26481: Don't use pointer arithmetic. Use span instead (bounds.1: http://go.microsoft.com/fwlink/p/?LinkID=620413). [c:\dev\cppcorecheck-example\_build\app.vcxproj]
c:\dev\cppcorecheck-example\main.cpp(5): warning C26440: Function 'main' can be declared 'noexcept' (f.6: http://go.microsoft.com/fwlink/?linkid=853927). [c:\dev\cppcorecheck-example\_build\app.vcxproj]
24 Warnung(en)
0 Fehler
Verstrichene Zeit 00:00:05.77
In order to suppress the warnings form the third-party library Boost additional settings have to be provided.
Here's the catch: CppCoreCheck relies on environment variables for some parts of its configuration, more precisely:
Esp.Extensions
: Should be set toCppCoreCheck.dll
Esp.AnnotationBuildLevel
: Should be set toignore
CAExcludePath
: Should be set to the directory paths to ignore (e.g.C:\boost-1.68.0-x64\include\boost-1_68;C:\foo;
)
Is there any way to set environment variables for the compilation phase using CMake? I am currently not aware of an approach:
Setting environment variables as follows in the
CMakeLists.txt
does not work, since the environment variables are only valid during the configure phase:set(ENV{Esp.Extensions} "CppCoreCheck.dll") set(ENV{Esp.AnnotationBuildLevel} "ignore") set(ENV{CAExcludePath} "C:\\boost-1.68.0-x64\\include\\boost-1_68")
Using a custom command during the build phase of the target does not seem to work too:
add_custom_command(TARGET ${args_TARGET} PRE_BUILD COMMAND ${CMAKE_COMMAND} -P "${PROJECT_SOURCE_DIR}/set_cppcorecheck.cmake" )
Note:
set_cppcorecheck.cmake
contains the threeset
commands listed above.
It does properly work if the environment variables are set in the console invoking the build command, e.g.
SET Esp.Extensions=CppCoreCheck.dll
SET Esp.AnnotationBuildLevel=ignore
SET CAExcludePath=C:\dev\native\boost\boost-1.68.0-x64\include\boost-1_68
cmake --build _build --target app
But this is ugly and does not scale. Reason: My goal is to populate CAExcludePath
automatically by the build system.
I've read https://www.reddit.com/r/cpp/comments/6u2myo/how_to_use_the_c_core_guidelines_checker_outside where the same problem has been described (without a solution).
Does anyone have a solution for my problem (setting an environment variable for the compilation phase of a "normal" target)?
add_custom_command
, but discarded that thought very fast (that would be madness, imo). Thanks for your suggestion to provide a feature request. I will request that feature on visualstudio.uservoice.com and add a link to the request here later. Either CLI arguments or a configuration file would be much much better. – Chimpanzee