feat/RFC: mcpp 项目级构建 Hook 机制
v1 只提供项目级构建 Hook:mcpp 从项目的 mcpp.toml 读取生命周期命令,并在对应构建事件发生时执行一个外部进程。
1. 问题
mcpp 项目目前无法在构建开始、失败或完成时执行项目自定义命令。
构建音效、桌面通知、结果上报等场景需要一个简单的生命周期入口,同时允许这些工具通过 xlings 生态安装和分发。
2. 提案
在项目 mcpp.toml 中增加 [hooks]:
[hooks]
build_start = "echo 1"
build_failed = "echo 2"
build_finished = "echo 3"
timeout_seconds = 10
enabled = true
side_effect = true
v1 的核心约定:
- Hook 只从当前项目的 mcpp.toml 读取;
- 每个事件最多配置一条外部命令;
- Hook 与构建同步执行;
- 未配置 [hooks] 时,现有构建行为不变;
- Hook 使用统一的超时和错误策略;
- Hook 所需程序及资源可以作为普通 xpkg 由 xlings 安装。
3. 配置
| 字段 |
类型 |
默认值 |
含义 |
| build_start |
string |
— |
构建开始时执行的命令 |
| build_failed |
string |
— |
构建失败时执行的命令 |
| build_finished |
string |
— |
构建成功完成时执行的命令 |
| timeout_seconds |
integer |
10 |
单条 Hook 命令的最大执行时间 |
| enabled |
boolean |
true |
是否启用当前项目的 Hook |
| side_effect |
boolean |
true |
Hook 失败是否使本次构建失败 |
事件命令是宿主平台上的一条命令行,在当前项目根目录执行。未配置的事件直接跳过。
timeout_seconds 应为正整数。Hook 超时后终止对应进程,并按 side_effect 处理。
4. 事件语义
v1 定义三个事件:
| 事件 |
触发时机 |
| build_start |
项目配置完成、正式构建开始前 |
| build_failed |
本次构建以失败状态结束 |
| build_finished |
本次构建成功完成 |
一次构建的生命周期为:
build_start
↓
执行构建
├─ 成功 → build_finished
└─ 失败 → build_failed
build_failed 与 build_finished 是互斥的终止事件,每次构建只触发其中一个。Hook 命令自身的结果不会再次触发另一个 Hook,避免递归调用。
5. 执行与错误行为
- enabled = false 时不执行任何 Hook;
- Hook 命令返回 0 表示成功;
- Hook 命令无法启动、返回非零或超时均视为 Hook 失败;
- side_effect = true 时,Hook 失败使 mcpp 最终返回失败;
- side_effect = false 时,Hook 失败只报告 warning,保持原构建结果;
- Hook stdout/stderr 直接沿用普通外部命令的终端行为;
- 每个事件只启动一个外部进程,不引入 Hook 并发和顺序配置。
6. 实现形态
新增单个 hooks.cppm 模块,集中负责:
- [hooks] 配置加载与初始化;
- Hook 事件定义;
- 统一事件调用接口;
- 外部命令执行;
- 超时和 side_effect 处理。
构建流程只在对应生命周期位置调用统一接口:
hooks::invoke(build_start)
hooks::invoke(build_failed)
hooks::invoke(build_finished)
实现复用 mcpp 现有 manifest 和跨平台进程执行能力,不增加独立运行时。
7. 构建音效示例
构建音效由普通 xpkg 提供:
[hooks]
build_finished = "mcpp-hooks-audioplayer niulai-mm"
build_failed = "mcpp-hooks-audioplayer niulai-niulai"
side_effect = false
[xlings]
deps = ["xim:mcpp-hooks-audioplayer@0.0.1"]
mcpp-hooks-audioplayer 可以是一个普通 mcpp 项目,将音频资源内置到自身二进制中,并通过 xlings 生态安装。mcpp 只负责在构建事件发生时执行该程序。
8. 测试与验收
测试覆盖:
- 未配置 [hooks] 时构建行为不变;
- build_start 在构建前执行一次;
- 成功构建只执行 build_finished;
- 失败构建只执行 build_failed;
- 未配置的事件不执行命令;
- enabled = false 不执行命令;
- Hook 超时后进程被终止;
- side_effect = true 时 Hook 失败使构建失败;
- side_effect = false 时 Hook 失败不改变构建结果;
- Windows、Linux、macOS 使用同一份配置结构。
9. 实施范围
Hook v1 由一个 PR 完成:配置模型、hooks.cppm、三个事件调用点、超时与错误处理、E2E 和文档。
构建音效程序作为独立 xpkg 实现,不阻塞 Hook v1。
feat/RFC: mcpp 项目级构建 Hook 机制
1. 问题
mcpp 项目目前无法在构建开始、失败或完成时执行项目自定义命令。
构建音效、桌面通知、结果上报等场景需要一个简单的生命周期入口,同时允许这些工具通过 xlings 生态安装和分发。
2. 提案
在项目 mcpp.toml 中增加 [hooks]:
v1 的核心约定:
3. 配置
事件命令是宿主平台上的一条命令行,在当前项目根目录执行。未配置的事件直接跳过。
timeout_seconds 应为正整数。Hook 超时后终止对应进程,并按 side_effect 处理。
4. 事件语义
v1 定义三个事件:
一次构建的生命周期为:
build_start ↓ 执行构建 ├─ 成功 → build_finished └─ 失败 → build_failedbuild_failed 与 build_finished 是互斥的终止事件,每次构建只触发其中一个。Hook 命令自身的结果不会再次触发另一个 Hook,避免递归调用。
5. 执行与错误行为
6. 实现形态
新增单个 hooks.cppm 模块,集中负责:
构建流程只在对应生命周期位置调用统一接口:
实现复用 mcpp 现有 manifest 和跨平台进程执行能力,不增加独立运行时。
7. 构建音效示例
构建音效由普通 xpkg 提供:
mcpp-hooks-audioplayer 可以是一个普通 mcpp 项目,将音频资源内置到自身二进制中,并通过 xlings 生态安装。mcpp 只负责在构建事件发生时执行该程序。
8. 测试与验收
测试覆盖:
9. 实施范围
Hook v1 由一个 PR 完成:配置模型、hooks.cppm、三个事件调用点、超时与错误处理、E2E 和文档。
构建音效程序作为独立 xpkg 实现,不阻塞 Hook v1。