Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

linglong debug test #26

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions api/schema/v1.json
Original file line number Diff line number Diff line change
Expand Up @@ -911,6 +911,47 @@
}
}
}
},
"merged": {
"type": "array",
"items": {
"type": "object",
"description": "Merge multiple modules into one directory",
"title": "RepositoryCacheMergedItem",
"required": [
"id",
"modules",
"commits"
],
"properties": {
"id": {
"type": "string",
"description": "binary module ostree commit hash"
},
"name": {
"type": "string",
"description": "human readable name"
},
"binaryCommit": {
"type": "string",
"description": "binary module ostree commit hash"
},
"modules": {
"type": "array",
"description": "list of merged module names",
"items": {
"type": "string"
}
},
"commits": {
"type": "array",
"description": "list of ostree commit hashes for each module",
"items": {
"type": "string"
}
}
}
}
}
}
}
Expand Down
30 changes: 30 additions & 0 deletions api/schema/v1.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -705,6 +705,36 @@ $defs:
description: ostree commit hash
info:
$ref: '#/$defs/PackageInfoV2'
merged:
type: array
items:
type: object
description: Merge multiple modules into one directory
title: RepositoryCacheMergedItem
required:
- id
- modules
- commits
properties:
id:
type: string
description: binary module ostree commit hash
name:
type: string
description: human readable name
binaryCommit:
type: string
description: binary module ostree commit hash
modules:
type: array
description: list of merged module names
items:
type: string
commits:
type: array
description: list of ostree commit hashes for each module
items:
type: string
type: object
properties:
# NOTE: "properties" is auto generated by referring all types is $defs
1 change: 0 additions & 1 deletion apps/generators/30-user-home/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,6 @@ int main()
} else {
std::cerr << "failed to mask bashrc" << std::endl;
}

std::cout << content.dump() << std::endl;
return 0;
}
20 changes: 18 additions & 2 deletions apps/ll-builder/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -589,10 +589,17 @@ int main(int argc, char **argv)
"file path of the linglong.yaml (default is ./linglong.yaml)",
"path",
"linglong.yaml");
auto execModules =
QCommandLineOption("modules",
"run using the specified module. eg --modules binary,develop",
"modules");
auto execVerbose =
QCommandLineOption("exec", "run exec than build script", "command");
auto buildOffline = QCommandLineOption("offline", "only use local files.", "");
parser.addOptions({ yamlFile, execVerbose, buildOffline });
auto debugMode =
QCommandLineOption("debug", "run in debug mode(base and runtime)", "");

parser.addOptions({ yamlFile, execVerbose, execModules, buildOffline, debugMode });

parser.addPositionalArgument("run", "run project", "build");

Expand All @@ -613,14 +620,23 @@ int main(int argc, char **argv)
if (parser.isSet(execVerbose)) {
exec = splitExec(parser.value(execVerbose));
}
QStringList modules = { "binary" };
if (parser.isSet(execModules)) {
modules = parser.value(execModules).split(",");
}
bool debug = false;
if (parser.isSet(debugMode)) {
modules.push_back("develop");
debug = true;
}
if (parser.isSet(buildOffline)) {
auto cfg = builder.getConfig();
cfg.skipFetchSource = true;
cfg.skipPullDepend = true;
cfg.offline = true;
builder.setConfig(cfg);
}
auto result = builder.run(exec);
auto result = builder.run(modules, exec, debug);
if (!result) {
qCritical() << result.error();
return -1;
Expand Down
6 changes: 3 additions & 3 deletions docs/pages/en/guide/ll-builder/create.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@ Arguments:
The `ll-builder create` command creates a folder in the current directory according to the project name, and generates the `linglong.yaml` template file required for the build. Here is an example:

```bash
ll-builder create org.deepin.hello
ll-builder create org.deepin.demo
```

Here is the output:

```text
org.deepin.hello/
org.deepin.demo/
└── linglong.yaml
```

Expand All @@ -54,7 +54,7 @@ version: "1"

```yaml
package:
id: org.deepin.hello
id: org.deepin.demo
name: hello
version: 0.0.0.1
kind: app
Expand Down
126 changes: 89 additions & 37 deletions docs/pages/guide/debug/debug.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,71 +6,123 @@ SPDX-License-Identifier: LGPL-3.0-or-later

# 调试玲珑应用

以下教程以“构建工具”一节中提到的 [linglong-builder-demo](https://github.com/linuxdeepin/linglong-builder-demo) 项目为例。我们将项目放在 `/path/to/project`。参考教程操作时**注意对路径进行替换**
以下教程以“构建工具”一节中提到的 org.deepin.demo 项目为例。

由于玲珑应用运行在容器中,想要在宿主机上对其进行调试,我们需要在容器中使用 `gdbserver` 运行应用,所以首先需要安装 `gdbserver`
我们将项目放在 `/tmp`。参考教程操作时**注意对路径进行替换**

我们可以使用发行版提供的 `gdbserver`,以 `apt` 为例:
## 在终端中使用 gdb 进行调试

```bash
sudo apt install gdbserver gdb -y
```
### 在调试环境运行应用

接下来参考“运行编译后的应用”中的教程,通过 `ll-build run` 命令在容器中运行 `bash`,并通过 `gdbserver` 运行需要被调试的应用
在 [运行编译后的应用](../ll-builder/run.md) 一节中,我们已经知道使用`ll-builder run --exec /bin/bash`可以运行编译后的应用并进入容器的终端。只需要再 run 后面加上 `--debug` 参数即可以调试环境运行容器并进入容器。调试环境和非调试环境的区别主要有以下几点

```bash
ll-build run --exec /bin/bash
# 在容器中:
gdbserver :10240 deepin-draw
```
1. 调试环境会使用 base 和 runtime 的 binary+develop 模块,而非调试环境会使用 binary 模块,gdb 工具就在 base 的 develop 模块中。
2. 调试环境会使用 app 的 binary+develop 模块,而非调试环境默认使用 binary 模块(一般会将应用的调试符号保存到 develop 模块)。
3. 调试环境会在项目目录生成 linglong/gdbinit 文件并挂载到容器中的 ~/.gdbinit 路径。

上述命令中,`:10240`为任意当前没有被占用的 tcp 端口。之后我们还需要做两件事情:
请在项目目录执行`ll-builder run --debug --exec /bin/bash` 进入调试环境容器,然后执行 `gdb /opt/apps/org.deepin.demo/binary/demo` 启动应用的调试,和在外部使用命令行调试并无区别,这得益于调试 linglong/gdbinit 文件为 `gdb` 提供了初始配置。

1. 在容器外使用 `gdb` 连接上容器中的 `gdbserver`;
2. 设置源码映射路径。
### 在运行环境调试应用

## 在终端中使用 gdb 进行调试
调试环境和用户正常使用的运行环境是存在小部分差异的,如果需要直接在运行环境中调试应用,可以使用 `ll-builder run --exec /bin/bash` 进入容器,然后执行 `gdbserver 127.0.0.1:12345 /opt/apps/org.deepin.demo/binary/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 调试应用。使用`ll-cli run $appid --exec /bin/bash` 也可使用 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"
}
]
}
]
}
```

1. 找到容器中被执行的可执行文件在宿主机上的位置,对于如上项目,该文件位于 `/path/to/project/.linglong-target/overlayfs/up/opt/apps/org.deepin.demo/files/bin/demo`。
部分配置需要按照项目实际情况更改:

对于通过 `ll-cli` 安装的应用,其可执行程序一般位于 `$LINGLONG_ROOT/layers/[appid]/[version]/[arch]/files/bin` 下。
- "program": "${workspaceFolder}/linglong/output/binary/files/bin/demo",

在容器外使用 `gdb` 加载该程序:
这是传递给 gdb 的二进制文件,`demo` 需要更改为项目实际的二进制文件名

```bash
gdb /path/to/project/.linglong-target/overlayfs/up/opt/apps/org.deepin.demo/files/bin/demo
```
- "stopAtEntry": true

2. 在 `gdb` 中使用 `target` 命令连接 `gdbserver`,操作如下所示:
这是要求 gdb 在 main 函数自动停止,如果不需要可以设置为 false

```bash
target remote :10240
```
- "miDebuggerServerAddress": "127.0.0.1:12345"

3. 在 `gdb` 中输入以下命令以设置路径映射,帮助 `gdb` 找到对应的源代码,假定源码放置在主机的`Desktop`,命令如下:
这是 gdb 连接的远程地址,在启动 gdbserver 时如果端口不是默认的 12345,需要修改为实际端口。

```bash
set substitute-path /source /path/to/project
```
- "text": "set substitute-path /project ${workspaceFolder}"

之后正常使用 `gdb` 即可
这是设置源码路径的替换,`${workspaceFolder}` vscode 会自动替换成当前工作目录,如果需要更改为实际路径可以修改

## QtCreator 配置
- "text": "set debug-file-directory ${workspaceFolder}/linglong/output/develop/files/lib/debug"

参考上述过程,我们可以很轻松地完成 `QtCreator` 的配置:
这里是设置调试文件的目录,如果调试符号没有保存到`develop`模块,需要修改为实际位置。

依次点击:调试>开始调试>连接到正在运行的调试服务器,在对话框中填入:
## 在 Qt Create 中使用 gdb 进行调试

Qt Create 也集成了对 gdb 的支持,启动 Qt Create 后打开菜单栏中的 `调试` -> `开始调试` -> `连接到正在运行的调试服务器`,在弹出的对话框中填入:

```text
服务器端口:`10240`
服务器端口:`12345`

本地执行档案:`/tmp/org.deepin.demo/linglong/output/binary/files/bin/demo`

工作目录:`/tmp/org.deepin.demo`

本地执行档案:`/path/to/project/.linglong-target/overlayfs/up/opt/apps/org.deepin.demo/files/bin/demo`
Init Commands: `set substitute-path /project /tmp/org.deepin.demo`

Init Commands: `set substitute-path /source /path/to/project`
调试信息:`/tmp/org.deepin.demo/linglong/output/develop/files/lib/debug`
```

大致配置如下图所示:

![qt-creator](images/qt-creator.png)

配置完成后,即可正常使用`QtCreator`来进行调试了。

## 保存调试符号

玲珑在构建应用后会自动剥离二进制的调试符号,并存放到 `$PREFIX/lib/debug` 目录,但是一些工具链会在构建时提前将调试符号剥离,这会导致玲珑无法在二进制文件中找到这些符号,如果你的项目是使用 qmake,需要在 pro 文件中添加以下配置

```
# 玲珑在CFLAGS和CXXFLAGS环境变量里设置了-g选项,这里需要qmake继承这个环境变量
QMAKE_CFLAGS += $$(CFLAGS)
QMAKE_CXXFLAGS += $$(CXXFLAGS)
# 使用debug选项避免qmake自动剥离调试符号
CONFIG += debug
```

cmake 会自动使用 cflags 和 cxxflags 环境变量,所以不需要额外配置。其他构建工具可自定查询文档。
Binary file modified docs/pages/guide/debug/images/qt-creator.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion docs/pages/guide/ll-builder/build.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,6 @@ ll-builder build
ll-builder build --exec /bin/bash
```

进入容器后,可执行 `shell`命令,如 `gdb`、`strace` 等。
进入容器后,可执行 `shell`命令,如 `ps`、`ls` 等。

玲珑应用 `debug`版本更多调试信息请参考:[DEBUG](../debug/debug.md)。
14 changes: 7 additions & 7 deletions docs/pages/guide/ll-builder/create.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,17 @@ Arguments:
`ll-builder create`命令根据输入的项目名称在当前目录创建对应的文件夹,同时生成构建所需的 `linglong.yaml`模板文件。示例如下:

```bash
ll-builder create org.deepin.hello
ll-builder create org.deepin.demo
```

`ll-builder create org.deepin.hello`命令输出如下:
`ll-builder create org.deepin.demo`命令输出如下:

```text
org.deepin.hello/
org.deepin.demo/
└── linglong.yaml
```

## 编辑linglong.yaml
## 编辑 linglong.yaml

### linglong.yaml 文件语法的版本

Expand All @@ -54,7 +54,7 @@ version: "1"

```yaml
package:
id: org.deepin.hello
id: org.deepin.demo
name: hello
version: 0.0.0.1
kind: app
Expand Down Expand Up @@ -88,7 +88,7 @@ command: [echo, -e, hello world]

### 源码

使用git源码
使用 git 源码

```yaml
sources:
Expand All @@ -110,7 +110,7 @@ build: |
make install
```

### 完整的linglong.yaml配置
### 完整的 linglong.yaml 配置

`linglong.yaml`文件内容如下:

Expand Down
Loading
Loading