Closed
[enhancement] hcomm 仓新增 .clang-tidy 函数复杂度控制配置 #752
严正行Add on  Aug 5Closed at  12 days ago
严正行
严正行Collaborators
Aug 5 Create

问题描述

当前 hcomm 仓已有 .clang-format 做代码格式化,但缺少函数复杂度控制类静态检查配置。hcomm 作为 CANN 通信基础库,代码规模大、模块依赖复杂,长期演进过程中可能积累复杂度较高的函数,影响代码可维护性和可测试性。

本 issue 提议在 hcomm 仓根目录新增 .clang-tidy 配置文件,启用 Clang-Tidy 的 readability-function-size 和 readability-function-cognitive-complexity 检查器,配合 infrastructure 仓 CI 后续接入 clang-tidy 检查时读取本配置。

上游 issue

本 issue 是 infrastructure 仓 issue #229 的 hcomm 仓侧配套实施:

建议方案

在 hcomm 仓根目录新增 .clang-tidy 配置文件,阈值遵循华为 C/C++ 编程规范:

检查器 配置项 阈值 检测内容
readability-function-size LineThreshold 50 行 函数行数(华为编程规范)
readability-function-size StatementThreshold 50 函数语句数量
readability-function-size BranchThreshold 15 控制语句数量
readability-function-size ParameterThreshold 6 函数参数数量
readability-function-size NestingThreshold 4 嵌套深度
readability-function-cognitive-complexity Threshold 25 认知复杂度

配置文件示例

---
Checks: >-
  -*,
  readability-function-size,
  readability-function-cognitive-complexity
CheckOptions:
  - key: readability-function-size.LineThreshold
    value: "50"
  - key: readability-function-size.StatementThreshold
    value: "50"
  - key: readability-function-size.BranchThreshold
    value: "15"
  - key: readability-function-size.ParameterThreshold
    value: "6"
  - key: readability-function-size.NestingThreshold
    value: "4"
  - key: readability-function-cognitive-complexity.Threshold
    value: "25"
  - key: readability-function-cognitive-complexity.IgnoreMacros
    value: "true"
HeaderFilterRegex: ".*"
FormatStyle: "none"
WarningsAsErrors: ""

实施步骤

  1. 在 hcomm 仓根目录新增 .clang-tidy 配置文件
  2. WarningsAsErrors 留空(告警模式,不阻断编译),存量代码不立即阻断
  3. 配合 infrastructure 仓 CI 后续接入 clang-tidy 检查(渐进式启用:告警模式 → 观察期 → 门禁模式)

注意事项

  1. 本 PR 仅新增配置文件,不修改任何源码,不影响编译
  2. CMakeLists.txt 未引用 CMAKE_CXX_CLANG_TIDY,加配置文件不会触发本地编译跑 clang-tidy
  3. 存量代码可能存在超阈值函数,后续配合 infrastructure CI 增量检查模式逐步收敛
  4. 部分底层算法函数如需更高复杂度,可用 // NOLINT(readability-function-size) 豁免

参考文档

适用范围

  • 仓库:cann/hcomm
  • 提议归属 SIG:runtime
  • 申请人:@yanzhenghang
likedislike
严正行严正行Collaborators
Aug 5 Associated pull request
LeewisCollaborators
Aug 6 Comments:

/assign @yanzhenghang

likedislike
CANN-robotCANN-robotCollaborators
Aug 6 Assign yanzhenghang as responsible person
严正行严正行Collaborators
Aug 27 Added label: tech-debt
LLeewisCollaborators
Sep 2 associated Kanban: HCCL
LLeewisCollaborators
Sep 2 associated Kanban: HCOMM
LLeewisCollaborators
Sep 8 changed custom category from 任务 to 需求
LeewisCollaborators
12 days ago Comments:

✅ Issue 已解决

该 Issue 已通过以下 PR 修复并合入:

关联 PR

  • PR #4438:[enhancement] hcomm 仓新增 .clang-tidy 增量拦截脚本 + build.sh 集成

修改方案

本 PR 超出 Issue 原始提议范围,不仅新增了 .clang-tidy 配置文件,还实现了完整的增量拦截机制,使函数复杂度检查从"配置就绪"升级为"实际生效"。

1. 新增 .clang-tidy 配置文件

  • 启用 readability-function-size 和 readability-function-cognitive-complexity 两个检查器
  • 阈值遵循华为 C/C++ 编程规范:函数行数 50 / 语句数 50 / 分支数 15 / 参数数 6 / 嵌套深度 4 / 认知复杂度 25
  • WarningsAsErrors 留空,阻断逻辑由脚本控制而非 clang-tidy 自身,实现存量代码不阻塞
  • HeaderFilterRegex 锚定到 src|include|pkg_inc|test|experimental 路径段边界,兼容相对路径与 compile database 绝对路径

2. 新增增量拦截脚本 scripts/clang_tidy_check.py + .sh

  • 通过 git diff TARGET_BRANCH...HEAD 获取变更文件和新增行号范围
  • 调用 clang-tidy -p build <变更文件> 执行检查(依赖 compile_commands.json)
  • 核心过滤逻辑:只保留"告警行在新增行内"的违规,存量函数的告警被过滤掉,实现"只拦新增代码"
  • 违规时 exit 1 阻断构建;无 clang-tidy / 无 compile_commands.json / 无 base-ref 时 fallback 跳过(exit 0),不误阻断
  • 入口通过 git rev-parse --show-toplevel 解析仓库根并 os.chdir,消除 cwd 依赖
  • 违规判定增加告警文件与被检文件的归一化绝对路径比对,防止头文件告警误拦

3. build.sh 集成

  • 构建后调用 clang_tidy_check.sh,通过 ENABLE_CLANG_TIDY_CHECK 环境变量控制(默认 on)
  • CMake 增加 -DCMAKE_EXPORT_COMPILE_COMMANDS=ON,解决两仓 CMake 未导出 compile_commands.json 导致检查从未真正执行的问题

4. 仓内单测 scripts/clang_tidy_check_test.py

  • 8 个用例覆盖:-U0 hunk 解析(含纯删除场景)、cwd 无关性、告警 file/line/check 解析、compile db 归一化

拦截语义明确:

场景 定义行是否新增 告警行是否在新增行 结果
新增超阈值函数 是 是 拦截 exit 1
修改存量超阈值函数 1 行 否 否(告警在定义行) 过滤 exit 0
新增合规函数 是 无告警 通过 exit 0
NOLINT 豁免 — — 通过 exit 0

经验沉淀

1. 静态检查配置落地必须配套"增量拦截"机制

  • 问题模式:仅新增 .clang-tidy 配置文件而不实现拦截逻辑,检查形同虚设——CMakeLists.txt 未引用 CMAKE_CXX_CLANG_TIDY 时本地编译不会触发 clang-tidy,CI 也无法自动读取
  • 修复策略:配置文件只定义"规则",还需独立脚本实现"拦截语义"。关键设计是区分新增代码与存量代码:通过 git diff 提取新增行号范围,只保留告警行落在新增行内的违规,存量代码不阻塞
  • 预防措施:引入静态检查时,同步设计增量拦截方案(告警模式 → 观察期 → 门禁模式渐进式启用),避免一次性启用导致存量代码大面积报错阻断

2. compile_commands.json 是 clang-tidy 生效的隐性前置依赖

  • 问题模式:clang-tidy 需要 compile_commands.json 获取编译参数(include 路径、宏定义等),但很多 CMake 项目默认不导出该文件,导致 clang-tidy 检查静默跳过或产出无效结果
  • 排查思路:如果 clang-tidy 检查"看起来通过"但实际未生效,首先确认 build/compile_commands.json 是否存在且内容完整
  • 预防措施:CMake 配置中始终加 -DCMAKE_EXPORT_COMPILE_COMMANDS=ON;拦截脚本中显式检查该文件是否存在,缺失时 fallback 跳过并打印醒目提示

3. 拦截脚本的健壮性设计:fallback 优先,不误阻断

  • 问题模式:CI 环境可能缺少 clang-tidy 二进制、compile_commands.json、base-ref 等依赖,脚本硬依赖会导致非代码问题误阻断 CI
  • 修复策略:所有外部依赖缺失时 exit 0 跳过而非 exit 1 阻断;clang-tidy 返回码非 0 时打印 WARNING 并计入汇总而非静默 PASS;base-ref 按 upstream → origin 顺序回退尝试
  • 预防措施:拦截脚本设计为"最佳努力"模式——有条件则严格检查,无条件则安全跳过;同时配套仓内单测覆盖核心解析逻辑(diff hunk 解析、告警解析、路径归一化),防止脚本自身 bug 导致漏检或误拦

4. 头文件告警的路径归一化处理

  • 问题模式:clang-tidy 对 .cc 文件检查时可能报出其 include 的头文件中的告警,如果仅按行号匹配新增行,头文件告警会误判为新增代码违规
  • 修复策略:违规判定时增加告警文件路径与被检文件路径的归一化绝对路径比对,只有告警来自被检文件本身(而非头文件)时才计入违规
  • 预防措施:处理文件路径时统一使用 os.path.realpath 归一化,避免相对路径/绝对路径/符号链接导致的路径不匹配问题

此总结由 AI 基于 Issue 与关联 PR 内容自动生成。

likedislike
LLeewisCollaborators
12 days ago Added label: resolved
LLeewisCollaborators
12 days ago Close issue
严正行严正行Collaborators
9 days ago Associated pull request
严正行严正行Collaborators
5 days ago Associated pull request
严正行严正行Collaborators
4 days ago Associated pull request
LLeewisCollaborators
4 days ago Deleted associated pull request: [bugfix] clang-tidy 增量检查浅克隆自愈:修复 CI 检出深度不足导致的门禁静默失效