refactor(tool): 接入 invocation 构建状态#115
Conversation
让 Tool 继续作为兼容 facade,同时把 build config 激活、Cargo 构建输入和 runtime artifact 写回迁移到 invocation state 边界。CargoBuildPipeline 不再持有可变 Tool 引用,build orchestration 负责消费明确的 build outcome,并通过临时 legacy_context 胶水层把 InvocationState 镜像到旧 AppContext。
InvocationState 是 active build、变量作用域和 runtime artifacts 的 source of truth;AppContext 仅作为 Tool::ctx/ctx_mut/into_context 的兼容镜像保留。加载或编辑 build config 只记录 legacy build_config,不再在 menuconfig 或纯加载路径 eager 激活 state,真正 build/run 和 runner config 读取路径再同步 active build。
CLI 的 --package/--bin selector 保持在二进制入口私有处理,并在读取 .board.toml 前更新 legacy ctx 作用域,保持 ${package} 按选中 package 展开。内部 CargoSelector、selector helper 和 build activation helper 不作为 public API 暴露,避免 R1 重构辅助面变成长期外部契约。
补充 menuconfig 回归测试,覆盖默认 build config 编辑不会验证暂时缺失的 Cargo package;补充 trybuild public API 负向用例,防止 build activation API 从内部边界泄漏。CLI、配置格式和 runner 入口保持通过 Tool facade 调用。
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Niu Zhihong <zhihong@nzhnb.com>
There was a problem hiding this comment.
审查总结
本次重构将 build config 激活后的运行时状态迁移到 InvocationState,并引入 ActiveBuildContext 作为构建上下文的内部 source of truth。整体架构清晰、层次分明,API 可见性约束合理。
验证结果
- ✅
cargo check -p ostool编译通过 - ✅
cargo test -p ostool全部通过(包括 trybuild UI 回归测试) - ✅
cargo clippy -p ostool无警告 - ✅
cargo fmt --all -- --check格式正确 - ✅
git diff --check无空白字符问题
代码质量评价
架构设计(良好)
InvocationState作为 mutable runtime state 的单一 source of truth,ActiveBuildContext区分 Cargo/Custom 两种构建路径,设计合理。CargoBuildPipeline从&mut Tool解耦为接收显式CargoBuildInput,消除了 pipeline 对 Tool 的可变借用依赖,使构建编排层职责更清晰。legacy_context模块作为临时兼容桥接层,集中管理InvocationState↔AppContext的同步逻辑,文档清晰标注了删除时机。
API 可见性(正确)
InvocationState、ActiveBuildContext、ActiveCargoBuild、ActiveCustomBuild均为pub(crate),不暴露为公共 API。CargoSelector和apply_cargo_selector在build/mod.rs中为 crate-private,CargoSelector::new仅在#[cfg(test)]下可用。CargoBuildPipeline::build从pub收窄为pub(super)。- UI 回归测试(
fail_invocation_state.rs、fail_build_activation_api.rs)正确验证了公共 API 边界。
menuconfig 语义(正确)
record_default_build_config_edit仅记录配置到ctx.build_config,不触发sync_build_context,避免了配置修复流程被 stale/missing Cargo package 阻断。
兼容性(完整)
sync_cargo_context返回类型从()变为anyhow::Result<()>,所有内部调用点(board/mod.rs、run/qemu.rs、run/uboot.rs)均已正确更新为使用?。Tool::ctx_mut()保留但补充了文档说明,明确告知直接修改AppContext不会反向更新InvocationState。
小建议(非阻断)
legacy_context::runtime_artifacts的 fallback 逻辑(state 为空时返回 ctx.artifacts)在当前过渡期是正确的,但建议在后续清理Tool::ctx兼容面时一并移除此 fallback,避免 state 和 ctx 之间出现不一致的边缘情况。Tool::objcopy_output_bin中self.runtime_artifacts().bin()和self.runtime_artifacts().elf()连续调用了两次runtime_artifacts(),虽然功能正确,但可以考虑将结果绑定到局部变量以提高可读性。
这些都不影响正确性,仅作后续优化参考。
Powered by mimo-v2.5-pro
There was a problem hiding this comment.
代码审查:PR #115 — refactor(tool): 接入 invocation 构建状态
总体评价
这是一个高质量的内部重构 PR,将可变运行时状态的源头从分散的 Tool 字段迁移到明确的 InvocationState。变更范围清晰、边界收窄合理、文档完整、测试充分。建议合并。
✅ 优点
-
状态源统一:
InvocationState成为 invocation 级别的 single source of truth,AppContext降级为兼容镜像,避免了双向同步的复杂性。 -
所有权改进:
CargoBuildPipeline不再借用&mut Tool,改为接收显式CargoBuildInput,彻底解耦了 build pipeline 和 tool facade 的生命周期。这提升了后续异步并行编排的可能性。 -
可见性收窄:
InvocationState、ActiveBuildContext、ActiveCargoBuild、ActiveCustomBuild、CargoSelector、apply_cargo_selector均标记为pub(crate),并通过trybuildUI 测试回归保护。CargoBuildPipeline::build()从pub降为pub(super)。API 面干净可控。 -
错误传播修正:
sync_cargo_context返回类型从()改为Result<()>,所有调用点(board/mod.rs、run/qemu.rs、run/uboot.rs)均已同步更新为?传播,修复了之前静默忽略错误的问题。 -
legacy_context 设计务实:兼容层显式标记为临时模块,
runtime_artifacts和runtime_arch优先读取state,仅在state为空时回退到ctx,过渡语义清晰。文档注释中明确给出了删除时机。 -
menuconfig 语义保留:
record_default_build_config_edit只记录配置到ctx,不触发 Cargo package 校验,保持了「编辑时允许 package 暂时不存在」的用户体验。 -
PR 描述质量:Summary / Approach / Changed Modules / Compatibility / Verification / Risks 结构完整,是项目内 PR 描述的典范。
🔍 验证结果
cargo fmt --all -- --check✅ 通过cargo clippy -p ostool --all-features✅ 无警告cargo test -p ostool --lib✅ 157 个单元测试全部通过cargo test -p ostool --test public_api✅ UI 回归测试通过(6 个 trybuild case)cargo test -p ostool --doc✅ 文档测试通过
💡 轻微观察(非阻塞)
-
main.rs与build/mod.rs的apply_cargo_selector重复:main.rs中的 CLI 版本额外处理ctx_mut().build_config更新,而build/mod.rs中的内部版本只修改BuildConfig。两者的职责差异是合理的(CLI 需要同步 legacy context),但未来可以考虑让build/mod.rs版本也通过legacy_context桥接写回,减少main.rs直接操作ctx_mut()的频率。 -
CargoBuildInput的布尔快照:debug和enable_someboot_build_config在构造时从Tool快照。这是有意为之的解耦设计,但如果同一个Tool在一次 invocation 中多次调用 build pipeline,需确保每次构造CargoBuildInput时传入当前值。当前所有调用点都是正确的。
结论
重构方向正确、实现干净、测试充分、兼容性无损。同意合并。
Powered by mimo-v2.5-pro
|
AI,轻而易举啊! |
|
@ZR233 hi,麻烦 review |
同步 fork 侧计划文档到 upstream/main 已合入 drivercraft#115 后的状态。 记录 drivercraft#108/drivercraft#111/drivercraft#114/drivercraft#115 已完成 R1 上游友好切片,并明确 InvocationState、ActiveBuildContext、artifact state 与 build config loader/menu hooks 已进入主路径。 保留完整 R1 终态尚未完成的边界:Tool/ctx 仍是兼容 API,runner/board entrypoints 仍依赖 Tool facade;下一步默认先做 R2 artifact/object-tools 窄切片,或另行切 R1g runner/board seam。 Co-authored-by: OpenAI Codex <codex@openai.com> Signed-off-by: Niu Zhihong <zhihong@nzhnb.com>
Summary
InvocationState,让 active build、变量作用域和 runtime artifacts 有明确的内部 source of truth。InvocationState、ActiveBuildContext、ActiveCargoBuild和ActiveCustomBuild为 crate-private 实现细节,避免把可变运行状态扩成公共 API。legacy_context胶水层,把InvocationState镜像到旧AppContext,集中Tool::ctx*过渡期同步逻辑。CargoBuildPipeline从&mut Tool中解耦,改为接收显式CargoBuildInput,由 orchestration 层消费 build outcome 并写回 runtime artifacts。menuconfig的编辑语义:默认 build config 编辑完成后只记录配置,不提前校验或激活 Cargo package,避免配置修复流程被 stale/missing package 阻断。--package/--binselector 处理留在二进制入口私有逻辑中,内部 selector / activation helper 不作为 public API 暴露。Approach
这次变更继续保留
Tool作为 public compatibility facade,但把可变运行状态的源头迁移到 invocation 边界。build pipeline 只负责构造/执行 Cargo 命令并返回 build facts;build orchestration 负责消费 outcome、准备 runtime artifacts,并写回InvocationState。InvocationState和 active build context 现在只在 crate 内部可见。对外仍保留Invocation/InvocationOptions/Tool这类入口,但不暴露可变状态容器本身,避免形成新的长期 public API 负担。legacy_context是临时兼容层:InvocationState是 source of truth,AppContext只服务现有Tool::ctx、Tool::ctx_mut和Tool::into_context调用。后续删除旧兼容 API 时,应优先删除这个模块。配置加载和配置编辑不再默认 eager 激活 build state。真正需要变量作用域、Cargo package 目录或 runtime artifact 的 build/run/runner config 路径会在消费具体 build config 时同步 active build。CLI selector 则保持在
ostool二进制内私有应用,并在读取.board.toml前更新 legacy context,确保${package}仍按选中 package 展开。Changed Modules
ostool/src/invocation.rs: 增加 invocation runtime state 和 active build context,并将这些状态类型收窄为 crate-private。ostool/src/legacy_context.rs: 增加临时InvocationState<->AppContext兼容桥接层。ostool/src/build/mod.rs: 增加 build context activation 和CargoBuildInput构造路径;将 selector 辅助类型保持为内部实现细节。ostool/src/build/cargo_pipeline.rs: 让 pipeline 接收显式 build input,不再持有可变Tool。ostool/src/tool.rs: 将Tool收缩为状态同步和兼容 facade;加载 build config 时只记录 legacy config,实际消费时再同步 active build。ostool/src/main.rs: CLI selector 改为二进制内私有处理,并补充 board config scope 回归测试。ostool/src/menuconfig.rs: 默认 build config 编辑后只记录配置,不提前验证选中的 Cargo package。ostool/tests/public_api.rs,ostool/tests/ui/fail_invocation_state.rs,ostool/tests/ui/fail_build_activation_api.rs: 增加 public API 边界回归测试。Compatibility
Tool、ToolConfig、ManifestContext和ctx::OutputArtifacts继续保留为兼容 API。InvocationState/ActiveBuildContext/ active build structs 不作为 public API 暴露。CargoSelector、selector 应用函数和 build activation helper 也不作为 public API 暴露。Tool::ctx_mut()仍保留,但新代码应优先使用 state-awareTool方法;直接修改旧AppContext不会反向更新InvocationState。ostool menuconfig仍允许用户打开并修复默认 build config,不会因为配置中的 Cargo package 暂时不存在而在编辑后立即失败。Verification
已运行并通过:
cargo fmt --all -- --checkcargo test -p ostool --test public_api --target x86_64-unknown-linux-gnu -- --nocapturecargo test -p ostool --target x86_64-unknown-linux-gnu -- --nocapturecargo clippy -p ostool --target x86_64-unknown-linux-gnu --all-featurescargo build -p ostool --target x86_64-unknown-linux-gnu --all-featuresgit diff --checkcargo clippy --target x86_64-unknown-linux-gnu --all-featurescargo build --target x86_64-unknown-linux-gnu --all-featurescargo test --target x86_64-unknown-linux-gnu -- --nocaptureRisks / Follow-up
Tool仍是兼容 facade;runner/board entrypoint 的显式输入迁移可以作为后续切片继续做。legacy_context是临时过渡层,应在Tool::ctx/ctx_mut/into_context兼容面退休后删除。