CMake 添加用于调用 clang 分析器的目标

CMake add target for invoking clang analyzer

本文关键字:分析器 目标 clang 调用 添加 用于 CMake      更新时间:2023-10-16

我基本上想实现与 http://blog.alexrp.com/2013/09/26/clangs-static-analyzer-and-automake 相同的目标,但使用 CMake。

analyze_srcs = foo.c
analyze_plists = $(analyze_srcs:%.c=%.plist)
CLEANFILES = $(analyze_plists)
$(analyze_plists): %.plist: %.c
  @echo "  CCSA  " $@
  @$(COMPILE) --analyze $< -o $@
analyze: $(analyze_plists)
.PHONY: analyze

所以你可以跑

make analyze
make clean

我想我需要使用add_custom_command/add_custom_target并以某种方式更改该目标的"对象文件"扩展名。

然后获取生成的文件列表,以将它们传递给脚本以将它们合并为 1 个输出文件。

谁能指出我正确的方向?

运行 cmake 时可以使用scan-build

scan-build cmake /path/to/source
scan-build make

scan-build设置CCCXXcmake选取的环境变量。

我找到了一种方法:

function(add_clang_static_analysis target)
    get_target_property(SRCs ${target} SOURCES)
    add_library(${target}_analyze OBJECT EXCLUDE_FROM_ALL ${SRCs})
    set_target_properties(${target}_analyze PROPERTIES
                          COMPILE_OPTIONS "--analyze"
                          EXCLUDE_FROM_DEFAULT_BUILD true)
endfunction()

将 clang 的 plist 文件(以这种方式获得扩展名 .o(合并到一个报告中仍然是打开的($<TARGET_OBJECTS:objlibtarget>

以下解决方案的缺点是编译和分析整个项目,而不是特定目标。

set(on_side_build_path ${CMAKE_BINARY_DIR}/clang_static_analysis)
set(scan_build_path scan-build)
set(reports_path ${CMAKE_BINARY_DIR}/clang_static_analysis_reports)
# Creates clean directory where the analysis will be built.
add_custom_target(clang_static_analysis_prepare
    COMMAND ${CMAKE_COMMAND} -E rm -rf ${on_side_build_path}
    COMMAND ${CMAKE_COMMAND} -E make_directory ${on_side_build_path}
    WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)
# Runs the analysis from the path created specifically for that task. Use 'my own' project source directory as the source directory.
add_custom_target(clang_static_analysis
    # scan-build wants Debug build, for better analysis.
    COMMAND ${scan_build_path} ${CMAKE_COMMAND} ${CMAKE_SOURCE_DIR} -DCMAKE_BUILD_TYPE=Debug
    COMMAND ${scan_build_path}
                -v -v -o ${reports_path} 
                ${CMAKE_COMMAND} --build .
    WORKING_DIRECTORY ${on_side_build_path}
)
# Run the *_prepare target always before the analysis
add_dependencies(clang_static_analysis clang_static_analysis_prepare)
调用

它:

cmake --build . --target clang_static_analysis

奖励#1:允许自定义工具链工作

scan-build注入CCCXX环境变量以指定替换的编译器,这些编译器是ccc-analyzerc++-analyzer。定义CMAKE_C_COMPILERCMAKE_CXX_COMPILER时,将忽略CCCXX变量。要支持scan-build,您需要做的是指向CMAKE_C*_COMPILER变量以使用环境中的变量(如果已定义(。因此,将其放在您的工具链文件中:

set(CMAKE_C_COMPILER some/path/to/c_compiler)
set(CMAKE_Cxx_COMPILER some/path/to/cxx_compiler)

将其替换为:

if(DEFINED ENV{CC})
    set(CMAKE_C_COMPILER $ENV{CC})
else()
    set(CMAKE_C_COMPILER some/path/to/c_compiler)
endif()
if(DEFINED ENV{CXX})
    set(CMAKE_CXX_COMPILER $ENV{CXX})
else()
    set(CMAKE_CXX_COMPILER some/path/to/cxx_compiler)
endif()

奖励#2:使用LLVM工具链中的扫描构建

如果您的自定义工具链是 LLVM,那么您很可能希望使用工具链中的 scan-build 命令。要启用它,只需使用 cmake 的缓存变量定义工具链路径的路径:

set(LLVM_TOOLCHAIN_PATH "some/path/here" CACHE PATH "Path to the LLVM toolchain") 

或从命令行:

cmake -DLLVM_TOOLCHAIN_PATH=some/path/here ...

,然后重用自定义目标中的路径:

set(scan_build_path ${LLVM_TOOLCHAIN_PATH}/bin/scan-build)

奖励#3:添加测试命令

enable_testing应在add_test前调用。 必须从项目的顶级CMakeLists.txt调用enable_testing(),以便ctest解析测试路径。

add_test(
    NAME clang_static_analysis
    COMMAND ${CMAKE_COMMAND} --build . --target clang_static_analysis
)

像这样运行它:

# Fire configure and generate stages
cmake ../source/dir
ctest -R clang_static_analysis --verbose