如何高效地在项目中对所有CPP文件运行clang-tidy?CI脚本静态分析提速方案咨询
我来分享几个能大幅加快clang-tidy运行速度的实用技巧,亲测有效:
1. 缩小头文件分析范围(最立竿见影的优化)
你当前用--header-filter=.*会让clang-tidy分析所有头文件——包括系统头文件、vendor目录下的第三方头文件,这些完全不是你需要检查的目标,会浪费大量时间在无关代码上。
修改成只匹配你项目自己的头文件:
--header-filter="^./engine/src/|^./editor/src/"
这样clang-tidy只会分析你项目源码目录下的头文件,跳过第三方和系统头文件,能直接砍掉大部分不必要的分析时间。
2. 利用编译数据库替代手动传递编译参数
你现在手动给clang-tidy传递--std=c++17、一堆-isystem参数,不仅容易出错,clang-tidy每次都要重新解析这些参数,额外增加开销。
生成compile_commands.json编译数据库(如果用CMake,只需添加编译选项):
cmake -B build -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
然后在脚本里用--p=compile_commands.json替代后面的--及所有编译参数,clang-tidy会直接读取每个文件的精确编译配置,既准确又高效。
3. 精简clang-tidy分析规则
默认启用的规则里可能包含一些非常耗时的深度分析规则(比如部分clang-analyzer-*系列),或者你根本不需要的规则。
明确指定你需要的规则,比如只保留代码规范、性能、bug检查类的核心规则:
--checks="-*,cppcoreguidelines-*,performance-*,bugprone-*,modernize-*"
-*表示禁用所有默认规则,后面的逗号分隔列表是你要启用的规则组,这样能大幅减少clang-tidy的分析工作量。
另外,clang-tidy对GLSL着色器(.frag/.vert)的支持并不完善,建议用专门的工具(比如glslangValidator)来检查着色器,把它们从find命令中移除,进一步减少分析范围。
4. 启用多线程并行处理
虽然你说想先优化静态分析本身,但并行处理是快速缩短总耗时的关键手段。利用xargs的-P参数,让clang-tidy同时用多个进程处理文件:
xargs -P $(nproc) -I{} ...
$(nproc)会自动获取CI机器的CPU核心数,最大化利用硬件资源,能把总时间砍到原来的1/N(N为核心数)。
5. 缓存与增量分析(CI专属优化)
在GitHub Actions中,你可以缓存compile_commands.json文件和clang-tidy的缓存目录(通过--cache-dir指定),这样重复运行时能复用之前的分析结果。
如果你的CI流程允许,还可以只分析本次PR中变更的CPP文件,而不是全量分析:
git diff --name-only origin/main HEAD | grep -E "\.cpp$" | xargs ...
这样日常PR检查的耗时会大幅降低,全量分析可以每周定时跑一次即可。
6. 升级clang-tidy版本
新版本的clang系列工具通常会优化静态分析的性能,比如clang 15、16在clang-tidy的速度上有不少提升。你当前用的是14,尝试升级到更高版本,可能会带来意外的速度提升。
修改后的示例脚本
结合以上优化点,脚本可以改成这样:
#!/bin/sh if [ -z $1 ]; then CMD=clang-tidy else CMD=clang-tidy-$1 fi # 仅分析项目CPP文件,并行处理,利用编译数据库,缩小头文件范围 find engine/src editor/src -type f -name "*.cpp" | xargs -P $(nproc) -I{} $CMD \ --header-filter="^./engine/src/|^./editor/src/" \ --p=compile_commands.json \ --checks="-*,cppcoreguidelines-*,performance-*,bugprone-*,modernize-*" \ --quiet {}
内容的提问来源于stack exchange,提问作者Gasim

