docs: C ABI migration campaign plans, handoffs and roadmap
Complete documentation set for the facade migration (B1-R6) and beyond: facade-migration-roadmap, handoffs v3-v6, R5 guides, R6 cleanup plan, R7 pure-ABI plan, long-term plans (riir/ai-agent/gtest/ui-redesign), updated Chinese README draft, UI design mockups, and the Google Test + struct-typedef rules in CONTRIBUTING.
This commit is contained in:
@@ -0,0 +1,216 @@
|
||||
# liboakengine 纯 C ABI 迁移 — 重做交接执行计划(v4)
|
||||
|
||||
> 本文档是后续执行者(DeepSeek Flash 或任何接手代理)的**唯一权威执行依据**。
|
||||
> v4 重写背景:2026-07-23 上一任执行代理误执行 `git checkout --`,把全部未提交的
|
||||
> 迁移工作回滚到 HEAD。后经 JetBrains LocalHistory 部分恢复。
|
||||
> **本文档面向没有此前对话记忆的执行者,自包含。**
|
||||
>
|
||||
> 契约细节(C ABI 头文件规则、事件机制 SOP、undo 规则、硬规则 R1–R6、各 facade 族
|
||||
> 签名)未在本文重复的,均以同目录 `c-abi-migration-handoff.md`(v3,已随
|
||||
> branch 提交保留)为准。两份文档冲突时,**本文(v4)优先**。
|
||||
|
||||
---
|
||||
|
||||
## 0. 事故记录与新的 git 铁律
|
||||
|
||||
### 0.1 发生了什么
|
||||
|
||||
- 迁移战役(B1–B11a)全部工作曾处于**未提交**状态。执行代理误执行
|
||||
`git checkout --`,所有已跟踪文件的修改被回滚到 HEAD(fcf717f6a)。
|
||||
- 未跟踪新文件(约半数 facade 族、全部测试、部分 app 文件、v3 交接文档、
|
||||
RIIR 计划)未受影响;已跟踪文件的修改(node/timeline/project/preview 的
|
||||
facade 扩容、几乎全部 app 侧调用点迁移、CMake 注册、roadmap 记录)丢失。
|
||||
- 用户随后从 JetBrains LocalHistory 导出恢复了一大部分(详见 §2 清单)。
|
||||
- 当前工作全部在分支 **`c-abi-migration`** 上,已有 3 个抢救/修复提交
|
||||
(b11d91f56 → e0e51647d → d1779d74e)。
|
||||
|
||||
### 0.2 新 git 铁律(覆盖此前"禁止 git 写操作"的旧规则)
|
||||
|
||||
1. **所有工作只在 `c-abi-migration` 分支进行。**
|
||||
2. **每完成一个小步立即提交**(一个族、一个文件、一个修复都算一步)。
|
||||
提交信息写明批次与内容。**绝不隔夜持有未提交工作。**
|
||||
3. **严禁** `git checkout --` / `git restore` / `git clean` / `git reset --hard` /
|
||||
`git stash`(这些命令曾毁掉一次战役)。确需回滚某个文件时,用
|
||||
`git show HEAD~N:<path>` 读出内容后手工写回,并先经用户确认。
|
||||
4. push 与否由用户决定;本地提交不需要再请示。
|
||||
|
||||
---
|
||||
|
||||
## 1. 目标与验收(不变)
|
||||
|
||||
1. `liboakengine.so` 动态符号表无 `olive::` C++ 符号(仅 `oakengine_*` + Qt/系统符号)。
|
||||
2. `oak-editor`、`oak-render-worker` 不 import 任何 `olive::` C++ 符号(豁免见 §6.4)。
|
||||
3. 全量测试通过;`engine/include/oakengine/*.h` 每个函数有测试覆盖。
|
||||
4. worker 端到端 harness 保持通过(不重做)。
|
||||
|
||||
**度量命令**(统一口径):
|
||||
|
||||
```bash
|
||||
nm -D cmake-build-debug/app/oak-editor | grep -c " U _ZN5olive" # 总指标
|
||||
nm -D cmake-build-debug/app/oak-editor | grep " U _ZN5olive" | c++filt | sed 's/.* U //;s/(.*//' | awk -F'::' '{print $1"::"$2}' | sort | uniq -c | sort -rn
|
||||
nm -D --defined-only cmake-build-debug/engine/liboakengine.so | grep -c " T _Z"
|
||||
grep -ho "oakengine_[a-z_0-9]*" engine/include/oakengine/*.h | sort -u > /tmp/decl.txt
|
||||
cat engine/tests/oakengine_*_test.cpp | grep -ho "oakengine_[a-z_0-9]*" | sort -u > /tmp/tested.txt
|
||||
comm -23 /tmp/decl.txt /tmp/tested.txt # 覆盖审计
|
||||
cmake --build cmake-build-debug -j$(nproc)
|
||||
cd cmake-build-debug && ctest --output-on-failure -j$(nproc)
|
||||
```
|
||||
|
||||
已知 flaky:`oak_cli_transcode`、`oakengine_export_test`、`olive-gtest`(偶发 SEGFAULT,
|
||||
单独重跑两次仍失败才算真失败)。
|
||||
|
||||
---
|
||||
|
||||
## 2. 当前状态(2026-07-23 实测)
|
||||
|
||||
### 2.1 构建状态
|
||||
|
||||
**当前构建是红的**,错误只集中在 4 个丢失的 facade 扩容族(§3 R1–R4)。
|
||||
其余部分(含 app、worker、cli、liboakcore、liboakengine 既有 facade)编译通过。
|
||||
|
||||
### 2.2 幸存且已提交(不要重做)
|
||||
|
||||
- **完整 facade 族**(头 + 实现 + 测试):`app`、`audio`、`color`、`config`、`disk`、
|
||||
`encoding`、`events`、`gizmo`、`lut`、`plugin`、`proxy`、`serializer`、`sync`、
|
||||
`task`、`traverse`、`undo`、`videoparams`、`viewer`、`worker`,以及更早期已入库的
|
||||
`init`/`ipc`/`export`/`exporter`/`playback`/`spscringbuffer`。
|
||||
- **全部 facade 测试文件**(engine/tests/oakengine_*_test.cpp,含 node/keyframe/
|
||||
timeline_edit/footage/preview/renderer——**丢失族的测试还在,它们就是重做时的
|
||||
API 规格书**)。
|
||||
- **app 侧**:`engineeventbridge.{h,cpp}`、`app/common/*`(configwrapper、undowrapper、
|
||||
colorcodingapp、filefunctionsapp、hashstreamapp、htmlapp、xmlutilsapp、debugapp)、
|
||||
各 handle 头(keyframehandle/markerhandle/cliphandle/trackhandle/colorprocessorhandle/
|
||||
vieweroutpututils)、`markerpainting.*`、`app/timeline/`、`app/ui/icons/`。
|
||||
- **文档**:v3 交接文档(`c-abi-migration-handoff.md`)、RIIR 计划(`plans/riir.md`)、
|
||||
roadmap 批次记录(经 LocalHistory 恢复,`facade-migration-roadmap.md`)。
|
||||
- **结构性改动**:B1 图标(engine 返回图标名 + app from_name 映射,已修复一致)、
|
||||
B2 布局 POD(SerializedLayoutInfo 全链路,已修复一致)、B3 coreengine.h、
|
||||
B7 managedcolor 删除与 VideoParams 头内联、CMake 全部注册(engine/capi/app/ui/
|
||||
timeruler/timeline/serializer/render)、`oak_proxy_params` POD(已补回 footage.h)、
|
||||
undostack B9a 访问器(已补回)、`engine/config/config.h` 的 `#ifndef OAK_CONFIG` 守卫、
|
||||
textv3.h 的 text_gizmo 访问器。
|
||||
|
||||
### 2.3 丢失(= 重做范围)
|
||||
|
||||
| # | 内容 | 批次 |
|
||||
|---|---|---|
|
||||
| R1 | `engine/include/oakengine/node.h`(545→~1500 行)+ `engine/src/capi/node.cpp`(1590→~3700 行):OAK_NODE_VALUE_* 完整枚举、输入元数据/property、值读写、多轨关键帧、`OakEngineKeyframe` 句柄族、NodeDragger、undoable 批量原语、context 位置族、group passthrough 族、multicam 族 | B8a/B8b |
|
||||
| R2 | `timeline.h`/`timeline.cpp`:track 高度换算、block_is_enabled、clip 输入 id 六 getter、`clip_set_media_in`/`request_invalidate`/`discard_cache`/`add_cache_passthrough`、marker 句柄族(OakEngineMarkerList/OakEngineMarker ~20 函数)、workarea 句柄族(~8)、`sequence_add_default_nodes`、`clip_get_media_range_rational`、块遍历族 | B4c |
|
||||
| R3 | `project.h`/`project.cpp`:folder 族(create/has_child_recursive/index_of_child/child_input_key/add_child)+ **`oakengine_folder_move_child`**(v3 新增,单条 undo 移动) | B5 |
|
||||
| R4 | `preview.h`/`preview.cpp`:cacher 四函数、`OakEnginePreviewRequest` 异步请求族(~10 函数)、playback cache 句柄 + `valid_ranges`/`indicator_height`、frame cache 句柄、waveform/audio analyze 两函数;事件 141/142/143 | B9c |
|
||||
| R5 | app 侧全部已跟踪调用点迁移(viewer 簇已恢复到 B9c 前中间态——仍用 RenderTicketWatcher,需随 R4 再迁一次;timelinewidget/nodeview/nodeparamview/projectexplorer/keyframeview/timeruler/dialogs/panels 等数百处) | B1–B11a app 侧 |
|
||||
| R6 | B11b GPU 收尾:renderer.h/cpp 已恢复 B11b 内容(texture/frame 族在),需验证 + 移除 B7 两过渡桥 | B11b |
|
||||
| R7 | B11c staticMetaObject 清理 + B11d visibility 收口与终验 | B11c/B11d |
|
||||
|
||||
### 2.4 事件 ID 与 facade 覆盖基线
|
||||
|
||||
- 事件 ID 已分配到 **143**(140 audio manager、141/142 playback cache、143 frame cache)。
|
||||
新事件从 **144** 起。
|
||||
- facade 覆盖审计在重做期间必然有缺口(丢失族的函数还没回来),**R1–R4 完成后
|
||||
审计必须为空(仅 oakengine_worker_main 豁免)**。
|
||||
|
||||
---
|
||||
|
||||
## 3. 重做执行计划(按顺序,每步闭环:构建 + ctest + 符号度量 + 立即提交)
|
||||
|
||||
### R1 node 族扩容(最大单块,先做)
|
||||
|
||||
1. 以 `engine/tests/oakengine_node_test.cpp`、`oakengine_keyframe_test.cpp` 为
|
||||
**唯一 API 规格**:把测试引用但头文件缺失的函数逐个补回 `oakengine/node.h`
|
||||
(OAK_NODE_VALUE_* 完整枚举、输入元数据/property 全套、值读写、多轨关键帧、
|
||||
`OakEngineKeyframe` 句柄族、`OakEngineNodeDragger`、undoable 批量原语、
|
||||
context 位置、group passthrough、multicam)。
|
||||
2. 实现补进 `engine/src/capi/node.cpp`,模式照现存的 `traverse.cpp`/`undo.cpp`
|
||||
(push_or_run、string_to_buf、impl() 转换)。
|
||||
3. `events.cpp`/`traverse.cpp`(幸存)依赖这些枚举与类型,随 R1 自然恢复编译。
|
||||
4. 验证:oakengine_node_test/keyframe_test/events_test 全过 + 全量 ctest 绿。
|
||||
5. **立即提交。**
|
||||
|
||||
### R2 timeline 族扩容
|
||||
|
||||
1. 以 `oakengine_timeline_edit_test.cpp` 为规格,补 `timeline.h`/`timeline.cpp`
|
||||
(§2.3 R2 列出的全部族;marker/workarea 句柄定义在 timeline.h,
|
||||
`OakEngineMarkerList`/`OakEngineMarker`/`OakEngineWorkarea` typedef 一并补回)。
|
||||
2. app 侧幸存文件(seekablewidget、timeruler、markerpainting、markerhandle)依赖
|
||||
这些类型,随 R2 恢复编译。
|
||||
3. 验证 + 立即提交。
|
||||
|
||||
### R3 project 族 folder 补全
|
||||
|
||||
1. 以 `oakengine_footage_test.cpp`(含 folder 与 `oakengine_folder_move_child`
|
||||
用例)为规格,补 `project.h`/`project.cpp` 的 folder 族与 move_child
|
||||
(move_child 语义:detach 旧 folder + attach 新 folder 合成**一条**
|
||||
MultiUndoCommand;实现参照 v3 §2.2-4 与 footage_test 断言)。
|
||||
2. 验证 + 立即提交。
|
||||
|
||||
### R4 preview 族扩容 + viewer 重迁
|
||||
|
||||
1. 以 `oakengine_preview_test.cpp` 为规格,补 `preview.h`/`preview.cpp`
|
||||
(§2.3 R4 全部;`OakEnginePreviewRequest` 内部 = RenderTicket + Watcher 封装,
|
||||
完成回调走 facade 自有 C 回调不占事件号;playback cache 事件 141/142、
|
||||
frame cache 143 已在 events.h/events.cpp 幸存,检查连通即可)。
|
||||
2. **帧 POD 契约红线**:`oak_playback_frame.linesize` 是**字节**;
|
||||
app 重建 display Frame 用四参构造 `VideoParams(w,h,format,k_internal_channel_count)`
|
||||
(默认构造 depth=0 会导致 Vulkan 上传 0 字节纯黑——v3 §2.2-6 的事故,勿复现)。
|
||||
3. viewer.cpp 随 R4 从 RenderTicketWatcher 中间态迁到 preview_request 流程
|
||||
(参照 v3 §5.2.2 契约;当前 viewer.cpp 是可编译的 B9c 前状态,能跑但符号多)。
|
||||
4. 验证(含 Backends viewer 5 用例)+ 立即提交。
|
||||
|
||||
### R5 app 侧调用点迁移重做
|
||||
|
||||
按 v3 §3 的 36 符号清单逐项消灭(清单以你重做时的 nm 实测为准):
|
||||
- 优先顺序同 v3 §5:杂项小点(Project::name_changed、SubtitleBlock::k_text_in、
|
||||
RenderManager、AudioWaveformCache)→ UndoCommand 3 → Node 5 + NodeFactory 1
|
||||
(**方案 A 钉死:删 nodeimpl.cpp,改调用点走 facade**)→ staticMetaObject 清理。
|
||||
- app 侧纯换调用不加新测试;每族符号归零后立即提交。
|
||||
|
||||
### R6 B11b GPU 收尾
|
||||
|
||||
renderer.h/cpp 已含 texture/frame 族(恢复版)。验证其编译与测试
|
||||
(oakengine_renderer_test),然后按 v3 §3.6 完成显示路径句柄化并移除 B7 两过渡桥
|
||||
(`oakengine_color_transform_job_set_processor`/`oakengine_color_set_display_color_processor`)。
|
||||
验收:Backends viewer 5 用例全过。
|
||||
|
||||
### R7 B11c/B11d 收口
|
||||
|
||||
按 v3 §3.7/§3.8:TrackListRippleToolCommand 遗留评估 → 豁免清单确认
|
||||
(AudioProcessor 4 + Block/Track::staticMetaObject = 6)→ visibility 收口
|
||||
(`CXX_VISIBILITY_PRESET hidden` 或 version script 白名单)→
|
||||
`nm -D --defined-only liboakengine.so | grep -c " T _Z"` = 0 →
|
||||
全量终验 + roadmap 附 C 补记战役完成。
|
||||
|
||||
---
|
||||
|
||||
## 4. 边界契约(沿用 v3,要点重申)
|
||||
|
||||
- C ABI 头只允许 C 类型;buf/size 字符串约定;owned/borrowed 注释;错误码
|
||||
`OAKENGINE_OK`/负数 `OAKENGINE_E_*`。
|
||||
- 改图操作必须 undoable(push_or_run 模式);用户语义上的单次操作必须单条 undo
|
||||
(`oakengine_folder_move_child` 是样板)。
|
||||
- 信号迁移唯一通道 = 事件机制(`oakengine_event_subscribe` + EngineEventBridge,
|
||||
SOP 见 roadmap 附 D);facade 自有 owned 对象的完成回调例外(playback/preview
|
||||
request 先例)。
|
||||
- **v3 §6.6 硬规则 R1–R6 全部继续有效**(ODR/hidden visibility、注册检查、
|
||||
undo 双参、linesize 字节、VideoParams 构造、接手先验证)。
|
||||
- 新 C 函数必须有单元测试;GL/Vulkan 用例可无 GPU 跳过;测试注册进
|
||||
`engine/CMakeLists.txt` 的 `make_oakengine_test`。
|
||||
|
||||
## 5. 禁止事项
|
||||
|
||||
1. **严禁 `git checkout --` / `restore` / `clean` / `reset --hard` / `stash`**(§0.2-3)。
|
||||
2. 禁止暴露 C++ ABI;禁止往 liboakengine 加 `_Z` 导出;禁止 Qt 类型进 core/。
|
||||
3. 禁止改 worker NDJSON 协议;禁止重做 §2.2 已列的幸存部分。
|
||||
4. 禁止修改已钉死签名:各 facade 头现有函数、事件 ID 1–143、v3/v4 契约。
|
||||
5. 禁止降低测试标准;禁止重新 cmake 配置构建目录;禁止改 CI/打包文件。
|
||||
6. 禁止在未验证构建状态前继续批次(R6 规则)。
|
||||
|
||||
## 6. 环境备忘
|
||||
|
||||
- 分支:`c-abi-migration`(已含 3 个抢救/修复提交)。
|
||||
- 构建目录 `cmake-build-debug`(Ninja + Qt6,Debug);asan/coverage 目录不要用。
|
||||
- 测试素材 `tests/demo.mp4`、`tests/img.png`、`tests/project_with_footage.ove`。
|
||||
- 本机有 GPU,Vulkan 用例真实执行;OpenGL offscreen 用例 SKIP 属正常。
|
||||
- 全量 ctest 44+ 个约 90–140s。
|
||||
- 单文件增量验证:`rm -f cmake-build-debug/app/CMakeFiles/libolive-editor.dir/<相对路径>.o && cmake --build cmake-build-debug --target olive-editor -j$(nproc)`。
|
||||
- 恢复工具备忘:JetBrains LocalHistory(`~/.cache/JetBrains/CLion*/LocalHistory`)
|
||||
在 IDE 里按目录 Show History 可再挖;git fsck 悬空对象已查无可用内容。
|
||||
Reference in New Issue
Block a user