feat/RFC: [system_deps] —— 经 pkg-config 集成宿主系统库
设计基线:.agents/docs/2026-07-24-embedded-platform-support-design.md 的 P1 条目(pkgconf via xlings + sysroot-aware)。错误路径沿用其决策表第 11 行的既有策略:有 .pc 用之,无则退回手写 ldflags,mcpp 不造 .pc。
现状核实基于本地检出(2026-08-24),行号以该检出为准。
1. 问题
宿主系统库目前只能经 [build].ldflags 手工声明。以 macOS/Homebrew Qt6 为例:
[target.macos.build]
ldflags = ["-F/opt/homebrew/opt/qt/lib",
"-framework", "QtWidgets", "-framework", "QtGui", "-framework", "QtCore"]
缺陷:路径硬编码;传递闭包人工维护;无自动化通道——build.mcpp 的 link-lib 经 Transform::LibFlag 强制为 -l<name>,无法表达 -framework(verbatim ldflag 指令系 deliberate 缺席)。而 pkg-config 输出与上述手写内容逐字等价,且 Requires: 自动展开传递依赖。
2. 提案
新增 manifest 段:
[dependencies]
compat.gtest = "1.15.2" # 索引分发、源码构建、hermetic
[system_deps] # 宿主已装、pkg-config 发现、host-coupled
Qt6Widgets = ">=6.5" # 值 = 版本约束;空串 = 仅要求存在
QtCore = ""
prepare 在 target triple 解析后查询一次 pkg-config,将 --cflags / --libs 输出按 token 分类折进现有 typed 通道。关键性质:.pc 模块名跨平台中立(macOS 发 -framework,Linux 发 -l),一份声明全平台正确,无需 cfg() 条件化。
v1 范围:排除 Windows;不造 .pc;不解析 CMake config files。schema 不绑定发现机制,为将来 CPS resolver 留缝。
3. 设计
3.1 注入点
L1 漏斗:root 于 merge_conditional_config 之后、makePackageRoot 快照之前;依赖包在各自加载路径的镜像点。由此:
- triple 已解析,可设 sysroot-aware env;
- 结果随 buildConfig 快照自动参与 P1689 扫描、fingerprint(cache_key 已哈希 cflags/ldflags/include_dirs)、compile_commands.json,零额外接线;
- 符合「每包恰好合并一次」不变量。
查询经 capture_exec_deadline 执行;ninja 规则静态,故必须在 prepare 期完成。system_deps 为空时直接返回,其余项目零开销。
3.2 Token 分类
| token |
去向 |
状态 |
-I<dir> / -idirafter <dir> |
includeDirs / includeDirsAfter |
现成 |
-D<m> |
defines |
现成 |
-l<n> / -L<dir> |
libraries / linkLibraryDirs |
现成 |
-framework <n> |
LinkIntent.frameworks(MachO 渲染已有) |
现成 |
-F<dir> |
新字段 LinkIntent.frameworkDirs |
需补 |
-Wl,… 等 |
ldflags verbatim |
现成 |
-isystem <dir> |
待定(重映射或拒绝),见 §6.3 |
— |
分类器为表驱动纯函数。有损分类须报 diag::degraded()(impact 必填)。
3.3 其余设计点
- Fingerprint:哈希查询结果而非环境变量——env 漂移但输出未变时不触发重建。
- Hermeticity:建议 v1 要求激活 hermetic 检查时显式
allow_host_libs = true(见 §6.2)。
- Offline:查询属本地内省,
--offline 下照常执行;lock 不记录结果(机器本地事实)。
- Static:resolved linkage 为 static 时追加
--static。
- 交叉编译:
tc.sysroot 非空时设 PKG_CONFIG_SYSROOT_DIR / PKG_CONFIG_LIBDIR,薄接线;完整 multiarch 解析归嵌入式 P0 后续。
- 已知限制:含空格的安装路径不可表示(生态固有问题),文档注明。
- 版本约束:v1 仅
>=N / =N / 空,映射 --atleast-version / --exact-version / --exists。
4. 错误路径
| 场景 |
处置 |
二进制不存在 / .pc 缺失 / 版本不满足 / 超时 |
硬错误 + 新 E 码;hint 给出「手写 ldflags」兜底示例(上文设计文档决策表第 11 行策略) |
| 有损分类 |
diag::degraded() |
配套:self doctor 增加 pkg-config 可用性与可解析性检查;mcpp why deps 标注旗标来源。
5. 测试与实施
测试以 fixture .pc 树 + PKG_CONFIG_PATH 实现,CI 完全离线,无需真实 Qt。覆盖:framework 渲染、Requires 闭包、define 到达编译行、三类失败文案快照、修改 fixture 触发重建、static 追加 --static、无 [system_deps] 项目构建图字节级不变。
| PR |
内容 |
| 1 |
schema/解析、resolver、注入、分类器、fingerprint、e2e |
| 2 |
frameworkDirs 通道 + ConditionalConfig 补 frameworks 字段 |
| 3 |
E 码 + doctor/why + 双语文档 |
后续独立 RFC:sysroot env 完整接线、CPS resolver、feature 门控、build.mcpp 查询 API。
6. 开放问题
- Schema 落点:
[system_deps](推荐,与 [dependencies] 形成语义对仗)vs [build].system_packages?
- Hermeticity:要求
allow_host_libs = true,还是声明即授权?
-isystem:降级重映射 + degraded,还是硬拒绝?
ConditionalConfig.frameworks 补洞随 PR2 还是先行独立合入?
- 新错误码编号确认。
7. 参考
方向认可即可按 §5 切分提交 PR1。
feat/RFC:
[system_deps]—— 经 pkg-config 集成宿主系统库1. 问题
宿主系统库目前只能经
[build].ldflags手工声明。以 macOS/Homebrew Qt6 为例:缺陷:路径硬编码;传递闭包人工维护;无自动化通道——build.mcpp 的
link-lib经Transform::LibFlag强制为-l<name>,无法表达-framework(verbatim ldflag 指令系 deliberate 缺席)。而 pkg-config 输出与上述手写内容逐字等价,且Requires:自动展开传递依赖。2. 提案
新增 manifest 段:
prepare 在 target triple 解析后查询一次 pkg-config,将
--cflags/--libs输出按 token 分类折进现有 typed 通道。关键性质:.pc模块名跨平台中立(macOS 发-framework,Linux 发-l),一份声明全平台正确,无需cfg()条件化。v1 范围:排除 Windows;不造
.pc;不解析 CMake config files。schema 不绑定发现机制,为将来 CPS resolver 留缝。3. 设计
3.1 注入点
L1 漏斗:root 于
merge_conditional_config之后、makePackageRoot快照之前;依赖包在各自加载路径的镜像点。由此:查询经
capture_exec_deadline执行;ninja 规则静态,故必须在 prepare 期完成。system_deps为空时直接返回,其余项目零开销。3.2 Token 分类
-I<dir>/-idirafter <dir>includeDirs/includeDirsAfter-D<m>defines-l<n>/-L<dir>libraries/linkLibraryDirs-framework <n>LinkIntent.frameworks(MachO 渲染已有)-F<dir>LinkIntent.frameworkDirs-Wl,…等ldflagsverbatim-isystem <dir>分类器为表驱动纯函数。有损分类须报
diag::degraded()(impact 必填)。3.3 其余设计点
allow_host_libs = true(见 §6.2)。--offline下照常执行;lock 不记录结果(机器本地事实)。--static。tc.sysroot非空时设PKG_CONFIG_SYSROOT_DIR/PKG_CONFIG_LIBDIR,薄接线;完整 multiarch 解析归嵌入式 P0 后续。>=N/=N/ 空,映射--atleast-version/--exact-version/--exists。4. 错误路径
.pc缺失 / 版本不满足 / 超时diag::degraded()配套:
self doctor增加 pkg-config 可用性与可解析性检查;mcpp why deps标注旗标来源。5. 测试与实施
测试以 fixture
.pc树 +PKG_CONFIG_PATH实现,CI 完全离线,无需真实 Qt。覆盖:framework 渲染、Requires闭包、define 到达编译行、三类失败文案快照、修改 fixture 触发重建、static 追加--static、无[system_deps]项目构建图字节级不变。frameworkDirs通道 +ConditionalConfig补 frameworks 字段后续独立 RFC:sysroot env 完整接线、CPS resolver、feature 门控、build.mcpp 查询 API。
6. 开放问题
[system_deps](推荐,与[dependencies]形成语义对仗)vs[build].system_packages?allow_host_libs = true,还是声明即授权?-isystem:降级重映射 + degraded,还是硬拒绝?ConditionalConfig.frameworks补洞随 PR2 还是先行独立合入?7. 参考
.agents/docs/2026-07-24-embedded-platform-support-design.md(P1 条目;决策表第 11 行 fallback 策略);open-items 分析(pkg-config 平台边界)dependency(method:'pkg-config');Cargo pkg-config crate方向认可即可按 §5 切分提交 PR1。