目录
CI构建可以分为几个部分:构建代码(可以是多个平台)------>UT用例 ------> 代码覆盖率 ------> 代码静态检测
首先保证有可以CMakeLists.txt可以在本地正常编译业务代码和UT代码
构建
首先需要有ci构建的配置文件,以gitlab为例,需要.gitlab-ci.yml的配置文件,内容和格式如下:
bash
image: makeappdev/cpp-dev # Docker image available at https://hub.docker.com
stages: # 配置pipeline的阶段
- build # 阶段1: 构建
- test # 阶段2: 测试
code_build: # 一个单一job的pipeline
stage: build # Stage of the job
script: # Main step of the job
- cmake -H. -Bbuild # 创建build目录,并运行生成cmake文件
- cmake --build ./build # 运行cmake进行编译
- make test # 运行所有unit test
cmake的具体命令如指定编译线程数等,可以在CMake之命令行中查看
配置这个yml之后gitlab可以运行pipeline了。
代码风格
代码风格可以使用clang-format检查。
- 首先安装clang-format工具:
sudo apt install clang-format
; - 编写 .clang-format文件:
bash
---
Language: Cpp
# BasedOnStyle: Google
AccessModifierOffset: -2
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Left
AlignOperands: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Attach
BreakBeforeInheritanceComma: false
BreakInheritanceList: BeforeColon
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
# BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 80
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IncludeBlocks: Preserve
IncludeCategories:
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
Priority: 2
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
Priority: 3
- Regex: '.*'
Priority: 1
IndentCaseLabels: false
IndentPPDirectives: None
IndentWidth: 2
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Left
ReflowComments: true
SortIncludes: true
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 2
SpacesInAngles: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Latest
TabWidth: 8
UseTab: Never
...
indent_columns: 2
...
这个配置样式定义了很多选项如缩进宽度,换行规则,空格的使用等等。可以针对自己的需求进行修改。
代码覆盖率
- 首先需要安装lcov或gcov工具:
sudo apt install lcov
;要确保它们可以在执行 cmake 时被找到。 - 代码根目录下新创建cmake目录,把CodeCoverage.cmake放到该目录下,CodeCoverage.cmake是用于配置 CMake 以收集代码覆盖率的模块
- 在CMakeLists.txt中新增查找和包含CodeCoverage.cmke的代码:
bash
# CMakeLists.txt
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
include(CodeCoverage)
这是CodeCoverage.cmake的一个示例,可以根据需要进行修改
- 在ci的yml文件最后加上对覆盖率的检测:
bash
mkdir ccov # 创建ccov用于存放生成的文件
make coverage # 覆盖率检测
静态检测
好用的C/C++代码风格检查工具主要有Clang-Tidy、Cppcheck、cpplint等。这些工具各有特色、广泛应用于项目开发过程中,帮助开发者识别代码中的风格问题和潜在错误、提供了自动化的代码审查功能。Cppcheck尤其值得一提,它不仅能进行代码风格检查,还能对代码进行静态分析,寻找代码中的内存泄露、缓冲区越界等问题。
Cppcheck
Cppcheck是一个开源的静态代码分析工具,旨在为C/C++语言的开发者提供一个高效的方式来检测其代码中的各种问题。与其他代码风格检查工具相比,Cppcheck专注于检测开发者可能会忽视的错误,实现了对代码质量的深入分析。它可以检测的问题类型包括但不限于未使用的函数、变量,指针和资源的泄露,以及潜在的数组越界等。Cppcheck易于使用,只需在命令行输入相应的指令和要检查的文件路径即可进行代码的静态分析,它支持多种输出格式,便于开发者查看和处理分析结果。此外,Cppcheck拥有良好的定制性,开发者可以根据自己的需要配置规则,适配个人或团队的代码风格。
Cppcheck特别擅长于发现C/C++代码中潜在的错误和风格问题。它通过分析源代码,不需要代码的执行和测试用例,就能够发现代码中的缺陷。这使得Cppcheck成为早期防止错误传播和提高代码质量的有力工具。
Cppcheck的使用方法非常灵活,它支持GUI和命令行两种模式,使得无论是在持续集成系统中还是本地开发环境下,Cppcheck都能够轻松地被集成进项目中。此外,Cppcheck还支持各种配置选项,允许开发者根据项目的具体需求来定制分析的规则和程度。这一点对于处理大型项目和多样化的代码基非常重要。
Clang-Tidy
Clang-Tidy是LLVM项目的一部分,是一个非常流行的C/C++代码风格和质量的检查工具。它集成了多个模块,能够检查出多种不同的编程错误,包括但不限于潜在的bug、不合理的构造、不符合现代C++标准的代码。此外,Clang-Tidy还支持自定义检查器,允许开发者根据自己的需求编写和集成新的规则。
Clang-Tidy不仅仅是一个代码风格检查工具,它的目标是提高代码质量和保持代码的一致性。它通过静态分析代码,发现可能的问题并提出改进建议。例如,它可以帮助开发者发现隐含的类型转换,未初始化的变量,过期或不安全的C++用法等问题。这使得Clang-Tidy成为了现代C/C++项目中不可或缺的工具之一。
cpplint
cpplint是由Google开发的一个C/C++代码风格检查工具,它根据Google的C++代码风格指南来检查代码是否符合规范。cpplint以其简单易用而广受欢迎,它通过分析源代码文件来识别不符合指南的代码风格和模式。
使用cpplint可以帮助开发者保持代码风格的一致性,并引导开发者遵守一套统一的编程规范。这对于团队协作和维护大型项目的代码质量至关重要。尽管cpplint的检查规则是基于Google的代码风格指南的,但开发者可以通过配置文件来调整或关闭某些规则,使之更贴合个人或团队的风格偏好。
配置
这里使用Clang-Tidy工具配置静态检测
- 首先需要安装clang-tidy工具:
sudo apt install clang-tidy
。Clang-Tidy 工具是一个非常强大的C++静态分析工具 - 同代码覆盖率一样,将ClangTidy.cmake放到cmake目录下
- 在CMakeLists.txt中新增一行
include(ClangTidy)
- 在根目录下放静态检测的.clang-tidy文件。
- 运行 CMake 或make 进行编译,Clang-Tidy 会在编译时运行
clang-tidy的内容大概如下:
bash
---
Checks: '-*,readability-*'
WarningsAsErrors: ''
HeaderFilterRegex: ''
AnalyzeTemporaryDtors: false
FormatStyle: none
User: user
CheckOptions:
- key: readability-identifier-naming.NamespaceCase
value: lower_case
- key: readability-identifier-naming.ClassCase
value: CamelCase
...
在上述配置中:
Checks
: 这一行定义了你想要运行的检查。在这个例子中,它会禁用所有检查(-*
),然后仅启用 readability-*
系列的检查。
WarningsAsErrors
: 如果这里列出了任何检查,那么这些检查的警告将被视为错误。
HeaderFilterRegex
: 定义一个正则表达式,仅分析与此表达式匹配的头文件。
AnalyzeTemporaryDtors
: 定义是否分析临时析构函数。
FormatStyle
: 定义代码格式化样式。none 表示不进行代码格式化。
User
: 定义用户
CheckOptions
: 用于为特定检查指定选项。这里的例子中,它改变了命名约定规则,要求命名空间全部小写,类名使用驼峰命名。
你可以检查 Clang-Tidy 的文档以获取更多信息和更多可用的检查:http://clang.llvm.org/extra/clang-tidy/
使用 .clang-tidy 文件可以帮助保持项目中的代码质量和一致性。