Integration of CMake with the Visual Studio 2017 C++ Core Guidelines Checker (CppCoreCheck)
Asked Answered
C

1

8

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 to CppCoreCheck.dll
  • Esp.AnnotationBuildLevel: Should be set to ignore
  • 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:

  1. 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")
    
  2. 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 three set 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)?

Chimpanzee answered 4/9, 2018 at 14:2 Comment(2)
I don't think this is possible (without resorting to extremely complicated measures like moving the whole invocation of all build commands inside a custom command), and I don't know of any other build tool that would require something like this. Imho this should be a feature request for the MSVC people: Make those options configurable from the command line.Hancock
Yeah, I thought a second about wrapping all the build related commands via 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
P
0

I think the solution is not implemented yet. Also been searching for it. I think this should fix it: https://gitlab.kitware.com/cmake/cmake/-/issues/19682

I do see hints that maybe you can work around it with https://devblogs.microsoft.com/cppblog/customizing-your-environment-with-visual-c-and-open-folder/

Paule answered 31/5, 2021 at 14:6 Comment(1)
Welcome to SO, even if links may answer the question, it is better to provide explanations. stackoverflow.com/help/how-to-answer for answering good practicesHerra

© 2022 - 2024 — McMap. All rights reserved.