26

我基本上想实现与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 个输出文件。

谁能指出我正确的方向?

4

3 回答 3

31

scan-build运行时可以使用cmake

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

scan-build设置CCCXX拾取的环境变量cmake

于 2014-02-14T17:18:30.510 回答
6

我找到了一个方法:

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>?)。

于 2014-02-06T14:20:29.617 回答
2

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

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_COMPILER变量将被忽略。您需要做的支持是指向变量以使用来自环境的变量(如果已定义)。所以在你的工具链文件中有这个:CMAKE_CXX_COMPILERCCCXXscan-buildCMAKE_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 工具链中的 scan-build

如果您的自定义工具链是 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_testenable_testing()必须从项目的顶层调用CMakeLists.txtforctest来解析测试路径。

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
于 2021-09-27T13:11:15.020 回答