CMake本身不支持“编译器插件”,因其仅为构建系统,不解析语法或加载插件;所谓集成实为透传参数(如-Xclang -load)或添加自定义检查任务(如cppcheck、clang-tidy)。

为什么 CMake 本身不支持“编译器插件”这个概念
CMake 不是编译器,它不解析语法、不执行语义检查,也不加载插件。所谓“集成编译器插件”,实际是指在构建流程中插入额外的静态分析命令(比如 cppcheck、clang-tidy),或通过编译器前端参数(如 -Xclang -load)让 Clang 加载自定义 AST 插件——但后者要求你已编译好插件 so/dll,并且 CMake 只负责把参数透传过去。
绝大多数开发者真正需要的,不是写 LLVM 插件,而是让 cppcheck 或 clang-tidy 在 cmake --build 过程中自动运行一次,并把结果暴露在终端或日志里。这和“插件”无关,本质是任务编排。
用 add_custom_target 实现 cppcheck 静态检查步骤
这是最轻量、最可控的方式:不侵入编译逻辑,不拖慢常规构建,但能一键触发检查。适用于 Windows + MinGW 或 Linux/macOS 环境。
-
cppcheck必须已安装并可在命令行直接调用(cppcheck --version能成功) - 在项目根目录的
CMakeLists.txt末尾添加:
add_custom_target(check-code
COMMAND cppcheck --enable=all --inconclusive --suppress=missingIncludeSystem
--project=${CMAKE_BINARY_DIR}/compile_commands.json
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMENT "Running cppcheck static analysis"
)
-
--project=...参数依赖compile_commands.json,所以需先启用导出:set(CMAKE_EXPORT_COMPILE_COMMANDS ON) - 若不用 JSON,可直接指定源码路径:
COMMAND cppcheck --enable=all src/ include/ - 执行检查只需:
cmake --build build --target check-code(Windows 下用mingw32-make check-code)
Clang-Tidy 怎么在 CMake 中启用并绑定到 build 步骤
Clang-Tidy 是更贴近“编译器集成”的选择,它能读取编译选项、理解模板实例化,还能自动修复部分问题。但它对 MinGW 工具链支持有限,更适合 Clang/LLVM 环境(如 MSVC+Clang-CL 或 WSL+Clang)。
- 确保
clang-tidy可执行文件在 PATH 中(clang-tidy --version成功) - 在
CMakeLists.txt中开启支持:
set(CMAKE_CXX_CLANG_TIDY "clang-tidy;-checks=-*,cppcoreguidelines-*,-cppcoreguidelines-pro-bounds-array-to-pointer-decay")
set(CMAKE_C_CLANG_TIDY ${CMAKE_CXX_CLANG_TIDY})
- 上述配置会让每次
cmake --build编译.cpp文件时,自动跑一遍 clang-tidy;警告会混在编译输出里(不是独立 target) - 若想只检查不编译,加
-quiet并配合add_custom_target;若要生成 HTML 报告,得自己封装脚本调用clang-tidy -export-fixes - 注意:MinGW-w64 默认用 GCC,不带 clang-tidy 支持;强行指定会失败,报错类似
clang-tidy: command not found或unsupported compiler
Clang 自定义 AST 插件的极简接入方式(仅限 Clang 环境)
如果你真写了 .so 插件(比如检测某个内部宏展开规则),CMake 唯一要做的就是把加载指令塞进编译参数。它不验证插件是否存在,也不管符号导出是否正确——这些全由 Clang 运行时决定。
- 假设插件路径为
${CMAKE_SOURCE_DIR}/plugins/libMyChecker.so,且已通过clang++ -Xclang -load -Xclang libMyChecker.so验证可用 - 在
CMakeLists.txt中添加:
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Xclang -load -Xclang $<mychecker_plugin>")
# 或更稳妥的绝对路径写法:
# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Xclang -load -Xclang ${CMAKE_SOURCE_DIR}/plugins/libMyChecker.so")
endif()</mychecker_plugin>
-
mychecker_plugin是一个 dummy target,仅用于生成路径(可选);多数人直接写死绝对路径更可靠 - 插件必须与当前 Clang 版本 ABI 兼容,否则编译时会静默失败或崩溃;建议用
llvm-config --version和插件编译时的版本严格对齐 - 这种做法无法跨平台,MSVC/MinGW 完全不识别
-Xclang参数,CMake 不报错但编译器会忽略或报错
真正难的从来不是怎么写那几行 CMake,而是插件本身的 ABI 稳定性、错误处理粒度、以及如何让它在 CI 中稳定产出可读报告——这些 CMake 一概不管。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











