LLVM学习---clang-format代码格式化 原创

LLVM学习—clang-format代码格式化



更多精彩内容
👉个人内容分类汇总 👈
👉开发工具 👈

1、前言

🫵别看了,如果你还在饱受🐷队友💩山代码的折磨,那就不要错过Clang-Format。

在本章主要学习使用LLVM中的Clang-format

关于Clang-format的详细说明、配置参数项这里不会细说,附带的链接里就很详细。

这里主要讲解如何再Qt开发中使用Clang-format。

LLVM 项目是模块化和可重用编译器和 工具链技术。

LLVM 项目有多个组件。该项目的核心是 本身称为“LLVM”。这包含所有工具、库和标头 处理中间表示所需的文件并将其转换为 对象文件。工具包括汇编器、反汇编器、位码分析器和 Bitcode 优化器。它还包含基本的回归测试。

clang-format是一个代码格式化工具,用于自动调整源代码格式以符合指定的编码风格。(编码规范写得再好,没人看等于零)

clang-format是一个非常实用的工具,它不仅可以帮助个人开发者提高编码效率,还能在团队协作中确保代码风格的统一,从而减少代码审查时的格式问题,专注于代码逻辑本身。

以下是关于clang-format的详细说明:

  1. 概念和作用
  • clang-format是LLVM项目的一部分,它可以用于C、C++、Java、JavaScript、Objective-C等多种编程语言的代码格式化。它的主要目的是帮助开发者自动整理代码的排版和格式,确保代码风格的一致性,从而提高代码的可读性和可维护性。
  1. 安装配置
  • clang-format可以在多个平台上使用,包括Linux、macOS和Windows。安装过程相对简单,可以通过包管理器或从LLVM官方网站下载源代码编译安装。
  1. 基本用法
  • 使用clang-format通常很简单,可以通过命令行指定输入文件和输出文件,或者直接对文件进行格式化。例如,clang-format -i input.cpp会将格式化后的代码直接修改原文件,或者集成到IDE中,自动使用。
  1. 常用选项
  • clang-format提供了多种选项来自定义格式化风格,如-style选项允许用户选择不同的预设风格(如LLVM、Google等),-column选项可以指定最大列数限制等。
  1. 自定义格式
  • 如果预设的风格不满足需求,clang-format还支持通过配置文件(如.clang-format)来自定义代码的排版规则,如缩进大小、括号风格、换行策略等。
  1. 集成开发环境
  • clang-format可以被集成到各种编辑器和IDE中,如Qt、Visual Studio Code、Xcode等,使得开发者在编写代码时能够实时保持代码格式的一致性。

2、网站

3、环境

  • Windows11
  • Qt 5.14.2
  • Qt Creator 4.11.1(Qt5.14.2安装自带)
    • 不包含Clang-format,需要单独下载
  • Qt Creator 10.0.2 (新版本对Clang-Format支持会更好)
    • D:\Qt\qtcreator-10.0.2\bin\clang\bin安装路径下附带了一个Clang-format 16.0.0
    • 也可以下载更新版本的
  • Clang-format 18.1.4
    • 自己下载安装的新版本

4、环境配置

在Qt Creator中Clang-format格式化代码分为两部分,各有优劣。

  • QtCreator自带:(qt默认开启,或者在插件中选择Clang Format)
    • 在代码编写时自动补全的模板格式;
    • 可在保存时格式化代码;
    • 可视化编写规则;
    • 无需配置环境;
    • 使用非标准.xml格式配置文件;
    • 在Qt Creator 4.11.1支持较差。
  • 插件形式调用clang-format:(插件中选择Beauitfier)
    • 代码编写完成后,保存代码时自动修改代码格式。
    • 需要配置插件、Clang-format路径;
    • 使用通用标准.clang-format配置文件;
    • 在新旧版本QtCreator支持都较好;
    • 较新版本的QtCreator安装后在D:\Qt\qtcreator-10.0.2\bin\clang\bin路径下会自带Clang-format.exe

1.1 Clang-format配置1

  1. 打开Qt Creator,点击【帮助】->【关于插件】,勾选Beautifier安装插件,然后重启Qt Creator;

    • 需要注意的是这里安装插件并不是下载插件,在安装QtCreator时这些插件就已经存在于D:\Qt\Qt5.14.2\Tools\QtCreator\lib\qtcreator\plugins路径下了,所以离线版本也可以使用。

    在这里插入图片描述

  2. 安装成功后打开【首选项】会多出一项【美化器】或者叫【Beautifier】;

    在这里插入图片描述

  3. 下载Clang-format;

    • 可以只是选择单独下载Clang-format,体积小,不过版本较低;

      在这里插入图片描述

    • 也可以下载最新版本(github)的LLVM安装包,里面包含了很多工具,包括clang-format;

      在这里插入图片描述

  4. 安装完成LLVM后打开Qt Creator,勾选【启动文本保存时的自动格式化】,工具选择ClangFormat;

    在这里插入图片描述

  5. 选择【Clang Format】,将【配置】中的Clang Format命令选择为刚才安装的LLVM路径下的Clang-format.exe;

  6. 然后可以在【选项】中勾选使用【预定义的风格】或者【自定义风格】;

    在这里插入图片描述

  7. 如果使用【自定义风格】,则点击【添加】,我的命名为myClang-format,然后编辑自己的风格文件.clang-format,然后这个文件会存在于下列路径中:

    C:\Users\MHF\AppData\Roaming\QtProject\qtcreator\beautifier\clangformat\myClang-format\.clang-format
    
  8. 也就是说可以在qt Creator中编辑,也可以找到.clang-format文件直接修改;(注意如果文件中有中文,需要注意会不会编码错误导致无法使用)

  9. 设置好格式化风格后,创建一个工程,随便编写一些代码,然后按Ctrl + S保存代码,就会自动格式化代码了。

    在这里插入图片描述

  10. 还有就是C++代码风格的配置了,这是在编写代码时自动补全的代码模板格式;

在这里插入图片描述

1.2 Clang-format配置2

  1. 打开【首选项】,选择【C++】->【代码风格】,根据个人需求选择【Format mode】,这里我选择【Full formatting】;

  2. 选择Full formatting,勾选Override Clang Format configuration file

  3. 这时候风格规则是不能修改的,点击【复制】创建一个新文件,就可以修改了;

    在这里插入图片描述

5、clang-format配置文件

配置项说明
注意:如果使用了高版本的特性,则会导致配置文件无法生效,可以使用clang-format --style=llvm -dump-config > .clang-format命令导出clang-format的内置风格配置文件,然后再在导出的文件上修改,就不会出现版本不支持的情况了。

  • 下列格式化规则是我自己使用的配置,部分内容做了注释;
    • 注意:使用时注意编码不要出现错误;
    • 注意:如果自己安装的clang-format版本不高,就不要使用新特性,因为会不支持;
    • 注意:弃用的规则、危险性高的规则也尽量不要使用。
---
Language:        Cpp            # 目标格式化编程语言
AccessModifierOffset: -4        # TabWidth设置后才生效
AlignAfterOpenBracket: Align
AlignArrayOfStructures: None
AlignConsecutiveAssignments:
  Enabled:         false
  AcrossEmptyLines: false
  AcrossComments:  false
  AlignCompound:   false
  PadOperators:    false
AlignConsecutiveBitFields:
  Enabled:         false
  AcrossEmptyLines: false
  AcrossComments:  false
  AlignCompound:   false
  PadOperators:    false
AlignConsecutiveDeclarations:
  Enabled:         false
  AcrossEmptyLines: false
  AcrossComments:  false
  AlignCompound:   false
  PadOperators:    false
AlignConsecutiveMacros:
  Enabled:         false
  AcrossEmptyLines: false
  AcrossComments:  false
  AlignCompound:   false
  PadOperators:    false
AlignEscapedNewlines: DontAlign
AlignOperands:   Align
AlignTrailingComments:
  Kind:            Always
  OverEmptyLines:  0
AllowAllArgumentsOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false
AllowShortEnumsOnASingleLine: false
AllowShortFunctionsOnASingleLine: Inline
AllowShortIfStatementsOnASingleLine: Never
AllowShortLambdasOnASingleLine: All
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: Yes
AttributeMacros:
  - __capability
BinPackArguments: true           # 函数调用变量要么都在同一行上,要么每个变量都独自在一行。
BinPackParameters: true           # 函数声明的【参数】或者函数定义的参数要么在同一行上,要么每个变量都独自在一行
BitFieldColonSpacing: Both        # 在:号每边都增加一个空白
BraceWrapping:                    # 大括号换行风格 BreakBeforeBraces==Custom时才生效
  AfterCaseLabel:  true
  AfterClass:      true           # 类的大括号是否换行
  AfterControlStatement: Always
  AfterEnum:       false
  AfterExternBlock: true
  AfterFunction:   true
  AfterNamespace:  false
  AfterObjCDeclaration: false
  AfterStruct:     true
  AfterUnion:      false
  BeforeCatch:     true
  BeforeElse:      true
  BeforeLambdaBody: true
  BeforeWhile:     false
  IndentBraces:    false
  SplitEmptyFunction: false
  SplitEmptyRecord: true        # AfterClass==true时生效
  SplitEmptyNamespace: false
BreakAfterAttributes: Never
BreakAfterJavaFieldAnnotations: true
BreakArrays:     true
BreakBeforeBinaryOperators: All
BreakBeforeConceptDeclarations: Always
BreakBeforeBraces: Custom
BreakBeforeInlineASMColon: OnlyMultiline
BreakBeforeTernaryOperators: true                  # 三元运算符换行后在前
BreakConstructorInitializers: BeforeComma          # 构造函数初始化列表换行规则
BreakInheritanceList: BeforeColon
BreakStringLiterals: true
ColumnLimit:     100                               # 代码最大列数
CommentPragmas:  '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerIndentWidth: 4               # 构造函数初始化列表和继承列表换行后缩进的字符数,无符号整数。
ContinuationIndentWidth: 4                         # 当一行代码放不下,自动换行后的缩进
Cpp11BracedListStyle: true                         # 大括号列表附近是否有空格{ 1, 2 }/{1, 2}
DerivePointerAlignment: false
DisableFormat:   false                             # 设置位false后可以使用// clang-format off .. // clang-format on注释禁用某段代码格式化
EmptyLineAfterAccessModifier: Never                # 类中访问修饰符后放置空行
EmptyLineBeforeAccessModifier: LogicalBlock        # 类中访问修饰符之前放置空行
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true                         # 自动修复命名空间注释名称
ForEachMacros:
  - forever
  - foreach
  - Q_FOREACH
  - BOOST_FOREACH
IfMacros:
  - KJ_IF_MAYBE
IncludeBlocks:   Preserve                          # 头文件分类排序
IncludeCategories:
  - Regex:           '^<Q.*'
    Priority:        200
    SortPriority:    200
    CaseSensitive:   true
IncludeIsMainRegex: '(Test)?$'
IncludeIsMainSourceRegex: ''
IndentAccessModifiers: false                       # 指定访问修饰符是否应具有自己的缩进级别
IndentCaseBlocks: true                             # case的{}缩进
IndentCaseLabels: false                            # case的标签是否缩进
IndentExternBlock: AfterExternBlock
IndentGotoLabels: true
IndentPPDirectives: AfterHash                      # 预处理器指令缩进样式
IndentRequiresClause: true
IndentWidth:     4                                 # 缩进4个字符
IndentWrappedFunctionNames: false
InsertBraces:    false                             # 控制语句(if、else、for、do和while)后面自动插入大括号(危险,可能导致代码错误)
InsertNewlineAtEOF: false
InsertTrailingCommas: None                         # 仅适用于 JavaScript 
IntegerLiteralSeparator:                           # 格式化整数文字分隔符
  Binary:          4                               # 二进制文本中的分隔符格式,按4位分割
  BinaryMinDigits: 0                               # 达到多少位二进制文本才进行分割
  Decimal:         3                               # 以十进制文字格式设置分隔符的格式。
  DecimalMinDigits: 0                              # 十进制最小分割位数
  Hex:             2                               # 十六进制文字格式分割个数
  HexMinDigits:    0
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: false
LambdaBodyIndentation: Signature                   # lambda表达式换行、缩进样式样式
LineEnding:      DeriveLF                          # 换行符样式
MacroBlockBegin: ''
MacroBlockEnd:   ''
MaxEmptyLinesToKeep: 1                             # 要保留的最大连续空行数
NamespaceIndentation: None                         # 命名空间缩进
ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 4
ObjCBreakBeforeNestedBlockParam: true
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PackConstructorInitializers: BinPack               # 设置初始化列表,和BreakConstructorInitializers 有一定冲突
PenaltyBreakAssignment: 150
PenaltyBreakBeforeFirstCallParameter: 300
PenaltyBreakComment: 500
PenaltyBreakFirstLessLess: 400
PenaltyBreakOpenParenthesis: 0
PenaltyBreakString: 600
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 50
PenaltyIndentedWhitespace: 0
PenaltyReturnTypeOnItsOwnLine: 300
PointerAlignment: Left                            # 指针对齐风格
PPIndentWidth:   -1
QualifierAlignment: Leave                         # 不同的排列说明符和限定符的方法(危险,可能改变代码含义)
ReferenceAlignment: Pointer                       # 引用对齐风格
ReflowComments:  false
RemoveBracesLLVM: false
RemoveSemicolon: false
RequiresClausePosition: OwnLine
RequiresExpressionIndentation: OuterScope
SeparateDefinitionBlocks: Always                  # 指定使用空行分隔定义块,包括 类、结构、枚举和函数。
ShortNamespaceLines: 1
SortIncludes:    CaseSensitive                    # 头文件排序规则
SortJavaStaticImport: Before
SortUsingDeclarations: Lexicographic              # using声明排序
SpaceAfterCStyleCast: true                        # 在C语言风格的强制类型转换后插入空格
SpaceAfterLogicalNot: false                       # 不在逻辑运算符 !后插入控制
SpaceAfterTemplateKeyword: false
SpaceAroundPointerQualifiers: Default
SpaceBeforeAssignmentOperators: true              # 赋值运算符前是否有空格
SpaceBeforeCaseColon: false                       # case的:前是否有空格
SpaceBeforeCpp11BracedList: false                 # 调用构造函数时初始化列表的大括号前面是否有空格
SpaceBeforeCtorInitializerColon: true             # 构造函数的:前面是否有空格
SpaceBeforeInheritanceColon: true                 # 继承的:前面是否有空格
SpaceBeforeParens: ControlStatements              # 定义在哪些情况下在左括号之前放置空格
SpaceBeforeParensOptions:                         # 单独控制不同情况下括号前面的空格,在SpaceBeforeParens==Custom时生效
  AfterControlStatements: true
  AfterForeachMacros: true
  AfterFunctionDefinitionName: false
  AfterFunctionDeclarationName: false
  AfterIfMacros:   true
  AfterOverloadedOperator: false
  AfterRequiresInClause: false
  AfterRequiresInExpression: false
  BeforeNonEmptyParentheses: false
SpaceBeforeRangeBasedForLoopColon: true           # 范围的for循环冒号之前删除空格
SpaceBeforeSquareBrackets: false                  # [之前的空格
SpaceInEmptyBlock: false
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 3                   # 尾部//注释之前的空格
SpacesInAngles:  Never
SpacesInConditionalStatement: false               # 已弃用
SpacesInContainerLiterals: false
SpacesInCStyleCastParentheses: false
SpacesInLineCommentPrefix:
  Minimum:         1
  Maximum:         -1
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard:        Auto                             # 解析和格式化与此标准兼容的c++结构
StatementAttributeLikeMacros:
  - Q_EMIT
StatementMacros:
  - Q_UNUSED
  - QT_REQUIRE_VERSION
  - Q_CLASSINFO
  - Q_ENUM
  - Q_ENUM_NS
  - Q_FLAG
  - Q_FLAG_NS
  - Q_GADGET
  - Q_GADGET_EXPORT
  - Q_INTERFACES
  - Q_MOC_INCLUDE
  - Q_NAMESPACE
  - Q_NAMESPACE_EXPORT
  - Q_OBJECT
  - Q_PROPERTY
  - Q_REVISION
  - Q_DISABLE_COPY
  - Q_SET_OBJECT_NAME
  - QT_BEGIN_NAMESPACE
  - QT_END_NAMESPACE
  - QML_ADDED_IN_MINOR_VERSION
  - QML_ANONYMOUS
  - QML_ATTACHED
  - QML_DECLARE_TYPE
  - QML_DECLARE_TYPEINFO
  - QML_ELEMENT
  - QML_EXTENDED
  - QML_EXTENDED_NAMESPACE
  - QML_EXTRA_VERSION
  - QML_FOREIGN
  - QML_FOREIGN_NAMESPACE
  - QML_IMPLEMENTS_INTERFACES
  - QML_INTERFACE
  - QML_NAMED_ELEMENT
  - QML_REMOVED_IN_MINOR_VERSION
  - QML_SINGLETON
  - QML_UNAVAILABLE
  - QML_UNCREATABLE
  - QML_VALUE_TYPE
TabWidth:        4                             # tab符的列数
UseTab:          Never
WhitespaceSensitiveMacros:
  - BOOST_PP_STRINGIZE
  - CF_SWIFT_NAME
  - NS_SWIFT_NAME
  - PP_STRINGIZE
  - STRINGIZE
...

6、总结

编码规范很重要,别让💩山代码的折磨自己。

° :.  . • 🌙 ° ★  .  * .
⭐. .    . ☾ °☆  . * ⭐ ¸ .
∩ │◥███◣ ╱◥███◣
╱◥◣ ◥████◣▓∩▓│∩ ║
│╱◥█◣║∩∩∩ ║◥█▓ ▓█◣
││∩│ ▓ ║∩田│║▓ ▓ ▓∩ ║

posted @ 2024-04-28 00:28  mahuifa  阅读(0)  评论(0编辑  收藏  举报  来源