CMake与Visual Studio 2017 C ++核心准则检查器(CppCoreCheck)的集成

Flo*_*ers 5 c++ cmake visual-studio static-code-analysis cpp-core-guidelines

我目前尝试使用生成器将Visual Studio 2017 的C ++核心准则检查器(CppCoreCheck)与元生成系统CMake集成在一起Visual Studio 15 2017 Win64

以下示例说明了我的方法(我尝试将CMake源代码精简到最小)。

首先,我将所有编译器开关添加到了构建目标,以使用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"
    )
Run Code Online (Sandbox Code Playgroud)

我正在使用以下内容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
  }
}
Run Code Online (Sandbox Code Playgroud)

仅此示例就足以在目标编译期间调用CppCoreCheck:

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
Run Code Online (Sandbox Code Playgroud)

生成以下警告:

"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
Run Code Online (Sandbox Code Playgroud)

为了禁止显示警告,第三方库Boost必须提供其他设置。

这里有个要注意的地方:CppCoreCheck在其配置的某些部分依赖于环境变量,更确切地说是:

  • Esp.Extensions:应设置为 CppCoreCheck.dll
  • Esp.AnnotationBuildLevel:应设置为 ignore
  • CAExcludePath:应设置为要忽略的目录路径(例如C:\boost-1.68.0-x64\include\boost-1_68;C:\foo;

有什么方法可以使用CMake在编译阶段设置环境变量吗?我目前不知道一种方法:

  1. 设置环境变量如下的CMakeLists.txt没有工作,因为环境变量只在配置阶段有效:

    set(ENV{Esp.Extensions} "CppCoreCheck.dll")
    set(ENV{Esp.AnnotationBuildLevel} "ignore")
    set(ENV{CAExcludePath} "C:\\boost-1.68.0-x64\\include\\boost-1_68")
    
    Run Code Online (Sandbox Code Playgroud)
  2. 在目标的构建阶段使用自定义命令似乎也不起作用:

    add_custom_command(TARGET ${args_TARGET}
      PRE_BUILD
      COMMAND ${CMAKE_COMMAND} -P "${PROJECT_SOURCE_DIR}/set_cppcorecheck.cmake"
      )
    
    Run Code Online (Sandbox Code Playgroud)

    注意:set_cppcorecheck.cmake包含set上面列出的三个命令。

如果在控制台中通过调用build命令设置了环境变量,则它可以正常工作。

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
Run Code Online (Sandbox Code Playgroud)

但这是丑陋的,无法扩展。原因:我的目标是CAExcludePath由构建系统自动填充。

我已阅读https://www.reddit.com/r/cpp/comments/6u2myo/how_to_use_the_c_core_guidelines_checker_outside,其中描述了相同的问题(没有解决方案)。

有谁能解决我的问题(在“正常”目标的编译阶段设置环境变量)?