您现在的位置是:首页 > 经典句子

C/C++ 静态代码检测工具 Clang-tidy 简易教程:安装、使用、配合 cmake 使用、加入 CI/CD 流程等

作者:纳雷武时间:2024-04-11 17:10:58分类:经典句子

简介  文章浏览阅读2.2k次,点赞19次,收藏22次。最近尝试将 Clang-tidy 加入到项目中,以便加强代码规范。本文纪录在这一过程中积累的关于 Clang-tidy 的知识,涵盖安装、使用、cmake 和 CI/CD 实践等内容。_run-clang-tid

点击全文阅读

文章目录

前言Clang-tidy 是什么?Clang-tidy 检测流程安装使用Clang-tidy 命令clang-tidy-diff.py 脚本 实践检查项编译中开启 clang-tidy 检查跳过部分代码的检查将 clang-tidy 加入 CI/CD 参考


前言

最近尝试将 Clang-tidy 加入到项目中,以便加强代码规范。本文纪录在这一过程中积累的关于 Clang-tidy 的知识,涵盖安装、使用、cmake 和 CI/CD 实践等内容。

Clang-tidy 是什么?

Clang-tidy是一个强大的开源工具,用于自动执行C++源代码的静态分析。它是Clang项目的一部分,可以检查代码中的错误、风格问题、性能问题等,并且可以自动修复一些常见问题。

Clang-tidy的一个重要特性是它的可扩展性。你可以编写自己的检查器来检查特定的编程错误或风格问题。这使得Clang-tidy成为一个非常强大的工具,可以定制以适应你的编程风格和需求。

Clang-tidy还可以与其他工具集成,如编辑器和持续集成系统,以自动执行代码检查和修复。这使得它成为提高代码质量和减少编程错误的重要工具。

Clang-tidy 检测流程

Clang-tidy检测一个文件的过程大致如下:

预处理:Clang-tidy首先对源代码进行预处理,解析出宏定义、头文件包含等信息。语法分析:然后,Clang-tidy对预处理后的代码进行语法分析,生成抽象语法树(AST)。静态分析:接着,Clang-tidy对AST进行静态分析,检查可能的编程错误、风格问题等。报告和修复:最后,Clang-tidy报告检测到的问题,并尝试自动修复一些问题。

安装

Macos
推荐使用 pip 进行安装:

pip install clang-tidy

Linux,使用 apt 或者 pip

apt-get install clang-tidypip install clang-tidy

使用

Clang-tidy 命令

使用 clang-tidy 检测某个文件时需要知道头文件路径等编译信息,这是因为它需要了解代码的上下文环境,以便正确地解析代码并检测潜在的问题。例如,如果代码中使用了某个库的函数,Clang-tidy需要知道该库的头文件路径才能正确地解析函数的声明和定义。如果缺少这些编译信息,Clang-tidy可能会产生误报或漏报的问题。

因此一个 clang-tidy 检查的命令大概是这样的:

clang-tidy --checks='-*' test.cpp -- -I ./src/ -x c++

这个命令的含义如下:

clang-tidy:调用clang-tidy工具。–checks=‘-*’:指定要执行的检查器。这里的-*表示不执行任何检查器,即关闭所有检查器。test.cpp:指定要检查的源文件名。–:用于分隔clang-tidy的选项和编译器的选项。-I ./src/:指定编译器的头文件搜索路径,即将./src/目录添加到头文件搜索路径中。-x c++:指定编译器要编译的源文件类型为C++。

在实际使用 clang-tidy 中,搭配上 cmake 将事半功倍。clang-tidy 中有个 -p 参数,-p build-path参数是用于指定Clang-tidy读取编译命令数据库的路径。编译命令数据库通常是一个名为compile_commands.json的文件,它包含了编译每个源文件所需的完整命令行,包括编译器选项、头文件路径等信息。

例如,如果你使用CMake进行构建,可以通过设置-DCMAKE_EXPORT_COMPILE_COMMANDS=ON选项来生成compile_commands.json文件。然后,你可以使用-p参数告诉Clang-tidy在哪里找到这个文件,如clang-tidy -p /path/to/build/directory。

如果没有指定-p参数,Clang-tidy会尝试在第一个输入文件的所有父路径中搜compile_commands.json文件。

这个参数的主要目的是让Clang-tidy能够正确解析源代码。因为C++的语法和语义很大程度上取决于编译上下文,如果没有正确的编译信息,Clang-tidy可能无法正确解析源代码,也就无法进行准确的静态分析。

clang-tidy-diff.py 脚本

clang 官方提供了一些脚本,在 clang-tidy 命令行的基础上提供了额外的能力,通过 clang-tidy-diff.py 来检查 git diff 中实际发生修改的代码。你可以这样使用:

git diff branchA master | python clang-tidy.py -path /path/to/compile_commands.json

这个命令的含义如下:

git diff branchA master:使用git diff命令比较分支branchA和master之间的差异,并将差异输出到标准输出流中。|:管道符号,将git diff的输出作为下一个命令的输入。python clang-tidy-diff.py:使用Python脚本 clang-tidy-diff.py 来处理git diff的输出。-path /path/to/compile_commands.json:指定编译命令数据库的路径为/path/to/compile_commands.json。

实践

检查项

clang-tidy 的检查项非常丰富,这部分可以参考:

clang-tidy静态语义检查,安装、使用、检查项注解extra/clang-tidyClang-Tidy-in-CLion-2021.3-default-configuration

如果你不知道检查哪些,那偷个懒直接使用 CLion 的默认配置即可,通过 how-to-dump-clions-default-clang-tidy-configuration 提到的方法生成 .clang-tidy 文件。命令行中使用 --config-file 指定 .clang-tidy 文件即可

clang-tidy --config-file=/path/to/.clang-tidy ...

在检查项中,可以指定 warning-as-error ,例如

---Checks: '-*,bugprone-argument-comment,bugprone-assert-side-effect,bugprone-bad-signal-to-kill-thread,bugprone-copy-constructor-init'WarningsAsErrors: 'bugprone-*'

这样检测到相关问题后直接报错,方便 ci/cd 进行检查

编译中开启 clang-tidy 检查

在CMake中,我们可以通过设置CMAKE_CXX_CLANG_TIDY属性来为整个项目开启Clang-tidy检查。例如:

set(CLANG_TIDY_COMMAND clang-tidy;            -header-filter=^${PROJECT_ROOT_DIR}/src/.*;            -config-file=${PROJECT_ROOT_DIR}/.clang-tidy;)set(CMAKE_CXX_CLANG_TIDY ${CLANG_TIDY_COMMAND})

在这个例子中,CMAKE_CXX_CLANG_TIDY被设置为一个包含Clang-tidy命令和相关选项的变量。这将导致所有编译的文件都会被Clang-tidy检查。

然而,有时我们可能希望跳过某些文件的检查,比如第三方库的代码。在这种情况下,使用CMAKE_CXX_CLANG_TIDY就不再适用。一个更好的选择是使用set_target_properties命令,只为特定的目标开启Clang-tidy检查。例如:

set_target_properties(myTarget            PROPERTIES            CXX_CLANG_TIDY ${CLANG_TIDY_COMMAND})

在这个例子中,只有myTarget目标的源文件会被Clang-tidy检查,其他没有设置CXX_CLANG_TIDY属性的目标则不会受到影响。

跳过部分代码的检查

可以使用 NOLINTNOLINTNEXTLINE 以及 NOLINTBEGIN + NOLINTEND 跳过某些代码的静态检测

int a = 10; // NOLINT// NOLINTNEXTLINEint b = 20;// NOLINTBEGINvoid fun(){dosomething(); // 跳过 BEGIN 和 END 之间的代码}// NOLINTEND 

将 clang-tidy 加入 CI/CD

有两种方式将 clang-tidy 加入 CI/CD 中:

在 cmake 中设置 CXX_CLANG_TIDY 开启编译时检查使用 clang-tidy-diff.py 检测被修改的文件

对比两种方式各有优劣:

开启编译时检查,设置方便,但增加编译耗时,且对现有所有文件进行检查,如果项目文件很多那么修改所有 error 是一个苦力活。clang-tidy-diff.py 只检查增量或者被修改的文件,但需要提供 compile_commands.json 文件。

最终选择了方法 2,庆幸的是目前大部分 C/C++ 项目都使用基本使用 cmake 来管理,包括 Android NDK,因此使用起来并无太大麻烦。例如你想在 CI/CD 中检查某个 Android NDK 项目,你可以这么做:

使用 ./gradlew assembleFullRelease 编译你的项目找到生成的 compile_commands.json 文件所在使用 clang-tidy-diff.py 检查被修改的文件:git diff A B | python clang-tidy-diff.py -path=/path/compile_commands.json -config-file=/path/.clang-tidy

参考

clang-tidy静态语义检查,安装、使用、检查项注解clang-tidy-diff.py

点击全文阅读

郑重声明:

本站所有活动均为互联网所得,如有侵权请联系本站删除处理

我来说两句