diff --git a/user-guide/files/任意C-C++项目如何使跳转等编辑功能正常工作.md b/user-guide/files/任意C-C++项目如何使跳转等编辑功能正常工作.md new file mode 100644 index 0000000..1de45e4 --- /dev/null +++ b/user-guide/files/任意C-C++项目如何使跳转等编辑功能正常工作.md @@ -0,0 +1,90 @@ +# 任意C/C++工程,如何使跳转等编辑功能正常工作(clangd) +- 简单来说 + * 能构建编译数据库就构建编译数据库 + * 不能构建编译数据库时,在插件设置中添加头文件搜索路径能解决大部分问题 + * 对clangd配置有了解后可以使用clangd配置做更定制化的设置 + +## clangd +- 着色(高亮)、跳转、语法检查、查找引用、补全等编辑功能是如何实现的? + * 最关键的是需要解析代码,生成抽象语法树,要跨文件解析代还要知晓代码如何构建,整个处理过程类似编译器的处理过程。称提供这种服务的程序叫语言服务器 + * LSP(Language Server Protocol,语言服务器协议)用于编辑器和语言服务器之间的通信,是微软在2016年推出的协议。采用LSP,编辑器可以不开发自己的编辑功能,复用其他语言服务器的功能。在LSP结构中,主要由客户端和服务端组成,客户端在编辑器中,服务端是语言服务器 + * 具体到C/C++,clangd是一个开源的C/C++语言服务器,它基于Clang C++编译器,Clang是LLVM的一部分 + * Kylin-IDE和Kylin-Code推荐的C/C++编辑支持插件Kylin Clangd,正是基于clangd。所以,为了更好地使用使用C/C++编辑功能,需要了解一些clangd的配置方法 + * 安装,操作系统软件源中通常提供了clangd + - 安装命令`apt install clangd`或`yum install clang-tools-extra` + - 软件源中有时会有多个版本的clangd,尽量安装最新版本的clangd,桌面系统可以使用`apt search clangd`查询clangd版本,通常为软件包名为`clangd-n`,n表示版本 + - 如果使用Kylin-IDE或Kylin-Code的开发环境快速部署功能安装C/C++开发选项,则会自动安装clangd,而不需要手动安装 + - 已安装后,版本查看命令:`clangd --version` + +## 编译数据库 +- clangd正常解析代码,需要编译数据库 +- 需要先理解编译数据库这个概念 + * 一个常见的情况:打开一个C/C++ 源代码文件之后,为什么编辑器中报了很多警告和错误,而代码明明没有任何问题 + - 解析源代码需要一定的上下文,为了让 clangd 能够正确解析项目中的 C/C++ 文件,使其自动补全,跳转等特性生效,clangd 需要知道如何编译源代码文件 + - 即 clangd 需要知道代码文件的编译命令 + * 通常,clangd 从**编译数据库**中获取基本的编译命令。也就是说,如果存在编译数据库,并且编译数据库和代码对应,则编辑功能就可以正常使用。如果没有编译数据库或其他配置,则代码通常不能正常解析 +- 编译数据库是一个文本文件,它描述了代码库的编译命令。它通常是: + * 一个名为 `compile_commands.json` 的文件,列出了项目中每个文件的编译命令。该文件通常由像 CMake 这样的构建系统生成 + * 一个名为 `compile_flags.txt` 的文件,如果所有代码文件使用的编译参数相同,可以把使用的编译参数一个一行放在此配置文件中。针对简单的项目,可以采用该方式。如果`compile_commands.json`存在则`compile_flags.txt` 文件将被忽略 + * clangd首先在包含源文件的目录中和此目录下的build目录下检查编译数据库,然后向上遍历父目录 +- 编译数据库的生成方法 + * 方法一:构建工具生成。如果工程是使用构建工具构建的,则构建工具可以生成编译数据库 + - CMake: 使用 `-DCMAKE_EXPORT_COMPILE_COMMANDS=ON` 选项生成 `compile_commands.json` 文件, 但是该选项仅在 Generator 是 Makefile 或者 Ninja 的时候有效果。 + - Bazel: 使用 `--experimental_action_listener=//tools/clang:generate_compile_commands` 选项生成 `compile_commands.json` 文件。 + * 方法二:bear工具 + - 原理:bear工具跟踪编译过程,记录编译命令,将编译命令记录到`compile_commands.json` 文件中 + - 使用:需要在构建命令前面加上 `bear` ,命令格式如下 + ```bash + bear -- + 例子: + make clean//需要重新构建才能执行所有构建命令 + bear -- make + ``` + - 缺点:bear需要全程跟踪编译过程,需要编译一遍才能够生成编译数据库,对于某些编译时间很长的大型项目,耗时较多 + - 安装方法:操作系统软件源中通常提供了 bear 工具,可以直接安装。例如,桌面操作系统: + ```bash + sudo apt-get install bear + ``` + +## 无法生成编译数据库怎么办? +### 使用Kylin Clangd插件设置clangd +- 设置入口:首先要安装Kylin Clangd插件,然后点击左下角齿轮图标,选择“设置”,在搜索框中输入clangd,即可显示clangd配置 + * 设置有两类,一类是“用户”,另一类是“工作区” + - 用户:是当前操作系统用户的配置,对用户的所有项目生效;如果想对所有项目生效,则修改用户配置 + - 工作区:是当前工程的配置,仅对当前工程生效;如果仅想在当前工程使用当前设置,则修改工作区配置 + - 若工作区配置和用户配置有冲突,如果工作区配置中的某个条目后标记了“修改于用户”,表示以用户配置为准;若无此标记,则以工作区配置为准 +- 插件主要配置参数含义 + * Arguments:为clangd server添加参数。具体参数可以执行命令查看:`clangd -h` + * Head Insertion:控制clangd是否自动插入#include + - iwyu:在编写代码时会根据当前代码符号自动插入头文件,即便头文件通过其他头文件包含了。有时,自动插入头文件会引起困惑,如不需此功能,请选择never + - never:不自动插入头文件 + * On Config Changed:当编译数据库或配置文件变化时,如何处理。例如当`compile_commands.json`被修改后(修改了代码文件编译方法或添加了新代码文件)。当clangd版本是12或以上时,clangd会自动重载,可以忽略此参数,不过目前银河麒麟操作系统上的clangd版本通常是10或11,故此参数仍有效 + - restart:自动重启clangd server,以使修改生效 + - prompt:提示用户是否重启,用户确认重启后再重启 + - ignore:不重启 + * Path:clangd路径。如果clangd安装在了非标准路径,可以使用此参数定义clangd程序路径 + * Trace:指定一个文件路径,clangd会将自己运行时的性能数据写入到这个文件中,便于分析clangd的性能 + * **Additional Include Paths**:额外的头文件包含检查路径。此参数用途较大,编辑功能不能正常生效,多数情况是头文件未找到,可以设置此参数。类似添加了编译参数-I,但仅用于代码解析,不用于代码实际编译 + - 设置方法:直接填入包含路径即可,例如`/home/user/work/code/include`,该值是一个数组,可以设置多个包含路径 + * Fallback Flags:Fallbanck编译参数是指在没有找到编译数据库时,clangd会使用的默认解析方法。Fallback编译参数为clangd提供了一种灵活的方式,以便在缺少特定编译信息时仍能进行代码分析和补全。在快速开发或小型项目中,可能不需要复杂的构建系统,Fallback编译参数可以提供基本的支持 + - 添加格式:直接添加参数即可,例如: + ``` + -std=c++17 + -I/usr/local/include + ``` + +### 使用clangd配置(clangd 11 以上) +- clangd11及以上可以使用clangd配置,配置文件是yaml格式文件 + * 仅对某工程生效:.clangd文件,放在工程代码目录中,clangd会搜索活动代码文件的所在目录和上层目录 + - 注意区分:.clangd目录是clangd11之前的版本使用的一个暂存目录 + * 用户设置:~/.config/clangd/config.yaml +- 配置方法参考:https://clangd.llvm.org/config +- 简单例子 + ```yaml + CompileFlags: + Add: [-xc++, -Wall] # 增加编译参数列表 + CompilationDatabase:./out/ # 指定编译数据库目录 + ``` + +## 参考链接 +- https://clangd.llvm.org/ \ No newline at end of file diff --git a/user-guide/目录.md b/user-guide/目录.md index a21c8af..2e40f84 100644 --- a/user-guide/目录.md +++ b/user-guide/目录.md @@ -25,6 +25,8 @@ #### [C-C++开发](./files/C-C++开发.md) +#### [任意C/C++工程,如何使跳转等编辑功能正常工作(clangd)](./files/任意C-C++项目如何使跳转等编辑功能正常工作.md) + #### [Java开发](./files/Java开发.md) #### [Python开发](./files/Python开发.md) @@ -39,4 +41,5 @@ #### [历史调试](./files/历史调试.md) + #### [问题反馈](./files/问题反馈.md) \ No newline at end of file