cpp-coro-graph
# cpp-coro-graph
一个语法层级(syntax-level)的 **C++17 协程 + 设备标签(device)** 调用图工具。
**主要运行目标:Linux。** 仅依赖 Python 3.9+ 标准库(运行时不需要额外 pip 依赖)。
功能概览:
- **所有函数都建点**:包括定义 `{...}` 和声明 `Foo();` / `= default` / `= delete`
- 类/结构体成员函数会解析为 `Class::Method`(含构造/析构)
- 从 `co_await` / `CO_AWAIT` 提取 **`await`** 边,同时保留普通 **`calls`** 边
- 从 `spawn` / `scope->spawn` / `sync_wait` 等 **peel** 出真实 worker,生成 **`spawn`**(或 calls)边
- `when_all(...)` 内的并行任务会 peel 成多条 **`await`**
- 成员调用链支持:`co_await m.Init()` → `SosModel::Init`
- 通过 `rules/devices.json` 标注 **device**(`cpu` / `gpu` / `npu` / `dsp`;与业务 namespace 如 `yuv_domain` 区分)
- 文件节点可查;`#include` → **`includes`**;按 **namespace** 过滤;`ccg seq` / `--by-namespace`
- 提供 HTML 可视化 + **CodeGraph 风格 CLI**(`ccg`)+ MCP 服务
## 回归样例 `fake_sample/`
最小化 C++ 树,覆盖 **P1–P11**(spawn+`on_empty`、`when_all`、类成员/重载/模板、header-only、深 await、`sync_wait`、同名不同 namespace、多级 include、多 stage seq)。
```bash
python3 scripts/verify_fake_sample.py # 自动回归(推送前已跑通)
# 人工对照预期:fake_sample/verify.md
ccg index fake_sample && ccg query --namespace nsA::moduleB --kind coroutine
```
## 安装 CLI(类似 `codegraph`)
```bash
git clone https://github.com/ArcherLin13/cpp-coro-graph.git
cd cpp-coro-graph
# 把 `ccg` 放到 PATH(~/.local/bin)— 不需要 pip
chmod +x scripts/*.sh scripts/ccg scripts/cpp-coro-graph
./scripts/install_cli.sh
# 确保 ~/.local/bin 已加入 PATH
# 或者:可编辑安装
python3 -m pip install -e .
```
安装后可使用短命令(与 CodeGraph 体验一致):
```bash
ccg index /path/to/repo # 生成 .cpp-coro-graph/graph.db
cd /path/to/repo # --db 会向上自动发现
ccg status
ccg status --by-namespace
ccg query OnSos
ccg query --kind file processor.h
ccg query --namespace nsA::moduleB --kind coroutine
ccg node OnSos # symbol: callers + callees
ccg node file:src/foo.cpp # file: contains / includes / importers
ccg callers OnSos
ccg callees OnSos
ccg seq OnSos # ordered calls/await inside a function
ccg explore OnSos # in/out + wider neighborhood
ccg path Call Init # control path A → B(file 查询则走 includes)
ccg impact OnSos
ccg viz --module path/to/module
```
别名关系:`cpp-coro-graph` == `ccg`。
不安装也可直接用:`./scripts/ccg callers OnSos --db .../graph.db`
## 建库(Index)
```bash
ccg index /path/to/your/linux/repo
# 或者一条命令完成 index + HTML + status
./scripts/index_repo.sh /path/to/your/linux/repo
```
日常改代码后增量更新(不用全量 index):
```bash
ccg sync /path/to/your/linux/repo
# 或在仓库根目录(自动发现 .cpp-coro-graph/graph.db)
cd /path/to/your/linux/repo && ccg sync
```
`sync` 会对比文件的 size/mtime,只重解析**新增/变更**的文件,以及**调用到这些文件符号**的 caller 文件。
第一次没有 db 时会自动退化为全量 `index`。
输出文件位于仓库目录下:
- `.cpp-coro-graph/graph.db`
- `.cpp-coro-graph/graph.html` (from `ccg viz` / index script)
建议在源码所在的 Linux 机器上运行(避免 WSL 的 `/mnt/c/...` 路径)。
冒烟与回归验证(覆盖 spawn / fx::ex::on / run_* / 模板 co_await):
```bash
python3 scripts/validate_fixtures.py # aigc + pipeline + sample
ccg index fixtures/aigc --db /tmp/aigc.db
ccg node run_pipeline --db /tmp/aigc.db
ccg path run_pipeline Init --db /tmp/aigc.db
```
## 快速查关系
| 需求 | 命令 |
|------|---------|
| 查符号 | `ccg query Keyword` |
| 谁调用了 X / X 调用了谁 | `ccg node X` |
| 只看调用者 | `ccg callers X` |
| 只看被调方 | `ccg callees X` |
| 邻域展开 | `ccg explore X`(默认 `--depth 2`) |
| A 如何到达 B | `ccg path A B` |
| 变更影响面 | `ccg impact X` |
| 脚本化 JSON 输出 | 加 `--json` |
默认边过滤是 **control** = `calls` + `await`。
如果关注结构关系,使用 `--edge-kind inherits,contains`。
## 可视化(模块主干)
```bash
ccg viz --module path/to/module --depth 2
ccg viz --around Call --depth 2
ccg viz --full # 旧版全图模式,大工程不建议
```
浏览器交互:选择 module → 选择 entry chip → **双击节点**展开下一层。`calls` 默认开启。
## OpenCode MCP(快速接入)
和 CodeGraph 类似:**先在终端建库**,再让 Agent 通过 MCP **只读查询**。
重要限制:
- MCP **不会** `index` / `sync`,也**不会**生成 `graph.db`
- Agent 调 `ccg_*` 时**不能**临时换另一个 db;启动 MCP 时就定死连接哪一个库
- 源码变更后要在终端跑 `ccg sync`(或全量 `ccg index`),再继续用 MCP 查
```bash
# 1) 先保证 CLI 在 PATH
./scripts/install_cli.sh # 或者: pip install -e .
# 2) 对你的 C++ 仓库建库(这一步必须做;MCP 不会帮你做)
ccg index /path/to/your/repo
# 之后改代码:ccg sync
# 3) 写入 OpenCode 配置(项目级或全局)
cd /path/to/your/repo
ccg install-opencode --agents # 写入 ./opencode.json + AGENTS.md 提示
# 或用户级:
ccg install-opencode --global
# 4) 重启 OpenCode 并检查
opencode mcp list
```
若 `opencode mcp list` **timeout**:
> 调大 `timeout` **通常没用**。OpenCode 的 `timeout` 是「握手/拉 tools」的等待上限;
> 一直 timeout = **进程根本没回 initialize**(命令起不来、stdout 被缓冲、或 PATH/模块错误),不是“太慢”。
请按下面排查:
```bash
# 1) 看 install 写进去的真实 command
ccg install-opencode --agents --db /abs/path/.cpp-coro-graph/graph.db
# 会打印: mcp command: ["/usr/bin/python3", "-u", ".../scripts/ccg_mcp.py", "--db", "..."]
# 2) 手动跑同一条 command(应卡住等 stdin,stderr 有 mcp entry 日志)
python3 -u /path/to/cpp-coro-graph/scripts/ccg_mcp.py --db /abs/path/graph.db
# Ctrl+C 退出。如果立刻 ModuleNotFoundError / 找不到文件 → 先修这个
# 3) 确认 opencode.json 里是 type=local + command 数组(不要用 args/env 旧字段)
```
| 现象 | 原因 | 处理 |
|------|------|------|
| timeout / **MCP error -32001** 且调大无效 | 握手无响应(常见:帧头只认 CRLF、进程起不来、stdout 缓冲) | 更新后重装;手动跑 `ccg_mcp.py`;Windows Desktop 有已知 stdio 问题 |
| command not found: `ccg` | OpenCode PATH 无 `ccg` | 重装(新安装器不再依赖裸 `ccg`) |
| tools 返回 no graph.db | 还没建库 / cwd 不对 | `ccg index .` 或 `--db` 绝对路径 |
| 仅 Windows 全挂 | OpenCode 已知 Windows stdio 问题 | 尽量在 Linux 跑 OpenCode;或升级 OpenCode |
推荐稳妥写法(pin db + 重装配置):
```bash
cd /path/to/your/repo
ccg index .
ccg install-opencode --agents --db "$(pwd)/.cpp-coro-graph/graph.db"
```
`opencode.json` 配置示例(`examples/opencode.json` 里也有;`command` 应为绝对 python 路径):
```json
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"cpp-coro-graph": {
"type": "local",
"command": ["ccg", "mcp"],
"enabled": true,
"timeout": 15000
}
}
}
```
### MCP 怎么选 db?
启动 `ccg mcp` 时按下面顺序决定**唯一**的 db,之后所有查询都用它:
1. 配置里显式 `--db`(最稳)
`ccg install-opencode --db /abs/path/.cpp-coro-graph/graph.db`
→ command 变成 `["ccg", "mcp", "--db", "/abs/.../graph.db"]`
2. 未写 `--db`:从 **OpenCode 启动 MCP 时的项目 cwd** 向上查找
`.cpp-coro-graph/graph.db`(最多 8 层)
因此推荐:在目标 C++ 仓库根目录执行 `ccg index` + `ccg install-opencode`,让 cwd 自动对上该仓库的 db。
### MCP 工具(Agent 侧)
| 工具 | 用途 |
|------|-----|
| `ccg_node` | 符号详情 + callers + callees(建议从这里开始) |
| `ccg_callers` / `ccg_callees` | 单方向查询 |
| `ccg_explore` | 邻域展开(`depth`) |
| `ccg_path` | `src` 如何到达 `dst` |
| `ccg_impact` | 变更影响面 |
| `ccg_query` / `ccg_stats` | 搜索 / 健康检查 |
没有 `ccg_index` / `ccg_sync` 工具——建库请用终端 CLI。
Prompt 建议:*“use ccg_node on OnSos”*,或直接把安装生成的 AGENTS.md 片段贴进系统提示。
### Cursor MCP(可选)
同样需要先 `ccg index`;db 发现规则与上面相同(cwd 向上找,或 args 里加 `--db`):
```json
{
"mcpServers": {
"cpp-coro-graph": {
"command": "ccg",
"args": ["mcp"]
}
}
}
```
## 自定义设备规则(device)
字段名为 **`device`**(取值 `cpu`/`gpu`/`npu`/`dsp`),不要与业务 C++ namespace(如 `yuv_domain`)混淆。
可直接修改 `rules/devices.json`,或通过 `--rules your.json` 传入:
```json
{
"patterns": [
{"match": "RunOnNpu", "device": "npu", "backend": "custom"},
{"match": "clEnqueue", "device": "gpu", "backend": "opencl"}
]
}
```
规则按顺序匹配,命中即停;建议把更长、更具体的匹配项放前面。
## 边类型(Edge kinds)
| kind | 可视化 | 含义 |
|------|-----|---------|
| **`calls`** | 青色实线 | 直接/同步调用 |
| **`await`** | 红色虚线 | `co_await` / `CO_AWAIT`(含 `when_all` peel 出的并行任务) |
| **`spawn`** | 橙色 | 从 `spawn` / `scope->spawn` / `sync_wait` 等 peel 出的 worker |
| **`seq`** | 紫色虚线 `then` | 同一 caller 内:前一个被调 → 后一个被调(顺序) |
| **`includes`** | (默认不画) | `#include`:file → file |
| **`contains`** | 灰色 | 文件包含函数/类 |
| **`inherits`** | 绿色虚线 | `class Child : public Base` |
查询提示:
- `ccg query --kind file module_b` / `ccg node file:src/foo.cpp` — 文件节点 + contains / includes / importers
- `ccg query --namespace ns::mod --kind coroutine` — 按 namespace 过滤
- `ccg seq Call` — 函数内按行号的 calls/await/spawn 序列
- `ccg status --by-namespace` — 模块级符号计数
- 文件间:`ccg path file:A.h file:B.cpp`、`ccg impact pipeline.hpp`(走 includes)
`callers` / `callees` 默认 **control** = `calls` + `await` + `spawn`。
`ccg callees Call` 会按源码顺序输出 `#1 #2 …`。可视化里可切换 **seq (顺序)**;可展开节点会显示 **+** 和琥珀色边框。
```bash
ccg callees Call # 按顺序输出 #1 Init, #2 Load, …
ccg explore Init --edge-kind seq # Init -[seq]-> Load(在 Call 中的下一步)
ccg viz --module .
```
## 默认跳过目录
`.git`, `build`, `out`, `third_party`, `node_modules`, `.codegraph`, `bazel-*`, `.repo`, `prebuilts`, …
TDQS
Scored across 11 tools
Many tools have clear distinct purposes (stats, query, node, callers, callees, seq, path, impact), but ccg_explore and ccg_seq overlap with ccg_node's related edges and callers/callees, creating some ambiguity. The presence of aliases (coro_stats, coro_explore) adds confusion for an agent.
Most tools follow a consistent ccg_verb or ccg_noun pattern (ccg_stats, ccg_query, ccg_node, ccg_callers, etc.), which is predictable. However, the aliases coro_stats and coro_explore deviate from the ccg_ prefix, slightly breaking consistency.
11 tools is a reasonable count for a graph-based code analysis server covering stats, query, traversal, and impact. The two aliases are redundant but don't bloat the count excessively.
The tool set covers essential operations: graph stats, symbol/file lookup, edge exploration (callers, callees, sequence), path finding, and impact analysis. It lacks explicit filtering or aggregation tools, but the core analysis surface is well-covered for a read-only graph explorer.