Skip to Main Content
CMake 接入 clang-tidy:从开关到可维护门禁Back to Top

CMake 接入 clang-tidy:从开关到可维护门禁

3 minutes

CMake 接入 clang-tidy

clang-tidy 适合当工程的静态门禁:比编译器警告更靠近「现代 C++ 习惯」和「API 误用」。难点通常不在「能不能跑」,而在 CMake 怎么挂、配置怎么钉死、本地与 CI 怎么一致

本文按「能开关 → 能复现 → 能长期维护」三条线整理。


1. 先弄清两种挂法

1.1 编译时自动跑(CMAKE_CXX_CLANG_TIDY

CMake 会把 tidy 绑到每个编译命令上:改一个 .cpp,编译时顺带分析。

option(CXX_ENABLE_CLANG_TIDY "Attach clang-tidy to CXX compile" OFF)

if(CXX_ENABLE_CLANG_TIDY)
  find_program(CLANG_TIDY_EXE NAMES clang-tidy REQUIRED)
  set(CMAKE_CXX_CLANG_TIDY
    "${CLANG_TIDY_EXE};-warnings-as-errors=*"
    CACHE STRING "" FORCE)
endif()

适合:小目标 / 模块化工程 / 想强制「脏代码编不过」

代价:全量编译变慢;增量时只扫改过的 TU。

1.2 独立目标 / 脚本扫(不绑编译)

compile_commands.json + 自己的 clang-tidy 调用:

cmake -S . -B build -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
clang-tidy -p build src/**/*.cpp

适合:大仓库、只想在 PR 跑、或 tidy 与构建解耦


2. 配置文件:把规则钉在仓库里

优先放仓库根或 cmake/ 旁的 .clang-tidy,避免每人本机「默认检查集」不一致。

最小可用示例:

Checks: >
  -*,
  bugprone-*,
  modernize-use-nullptr,
  modernize-use-override,
  readability-identifier-naming,
  performance-unnecessary-copy-initialization
WarningsAsErrors: ''
HeaderFilterRegex: '.*'
FormatStyle: none

经验:

做法建议
一上来开 *噪音爆炸,团队会关掉 tidy
bugprone-* + 少量 modernize 起步易落地
WarningsAsErrors: '*'适合 CI 门禁;本地可先关
第三方头文件HeaderFilterRegex 限定自己的源码树

3. 与 CMake 分层基建的常见接法

现代工程常把开关放在 CompilerWarnings.cmake / ProjectSetup.cmake 一类文件里,例如:

# cmake/CompilerWarnings.cmake(示意)
function(cxx_enable_clang_tidy target)
  if(NOT CXX_ENABLE_CLANG_TIDY)
    return()
  endif()
  find_program(CLANG_TIDY_EXE NAMES clang-tidy)
  if(NOT CLANG_TIDY_EXE)
    message(WARNING "clang-tidy not found; skip")
    return()
  endif()
  set_target_properties(${target} PROPERTIES
    CXX_CLANG_TIDY "${CLANG_TIDY_EXE};--config-file=${CMAKE_SOURCE_DIR}/.clang-tidy")
endfunction()

C++23 modules / import std 工程:确认 tidy 用的 clang 版本与编译器同源(Homebrew LLVM 场景尤其常见),否则会出现「编译过、tidy 解析失败」。


4. 本地工作流(推荐)

export PATH="/opt/homebrew/opt/llvm/bin:$PATH"

# 默认关闭 tidy,日常编译快
cmake -S . -B build -G Ninja
cmake --build build

# 需要门禁时显式打开
cmake -S . -B build -G Ninja -DCXX_ENABLE_CLANG_TIDY=ON
cmake --build build

把「默认 OFF、CI ON」写进 README / preset,比强迫人人开 tidy 更可持续。


5. CI 门禁清单


6. 小结

目标做法
开发时提醒本机可选 CXX_ENABLE_CLANG_TIDY=ON
合入质量CI 打开 + warnings-as-errors
长期可维护仓库内 .clang-tidy + 窄检查集逐步加宽

下一篇会写 .cmake 模块拆分与 CMakePresets.json 的使用技巧,和 tidy 开关如何一起放进 preset。