Skip to content

ci: integrate clang-tidy checks - #239

Open
kilinchange wants to merge 1 commit into
masterfrom
style/clang-tidy-bootstrap
Open

kilinchange wants to merge 1 commit into
masterfrom
style/clang-tidy-bootstrap

Conversation

@kilinchange

@kilinchange kilinchange commented Sep 23, 2026 •

Copy link
Copy Markdown
Collaborator

背景

本 PR 为 InfiniTrain 接入 clang-tidy 静态检查基础设施,提供统一的规则配置、本地执行入口和 CI 检查流程,并支持通过 clang-tidy plugin 扩展项目自定义检查规则。

本次接入以建立基础能力为主,不尝试一次性覆盖完整的 Google C++ Style。对于 clang-tidy 已有且能够准确表达的规则优先直接复用;对于需要额外语义判断、容易产生误报的规范,后续按需通过项目自定义 check 实现。

主要改动

1. 新增 clang-tidy 配置

新增仓库级 .clang-tidy 配置,当前启用:

infinitrain-no-member-definitions-in-headers
readability-identifier-naming

其中:

  • infinitrain-no-member-definitions-in-headers 为 InfiniTrain 自定义规则;
  • readability-identifier-naming 为 clang-tidy 内置规则,本次仅选择能够明确映射到现有代码规范的命名项作为使用示例,避免通过复杂豁免规则强行模拟 clang-tidy 无法准确表达的语义。

例如枚举值使用 constant-style 命名:

enum class Mode {
  kOff,
  kModule,
  kFunction,
};

所有 clang-tidy diagnostics 当前统一作为 error 处理。

2. 新增 InfiniTrain clang-tidy plugin

在 tools/clang_tidy/ 下新增项目自定义 clang-tidy plugin,并实现:

infinitrain-no-member-definitions-in-headers

该规则用于约束 InfiniTrain 项目中的普通成员函数实现位置。

对于不需要在头文件中提供实现的成员函数,应在头文件中保留声明,并将具体实现放到对应源文件中,以减少头文件中的实现细节和不必要的编译依赖。

以下情况不会触发该规则:

  • 函数模板;
  • 类模板中的成员函数;
  • constexpr / consteval 函数;
  • = default / = delete 函数;
  • 编译器隐式生成的成员函数;
  • Lambda;
  • 宏展开产生的函数定义;
  • 配置允许的空函数体。

该规则属于 InfiniTrain 项目自身的额外约束,并非用于完整复刻 Google C++ Style。

3. 新增统一执行脚本

新增:

scripts/clang_tidy.py

作为本地开发和 CI 的统一 clang-tidy 执行入口,支持:

  • 检测当前提交是否包含 clang-tidy 相关修改;
  • 基于 compilation database 执行全量 clang-tidy;
  • 本地按 Git diff 过滤修改行对应的 diagnostics;
  • 过滤不参与检查的 translation unit;
  • 对多个 translation unit 重复产生的 header diagnostics 进行去重;
  • 同时保存原始报告和去重后的报告。

检查报告输出到:

build/lint/clang-tidy-report/clang-tidy-raw.txt
build/lint/clang-tidy-report/clang-tidy-unique.txt

其中去重仅用于改善报告可读性,不改变 clang-tidy 的原始退出状态。

4. 接入 GitHub Actions

新增 clang-tidy workflow,在以下场景运行:

  • Pull Request;
  • push 到 master。

CI 首先执行轻量的变更检测。不存在 C/C++、CMake、clang-tidy 配置或相关基础设施修改时,直接跳过后续依赖安装和静态检查。

存在相关修改时,CI 会:

  1. 拉取 submodule;
  2. 安装 LLVM/Clang 18;
  3. 构建 InfiniTrain clang-tidy plugin;
  4. 生成 CPU-only compilation database;
  5. 对过滤后的项目 C/C++ translation unit 执行 clang-tidy 全量扫描;
  6. 上传 clang-tidy 原始报告和去重报告。

CI 的变更检测仅用于决定是否执行 clang-tidy,实际执行时仍对 compilation database 中符合条件的 translation unit 进行完整扫描。

当前扫描排除:

third_party/
build/
tests/**/*_compile_fail.cc

当前 compilation database 为 CPU-only,不包含 CUDA translation unit,因此纯 .cu 修改不会触发本轮 clang-tidy 扫描。CUDA 静态检查后续在具备对应 toolchain 和 compilation database 后单独接入。

5. 补充使用文档

新增:

docs/code_quality.md

说明:

  • 当前启用的 clang-tidy 规则;
  • 项目自定义 clang-tidy plugin;
  • CI 触发和扫描范围;
  • compilation database 生成方式;
  • 本地全量检查和增量检查方法;
  • clang-tidy report;
  • 新增自定义 check 的开发流程。

本地运行

构建 clang-tidy plugin:

cmake -S tools/clang_tidy -B build/clang-tidy-plugin -G Ninja \
  -DCMAKE_BUILD_TYPE=Release \
  -DCMAKE_C_COMPILER=clang-18 \
  -DCMAKE_CXX_COMPILER=clang++-18 \
  -DLLVM_DIR=/usr/lib/llvm-18/lib/cmake/llvm \
  -DClang_DIR=/usr/lib/llvm-18/lib/cmake/clang

cmake --build build/clang-tidy-plugin

生成 compilation database:

cmake -S . -B build/lint -G Ninja \
  -DCMAKE_CXX_COMPILER=clang++-18 \
  -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
  -DCMAKE_CXX_SCAN_FOR_MODULES=OFF \
  -DUSE_CUDA=OFF \
  -DUSE_NCCL=OFF \
  -DUSE_OMP=OFF \
  -DBUILD_TEST=ON

执行与 CI 相同的全量检查:

python3 scripts/clang_tidy.py \
  --all \
  --build-dir build/lint \
  --load-plugin build/clang-tidy-plugin/InfiniTrainTidy.so

检查当前分支相对于 master 修改行产生的 diagnostics:

python3 scripts/clang_tidy.py \
  --ref origin/master \
  --build-dir build/lint \
  --load-plugin build/clang-tidy-plugin/InfiniTrainTidy.so

@kilinchange
kilinchange force-pushed the style/clang-tidy-bootstrap branch 10 times, most recently from 95cf552 to c2eb7d6 Compare September 24, 2026 10:59
location = source_manager.getSpellingLoc(location);
if (source_manager.isInSystemHeader(location) ||
source_manager.isWrittenInMainFile(location)) {
return;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里不能直接跳过主文件。本地增量检查会把修改的 .h 文件直接传给 clang-tidy,此时头文件本身就是主文件,其中的违规成员函数也会被跳过,导致本地检查漏报、CI 全量检查才报错。建议区分头文件和源文件,不要仅根据是否为主文件来跳过。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants