Files
oak-editor/docs/zh/c-abi-migration-handoff-v4.md
T
Mike-Solar c486c853ff 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.
2026-07-26 22:42:44 +08:00

13 KiB
Raw Blame History

liboakengine 纯 C ABI 迁移 — 重做交接执行计划(v4)

本文档是后续执行者(DeepSeek Flash 或任何接手代理)的唯一权威执行依据。 v4 重写背景:2026-07-23 上一任执行代理误执行 git checkout --,把全部未提交的 迁移工作回滚到 HEAD。后经 JetBrains LocalHistory 部分恢复。 本文档面向没有此前对话记忆的执行者,自包含。

契约细节(C ABI 头文件规则、事件机制 SOP、undo 规则、硬规则 R1R6、各 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-editoroak-render-worker 不 import 任何 olive:: C++ 符号(豁免见 §6.4)。
  3. 全量测试通过;engine/include/oakengine/*.h 每个函数有测试覆盖。
  4. worker 端到端 harness 保持通过(不重做)。

度量命令(统一口径):

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)

已知 flakyoak_cli_transcodeoakengine_export_testolive-gtest(偶发 SEGFAULT, 单独重跑两次仍失败才算真失败)。


2. 当前状态(2026-07-23 实测)

2.1 构建状态

当前构建是红的,错误只集中在 4 个丢失的 facade 扩容族(§3 R1–R4)。 其余部分(含 app、worker、cli、liboakcore、liboakengine 既有 facade)编译通过。

2.2 幸存且已提交(不要重做)

  • 完整 facade 族(头 + 实现 + 测试):appaudiocolorconfigdiskencodingeventsgizmolutpluginproxyserializersynctasktraverseundovideoparamsviewerworker,以及更早期已入库的 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 布局 PODSerializedLayoutInfo 全链路,已修复一致)、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.h545→~1500 行)+ engine/src/capi/node.cpp1590→~3700 行):OAK_NODE_VALUE_* 完整枚举、输入元数据/property、值读写、多轨关键帧、OakEngineKeyframe 句柄族、NodeDragger、undoable 批量原语、context 位置族、group passthrough 族、multicam 族 B8a/B8b
R2 timeline.h/timeline.cpptrack 高度换算、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_nodesclip_get_media_range_rational、块遍历族 B4c
R3 project.h/project.cppfolder 族(create/has_child_recursive/index_of_child/child_input_key/add_child+ oakengine_folder_move_childv3 新增,单条 undo 移动) B5
R4 preview.h/preview.cppcacher 四函数、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 等数百处) B1B11a app 侧
R6 B11b GPU 收尾:renderer.h/cpp 已恢复 B11b 内容(texture/frame 族在),需验证 + 移除 B7 两过渡桥 B11b
R7 B11c staticMetaObject 清理 + B11d visibility 收口与终验 B11c/B11d

2.4 事件 ID 与 facade 覆盖基线

  • 事件 ID 已分配到 143140 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.cppoakengine_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.8TrackListRippleToolCommand 遗留评估 → 豁免清单确认 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_*
  • 改图操作必须 undoablepush_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.txtmake_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 1143、v3/v4 契约。
  5. 禁止降低测试标准;禁止重新 cmake 配置构建目录;禁止改 CI/打包文件。
  6. 禁止在未验证构建状态前继续批次(R6 规则)。

6. 环境备忘

  • 分支:c-abi-migration(已含 3 个抢救/修复提交)。
  • 构建目录 cmake-build-debugNinja + Qt6Debug);asan/coverage 目录不要用。
  • 测试素材 tests/demo.mp4tests/img.pngtests/project_with_footage.ove
  • 本机有 GPUVulkan 用例真实执行;OpenGL offscreen 用例 SKIP 属正常。
  • 全量 ctest 44+ 个约 90140s。
  • 单文件增量验证: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 悬空对象已查无可用内容。