【关注我,后续持续新增专题博文,谢谢!!!】
上一篇我们讲了:基于VSCode+clangd插件打造高效C++开发环境之三:clangd简介
这一篇我们开始讲: 基于VSCode+clangd插件打造高效C++开发环境之四:clangd配置
目录
2.1:生成compile_commands.json(必要)
一、注意
注意通过以下方式重新生成了compile_commands.json文件或修改了clangd配置之后,通常需要重启clangd服务后才会生效,可以从命令面板(Ctrl + Shift + P)选择重启命令:
或重启VS Code。
二、:clangd配置
2.1:生成compile_commands.json(必要)
clangd能准确地解析、理解代码,以提供上述的强大功能,需要我们给它提供每一个源文件的编译参数(头文件包含目录、宏定义等)。我们可以通过compile_commands.json文件(也即compilation database,其详细规范可参考clang网站的说明)给clangd传递这些编译参数。
一些构建工具(如cmake、Bazel等)可以比较方便地生成compile_commands.json文件,但是AOSP的构建工具目前没有比较好的方式可以生成compile_commands.json。因此,下面我们将通过ninja提供的工具生成编译命令,再借助gen_compiledb.py脚本来生成compile_commands.json文件供clagnd使用。
修改代码通常不需要重新生成compile_commands.json,一般仅需要在新增了源码文件或者修改了编译参数(如在mk文件中新增了包含目录、宏定义等)需要重新生成。
a、前提条件
以下操作在连接到服务器的SSH终端(SecureCRT或MobaXteem等)中执行;
进行以下操作之前,需要确保待阅读的代码已经被编译过;
当前工作目录在工程源代码目录。
b、使用ninja生成commands
ninja提供了一个工具(-t commands)可以生成特定目标的编译命令:
./prebuilts/build-tools/linux-x86/bin/ninja -f out/combined-taro.ninja -t commands MODULES-IN-vendor-qcom-proprietary > proprietary_commands.txt
此处注意:combined-taro.ninja替换成实际工程中的combined-xxx.ninja,MODULES-IN-vendor-qcom-proprietary替换成实际要的模块,此处使用MODULES-IN-vendor-qcom-proprietary是因为发现直接使用camx目录做模块生成的信息会丢失。实际使用可以直接指定模块,指定模块后后面步骤的执行会快很多,如camx中camera.qcom.so相关的代码可以使用:
./prebuilts/build-tools/linux-x86/bin/ninja -f out/combined-taro.ninja -t commands camera.qcom > camx_commands.txt
c、生成compile_commands.json(Kernel部分直接看d)
下载上面最新版本的gen_compdb文件(gen_compiledb.py脚本已废弃),并赋可执行权限:
chmod +x gen_compdb
然后执行:
./gen_compdb -c -i proprietary_commands.txt -s vendor/qcom/proprietary/camx -o vendor/qcom/proprietary/camx/compile_commands.json -q
-i 参数用于指定前一节生成的commands.txt文件,请根据实际情况指定
-s 参数用于指定源码目录,指定了此参数时会仅保留下位于该目录下的c/cpp文件
-o 参数用于指定生成的compile_commands.json文件
-q 选项用于禁用log(会快一些)
这个过程会比较长(python版本可能需要数分钟,C++版本需要十几秒),执行完成后查看vendor/qcom/proprietary/camx/compile_commands.json文件是否存在,大小应该在几M到十M,太小了表示不正常。
每个想要阅读且想支持跳转的代码文件夹都需采用以上方法生成compile_commands.json文件,可以写成脚本,如:
# 生成commands
./prebuilts/build-tools/linux-x86/bin/ninja -f out/combined-taro.ninja -t commands MODULES-IN-vendor-qcom-proprietary > commands.txt# 生成各个目录的json
./gen_compdb -c -i commands.txt -s vendor/qcom/proprietary/camx -o vendor/qcom/proprietary/camx/compile_commands.json -q
./gen_compdb -c -i commands.txt -s vendor/qcom/proprietary/camx-api -o vendor/qcom/proprietary/camx-api/compile_commands.json -q
./gen_compdb -c -i commands.txt -s vendor/qcom/proprietary/camx-common -o vendor/qcom/proprietary/camx-common/compile_commands.json -q
./gen_compdb -c -i commands.txt -s vendor/qcom/proprietary/chi-cdk -o vendor/qcom/proprietary/chi-cdk/compile_commands.json -q# 确认文件是否生成
ls -l --block-size=k vendor/qcom/proprietary/camx/compile_commands.json vendor/qcom/proprietary/camx-api/compile_commands.json vendor/qcom/proprietary/camx-common/compile_commands.json vendor/qcom/proprietary/chi-cdk/compile_commands.json
一般而言,compile_commands.json只要位于我们查看的代码目录的父目录,且包含了我们需要的源文件即可。因此,一个比较简单的做法是进行一次完整的编译(如编译整个vendor),然后在源码树根目录生成一个大而全的compile_commands.json文件。这种做法会生成一个非常大的json文件(几百M),clangd会占用更多的内存和磁盘空间,但好处是能为整个项目生成完整的符号索引。如:
# 以为Taibai项目生成整个vendor的compile_commands.json为例
# 以下假设当前目录为源码树根目录# 生成目标hal_images的commands
./prebuilts/build-tools/linux-x86/bin/ninja -f out_hal/combined-hal_mgvi_64_armv82.ninja -t commands hal_images > commands.txt
# 生成compile_commands.json:
./gen_compdb -c -i commands.txt -o compile_commands.json
d、Kernel 生成 compile_commands.json
Kernel 代码无法使用 ninjia 生成 compile_command.json,但 kernel 自带了scripts/clang-tools/gen_compile_commands.py 可以直接生成,低内核版本没该脚本,可以直接从网上下载一份
编译一遍 kernel
~/21841/source/vnd$ ./mk_android.sh -t userdebug -m kernel
cd 到 out 目录,该目录下会有大量 *.o.cmd 文件,可以通过 find -name "*.cmd" 确认
~/21841/source/vnd/kernel_platform/out$ find -name "*.cmd"
./msm-kernel/net/mac80211/.util.o.cmd
./msm-kernel/net/mac80211/.status.o.cmd
.......
执行 gen_compile_commands.py 在当前目录下生成 compile_command.json
~/21841/source/vnd/kernel_platform/out$ python3 ../msm-kernel/scripts/clang-tools/gen_compile_commands.py
cp compile_command.json 到 kernel 目录下
~/21841/source/vnd/kernel_platform/out$ cp compile_commands.json ../msm-kernel/QCOM 8650 生成方式:
tools/bazel run //msm-kernel:pineapple_consolidate_compile_commands
MTK DX-3:
tools/bazel run //common:kernel_aarch64_compile_commands
2.2 :clangd命令行参数(可选)
启动clangd时,可以指定一组命令行参数,用于打开/关闭某些功能,这可以在vscode的配置中指定,vscode在启动clangd时会将这组参数传给clangd。如:
以下是个人使用的配置供参考:
"clangd.arguments": [
"--background-index",
"-j=16",
"--clang-tidy",
"--header-insertion=never",
"--completion-style=bundled",
"--all-scopes-completion"
]
完整的参数列表可以在连接到远程服务器的SSH终端中通过以下命令查看:
clangd --help-list
# 隐藏参数可以通过查看
clangd --help-list-hidden
clangd会输出可用选项及其用途,如:
# ...
USAGE: clangd [options]OPTIONS:
--all-scopes-completion - If set to true, code completion will include index symbols that are not defined in the scopes (e.g. namespaces) visible from the code completion point. Such completions can insert scope qualifiers
--background-index - Index project code in the background and persist index on disk.
--check[=<string>] - Parse one file in isolation instead of acting as a language server. Useful to investigate/reproduce crashes or configuration problems. With --check=<filename>, attempts to parse a particular file.
# ...
2.3 :clangd配置文件(可选)
clangd的配置文件是YAML格式,clangd的配置文件可以分为项目配置文件和用户配置文件:
项目配置文件:
位于项目目录下的.clangd文件,如我们可以在源码根目录写一个配置文件:
source/vnd/.clangd
用户配置文件:
Linux下用户配置文件位于:
~/.config/clangd/config.yaml
clangd不会为用户生成以上配置文件,如果没有找到上面路径的用户配置文件,需要自行新建。项目配置文件一般会覆盖用户配置文件中的配置项,如果不需要对每个项目进行单独配置,我们可以将所有配置项写到用户配置文件。
在clang的配置文件中,可以对compile_commands.json中的编译选项进行重写(如启用更多Warning信息);可以指定启用或关闭clang-tidy的检查项,以及对检查项进行配置;可以启用或关闭行内提示(Inlay Hints)等。
clangd完整的配置项可以参考clangd网站的说明,以下是个人配置文件,供参考:
CompileFlags:
# enable more warnings.
Add: [
-Wall,
-Wno-missing-prototypes,
-Wno-error,
]
Remove: [
-W*,
]
Diagnostics:
ClangTidy:
Add: [
bugprone-*,
clang-*,
misc-*,
modernize-*,
performance-*,
readability-*,
]
Remove: [
modernize-use-trailing-return-type,
modernize-avoid-c-arrays,
]
2.4 :clang-format配置文件(可选)
clangd会读取项目目录下的.clang-format文件作为代码风格的配置文件,默认是LLVM风格,配置文件可以参考clang网站的说明。MTK代码目前采用的风格Chromium,参考的配置文件如:
BasedOnStyle:
Chromium
2.5 :添加代码
1、点击远程图标,在自己的服务器上右键选择在当前窗口打开:
2、添加文件夹
菜单“文件” → “将文件夹添加到工作区” ,在弹出的对话框中选择需要添加的文件夹,可以通过多次操作添加多个文件夹。
至此,大功告成。
【关注我,后续持续新增专题博文,谢谢!!!】
下一篇讲解: