251 lines
9.6 KiB
Markdown
251 lines
9.6 KiB
Markdown
# VSCode 使用 Clangd 插件
|
||
|
||
Clangd 是一个基于 Clang 的语言服务器,它提供了代码智能感知和导航功能。通过与 VSCode 集成,可以实现以下功能:
|
||
|
||
- 代码补全和自动提示:Clangd 可以根据代码上下文提供准确的补全建议和自动提示,帮助开发者快速编写代码。
|
||
- 代码跳转和导航:Clangd 可以识别代码中的符号引用、函数调用等,并支持跳转到定义、查看声明等操作,便于阅读和理解复杂的内核源代码。
|
||
- 实时错误和警告检查:Clangd 可以实时检查代码中的语法错误、潜在问题和警告信息,帮助开发者及早发现和修复问题。
|
||
- 重构支持:Clangd 提供了一些重构功能,如重命名变量、提取函数等,可以简化代码重构的过程。
|
||
|
||
需要代码分析和跳转的话要安装 clangd,需要代码格式化则需要安装 clang-format,并能够在系统 PATH 种找到它们。
|
||
|
||
在 VSCode 中使用 Clangd 需要先安装 clangd (LLVM) 插件,然后使用源码目录下的 .clang-format,.clangd 或 .vscode/settings.json 进行项目配置。
|
||
|
||
## 1. 基本使用配置
|
||
|
||
### 1.1. 使用 .clangd 文件方式
|
||
|
||
clangd 的配置文件为源码路径下的 .clangd 文件。
|
||
|
||
可通过:
|
||
|
||
```bash
|
||
Ctrl+Shift+P -> clangd: open project configuration file
|
||
```
|
||
|
||
打开项目 .clangd 文件, 参考格式如下:
|
||
|
||
```clangd
|
||
# 提示嵌入,不使用函数参数嵌入提示
|
||
#InlayHints:
|
||
# Designators: Yes
|
||
# Enabled: Yes
|
||
# ParameterNames: No
|
||
# DeducedTypes: Yes
|
||
|
||
CompileFlags:
|
||
Add:
|
||
- -xc
|
||
- -ID:/Path/to/project/source/User
|
||
Remove:
|
||
- -forward-unknown-to-host-compiler
|
||
- --generate-code*
|
||
- -rdc=*
|
||
- -Xcompiler*
|
||
```
|
||
|
||
其中 -x 为 gcc 参数,用于忽略源代码文件扩展名,并使用 -x 参数指定的语言类型。如果源码文件不是标准后缀名称(.c,.cpp )或语法与扩展名不符,则 gcc 编译器便不能通过后缀名判断语言类型,此时可以通过该参数指定语言类型。取值可以为:
|
||
|
||
- -xc
|
||
- -xc++
|
||
- -xobjective-c
|
||
- -xc-header
|
||
- -xcpp-output
|
||
- -assembler
|
||
- -assembler-with-cpp
|
||
|
||
-I 为 gcc 指定库头文件路径的参数。
|
||
|
||
#### 1.1.1 Qt 的 .clangd 配置参考
|
||
|
||
```clangd
|
||
CompileFlags:
|
||
Add:
|
||
- -xc++
|
||
- -I/usr/include/aarch64-linux-gnu/qt5
|
||
- -I/usr/include/aarch64-linux-gnu/qt5/QtCore
|
||
- -I/usr/include/aarch64-linux-gnu/qt5/QtWidgets
|
||
```
|
||
|
||
### 1.2. 使用 .vscode/settings.json 方式
|
||
|
||
创建:.vscode/settings.json 文件,参考配置格式如下:
|
||
|
||
```json
|
||
{
|
||
"clangd.fallbackFlags": [
|
||
"-xc",
|
||
"-I${workspaceFolder}/User",
|
||
],
|
||
}
|
||
```
|
||
|
||
### 1.3. clang-format
|
||
|
||
使用代码格式化功能需要在 VSCode User Setting 中使能 Text Editor->Formatting->Formate On Type。
|
||
|
||
clang-format 的配置文件为源码路径下的 .clang-format 文件,几个配置参考如下:
|
||
|
||
```clang-format
|
||
BasedOnStyle: LLVM
|
||
UseTab: Never
|
||
IndentWidth: 4
|
||
TabWidth: 4
|
||
|
||
# 最外层大括号换行
|
||
# BreakBeforeBraces: Linux
|
||
|
||
BreakBeforeBraces: Allman
|
||
AllowShortIfStatementsOnASingleLine: true
|
||
IndentCaseLabels: false
|
||
ColumnLimit: 120
|
||
```
|
||
|
||
```clang-format
|
||
---
|
||
Language: Cpp
|
||
#圆括号之后,多行内容,进行对齐
|
||
AlignAfterOpenBracket: Align
|
||
|
||
#连续赋值时,对齐所有等号
|
||
AlignConsecutiveAssignments: true
|
||
#连续声明时,对齐所有声明的变量名
|
||
AlignConsecutiveDeclarations: true
|
||
|
||
#连续宏定义时,对齐所有定义值
|
||
AlignConsecutiveMacros: AcrossEmptyLinesAndComments
|
||
#AlignOperands Align将对齐分割到多行上的单个表达式的操作数
|
||
AlignOperands: Align
|
||
#对齐连续的尾随的注释
|
||
AlignTrailingComments: true
|
||
#允许将一个函数声明的所有参数移到下一行.
|
||
AllowAllParametersOfDeclarationOnNextLine: false
|
||
#将简单的语句块放到一个单行
|
||
AllowShortBlocksOnASingleLine: false
|
||
#if (a) return;放单行 属性:Never、WithoutElse没有else的可以放单行、OnlyFirstIf只有第一个if放单行、AllIfsAndElse总是把简短的if, else if和else语句放在同一行。
|
||
AllowShortIfStatementsOnASingleLine: Never
|
||
#BinPackArguments:如果为false,函数调用的参数要么全部在同一行,要么各有一行。
|
||
BinPackArguments: false
|
||
#BinPackParameters:如果为false,函数声明或函数定义的参数将全部在同一行或各有一行。
|
||
BinPackParameters: false
|
||
|
||
BreakBeforeBraces: Custom
|
||
# 控制单独的大括号换行事件,只有当BreakBeforeBraces设置为Custom时才有效
|
||
BraceWrapping:
|
||
#使控制语句(if/for/while/switch/..)换行。
|
||
AfterControlStatement: true
|
||
#使枚举定义换行。
|
||
AfterEnum: true
|
||
#使函数定义换行。
|
||
AfterFunction: true
|
||
#使结构定义换行。
|
||
AfterStruct: true
|
||
#使共同体定义换行。
|
||
AfterUnion: true
|
||
#在else之前换行。
|
||
BeforeElse: true
|
||
#换行大括号缩进。
|
||
IndentBraces: false
|
||
#空函数是否可以放在单行:flase允许 true不允许
|
||
SplitEmptyFunction: true
|
||
#空类,结构或联合主体是否可以放在单行:flase允许 true不允许
|
||
SplitEmptyRecord: true
|
||
#空namespace是否可以放在单行:flase允许 true不允许
|
||
SplitEmptyNamespace: true
|
||
|
||
SpaceBeforeParens: Custom
|
||
#控制圆括号前的单独空格,只有当SpaceBeforeParens设置为Custom时才有效
|
||
SpaceBeforeParensOptions:
|
||
#在控制语句关键字(for/if/while…)和开括号之间放置空格
|
||
AfterControlStatements: true
|
||
#在函数声明名称和开括号之间不允许使用空格
|
||
AfterFunctionDeclarationName: false
|
||
|
||
#指针对齐:右
|
||
PointerAlignment: Right
|
||
# 三元运算符将被放置在换行后
|
||
BreakBeforeTernaryOperators: true
|
||
#每行字符的限制,0表示没有限制
|
||
ColumnLimit: 0
|
||
#缩进空格宽度:4
|
||
IndentWidth: 4
|
||
#保留在赋值操作符之前的空格
|
||
SpaceBeforeAssignmentOperators: true
|
||
#不要排序include的头文件
|
||
SortIncludes: Never
|
||
#允许重新排版注释
|
||
ReflowComments: true
|
||
#尾行注释前的空格数
|
||
SpacesBeforeTrailingComments: 2
|
||
#连续空行的最大数量
|
||
MaxEmptyLinesToKeep: 1
|
||
#使用tab字符: Never从不使用, ForIndentation仅在缩进时使用制表符, ForContinuationAndIndentation, Always
|
||
UseTab: Never
|
||
#SpacesInParentheses如果为真(true), 将会在“(”之后和“)”之前插入空格。
|
||
SpacesInParentheses: false
|
||
#SpacesInSquareBrackets如果为真(true),将会在“[”之后和“]”之前插入空格。
|
||
SpacesInSquareBrackets: false
|
||
```
|
||
|
||
手动格式化当前文件:右击当前打开的文档,选择“格式化文档”。
|
||
|
||
如果想格式化一整个文件夹,可以安装 VSCode 的 format files(by:jbockle)插件,然后在文件窗口种右击要格式化的文件夹,选择“Start Formate Files: This Folder”。
|
||
|
||
### 1.4. 其他配置
|
||
|
||
#### 1.4.1 打开或关闭函数参数提示 (inlay hints)
|
||
|
||
编码阶段嵌入的函数参数 hints 比较干扰实现,可以通过 Ctrl+Shift+P 呼出 VSCode 命令,点击“clangd: Toggle inlay hints”进行切换即可。
|
||
|
||
## 2. 使用 VSCode+Clangd 开发 Linux 内核
|
||
|
||
如果直接使用 VSCode+Clangd 阅读内核代码的话,会存在一个问题:很难确定哪些 Linux 内核源码源码文件被编译使用了,哪些没有。此时使用 Bear 工具配合使用就可以很好的解决这个问题。Bear 是 Build EAR 的缩写,[官方](https://github.com/rizsotto/Bear)介绍如下:
|
||
|
||
```md
|
||
Bear is a tool that generates a compilation database for clang tooling.
|
||
|
||
The JSON compilation database is used in the clang project to provide information on how a single compilation unit is processed. With this, it is easy to re-run the compilation with alternate programs.
|
||
|
||
Some build system natively supports the generation of JSON compilation database. For projects which does not use such build tool, Bear generates the JSON file during the build process.
|
||
```
|
||
|
||
在 Ubuntu 下可以直接 Apt 安装
|
||
|
||
```bash
|
||
sudo apt install bear
|
||
```
|
||
|
||
Bear 的使用方式就是在原来的编译命令前加上 bear 命令即可,比如原来的编译命令为:
|
||
|
||
```bash
|
||
make mrproper
|
||
make defconfig
|
||
make zImage -j4
|
||
```
|
||
|
||
在使用 Bear 时只要将命令改为:
|
||
|
||
```bash
|
||
make mrproper
|
||
make defconfig
|
||
bear make zImage -j4
|
||
```
|
||
|
||
在编译完成后 Bear 将生成 compile_commands.json 文件。这个文件记录了工程是如何构建的,使用到了哪些源码文件,源码文件之间的包含关系,引用路径之类的。compile_commands.json 可以帮助 Clangd 构建符号关系索引库。
|
||
|
||
如果是交叉编译,需要将 compile_commands.json 中的“cc”全部替换为实际使用的交叉编译器,比如“arm-linux-gnueabihf-gcc”,然后保存。
|
||
|
||
如果项目下有 .cache 文件夹的话,需要删掉它。之后重新用 VSCode 打开源码目录,随便打开一个 .c 文件,Clangd 便自动开始索引文件了,索引文件会保存在 .cache 目录下。
|
||
|
||
由于内核源码较大,Clangd 将用几分钟的时间来建立索引。如果这个过程比较快,则说明配置没有生效。
|
||
|
||
如果一切顺利,就可以保存 VSCode 工程,以便下次使用。
|
||
|
||
## 3. 外部参考资料
|
||
|
||
1. [VSCode 使用 Clangd](https://blog.csdn.net/m0_47329175/article/details/128677511)
|
||
2. [解决 clangd 设置 query-driver 后无法解析 include 路径](https://zhuanlan.zhihu.com/p/616838477)
|
||
3. [VSCode 使用 clangd 构建 Linux 驱动开发环境](https://blog.csdn.net/Telly_/article/details/134289358)
|
||
4. [使用 VSCode clangd 插件进行 linux 内核代码阅读和嵌入式开发](https://blog.csdn.net/m0_61738650/article/details/131529082)
|
||
5. [VSCode 使用技巧](https://www.cnblogs.com/zjutzz/p/15303480.html#35-%E5%87%BD%E6%95%B0%E6%97%A0%E6%B3%95%E8%B7%B3%E8%BD%AC-clangd-%E9%85%8D%E7%BD%AE-compile_commandsjson-%E8%B7%AF%E5%BE%84)
|