linglong/docs/pages/guide/debug/debug.md

177 lines
7.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!--
SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
SPDX-License-Identifier: LGPL-3.0-or-later
-->
# 调试如意玲珑应用
以下教程以“构建工具”一节中提到的 org.deepin.demo 项目为例。
我们将项目放在 `/tmp`。参考教程操作时**注意对路径进行替换**。
## 在终端中使用 gdb 进行调试
### 在调试环境运行应用
在 [运行编译后的应用](../reference/commands/ll-builder/run.md) 一节中,我们已经知道使用`ll-builder run --exec /bin/bash`可以运行编译后的应用并进入容器的终端。只需要再 run 后面加上 `--debug` 参数即可以调试环境运行容器并进入容器。调试环境和非调试环境的区别主要有以下几点:
1. 调试环境会使用 base 和 runtime 的 binary+develop 模块,而非调试环境会使用 binary 模块gdb 工具就在 base 的 develop 模块中。
2. 调试环境会使用 app 的 binary+develop 模块,而非调试环境默认使用 binary 模块(一般会将应用的调试符号保存到 develop 模块)。
3. 调试环境会在项目目录生成 linglong/gdbinit 文件并挂载到容器中的 ~/.gdbinit 路径。
请在项目目录执行`ll-builder run --debug --exec /bin/bash` 进入调试环境容器,然后执行 `gdb /opt/apps/org.deepin.demo/binary/demo` 启动应用的调试,和在外部使用命令行调试并无区别,这得益于调试 linglong/gdbinit 文件为 `gdb` 提供了初始配置。
### 在运行环境调试应用
调试环境和用户正常使用的运行环境是存在小部分差异的,如果需要直接在运行环境中调试应用,可以使用 `ll-builder run --exec /bin/bash` 进入容器,然后执行 `gdbserver 127.0.0.1:12345 /opt/apps/org.deepin.demo/bin/demo` gdbserver 会使用 tcp 协议监听 12345 端口并等待 gdb 连接。
再打开一个宿主机终端,在项目目录执行 `gdb`,按行输入以下指令:
```txt
set substitute-path /project /tmp/org.deepin.demo
set debug-file-directory /tmp/org.deepin.demo/linglong/output/develop/files/lib/debug
target remote 127.0.0.1:12345
```
即可使用 gdb 通过 tcp 协议连接到运行环境中的 gdbserver 调试应用。
_如果运行环境没有 gdbserver 命令,请检查应用是否使用 org.deepin.base 作为 base尝试升级到最新版本的 org.deepin.base。_
## 在 vscode 中使用 gdb 进行调试
首先给 vscode 安装 C/C++ 插件,因为 vscode 是运行在宿主机上的,所以也需要通过 gdbserver 来为如意玲珑容器中的应用提供调试。和上个步骤一样,先在运行环境中启动 gdbserver然后 vscode 配置好 launch.json 文件即可。具体配置如下:
```json
{
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) linglong",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/linglong/output/binary/files/bin/demo",
"args": [],
"stopAtEntry": true,
"cwd": "${workspaceFolder}",
"MIMode": "gdb",
"miDebuggerServerAddress": "127.0.0.1:12345",
"setupCommands": [
{
"text": "set substitute-path /project ${workspaceFolder}"
},
{
"text": "set debug-file-directory ${workspaceFolder}/linglong/output/develop/files/lib/debug"
}
]
}
]
}
```
部分配置需要按照项目实际情况更改:
- "program": "${workspaceFolder}/linglong/output/binary/files/bin/demo",
这是传递给 gdb 的二进制文件,`demo` 需要更改为项目实际的二进制文件名
- "stopAtEntry": true
这是要求 gdb 在 main 函数自动停止,如果不需要可以设置为 false
- "miDebuggerServerAddress": "127.0.0.1:12345"
这是 gdb 连接的远程地址,在启动 gdbserver 时如果端口不是默认的 12345需要修改为实际端口。
- "text": "set substitute-path /project ${workspaceFolder}"
这是设置源码路径的替换,`${workspaceFolder}` vscode 会自动替换成当前工作目录,如果需要更改为实际路径可以修改。
- "text": "set debug-file-directory ${workspaceFolder}/linglong/output/develop/files/lib/debug"
这里是设置调试文件的目录,如果调试符号没有保存到`develop`模块,需要修改为实际位置。
## 在 Qt Create 中使用 gdb 进行调试
Qt Create 也集成了对 gdb 的支持,启动 Qt Create 后打开菜单栏中的 `调试` -> `开始调试` -> `连接到正在运行的调试服务器`,在弹出的对话框中填入:
```text
服务器端口:`12345`
本地执行档案:`/tmp/org.deepin.demo/linglong/output/binary/files/bin/demo`
工作目录:`/tmp/org.deepin.demo`
Init Commands: `set substitute-path /project /tmp/org.deepin.demo`
调试信息:`/tmp/org.deepin.demo/linglong/output/develop/files/lib/debug`
```
大致配置如下图所示:
![qt-creator](images/qt-creator.png)
配置完成后,即可正常使用`QtCreator`来进行调试了。
## 保存调试符号
如意玲珑在构建应用后会自动剥离二进制的调试符号,并存放到 `$PREFIX/lib/debug` 目录,但是一些工具链会在构建时提前将调试符号剥离,这会导致如意玲珑无法在二进制文件中找到这些符号,如果你的项目是使用 qmake需要在 pro 文件中添加以下配置
```bash
# 如意玲珑在CFLAGS和CXXFLAGS环境变量里设置了-g选项这里需要qmake继承这个环境变量
QMAKE_CFLAGS += $$(CFLAGS)
QMAKE_CXXFLAGS += $$(CXXFLAGS)
# 使用debug选项避免qmake自动剥离调试符号
CONFIG += debug
```
cmake 会自动使用 cflags 和 cxxflags 环境变量,所以不需要额外配置。其他构建工具可自定查询文档。
## 从debian仓库下载调试符号
由于base镜像中没有包含调试符号如果需要调试应用的系统依赖库需要从base对应的debian仓库手动下载调试符号包。具体步骤如下
1. 使用以下命令之一进入容器命令行环境:
```bash
ll-builder run --bash
# 或
ll-cli run $appid --bash
```
2. 查看base镜像使用的仓库地址:
```bash
cat /etc/apt/sources.list
```
3. 在宿主机浏览器中打开仓库地址定位依赖库的deb包所在目录:
- 使用命令 `apt-cache show <package-name> | grep Filename` 查看deb包在仓库中的路径
- 完整的下载地址为: 仓库地址 + deb包路径
例如要下载libgtk-3-0的调试符号包:
```bash
apt-cache show libgtk-3-0 | grep Filename
# 输出: pool/main/g/gtk+3.0/libgtk-3-0_3.24.41-1deepin3_amd64.deb
# 完整目录: <repo-url>/pool/main/g/gtk+3.0/
```
4. 在该目录下寻找对应的调试符号包,通常有两种命名格式:
- `<package-name>-dbgsym.deb`
- `<package-name>-dbg.deb`
5. 下载并解压调试符号包:
```bash
dpkg-deb -R <package-name>-dbgsym.deb /tmp/<package-name>
```
6. 配置调试器查找调试符号:
在上面的场景设置debug-file-directory时追加解压的目录用冒号分隔:
```
${workspaceFolder}/linglong/output/develop/files/lib/debug:/tmp/<package-name>/usr/lib/debug
```
这样调试器就能在解压的目录中找到系统依赖库的调试符号了。