Skip to content

Bug: 依赖 BMI 缓存命中时,被恢复的包 BMI 的传递 import std 没有进入消费方的构建图 #405

Description

@speak-agent

本 issue 的根因已被重写。 初版归因为「同一 home 用过两个 mcpp 版本 ⇒ 缓存 key 少一轴」,
那个结论被我自己的后续测量否掉了:两个版本选中的 std identity 是同一个
50c5b8df12f1bf98),而且单一版本、单一 home 就能复现。下面是纠正后的内容。

Bug: 依赖 BMI 缓存命中时,被恢复的包 BMI 的传递 import std 没有进入消费方的构建图

最小复现(一个 mcpp 版本,干净缓存)

rm -rf ~/.mcpp/build-cache/v1/pkg/mcpplibs/imgui@0.0.6/

mcpp new a --template imgui:window && (cd a && mcpp build)   # OK    ← 缓存 miss
mcpp new b --template imgui:window && (cd b && mcpp build)   # FAIL  ← 缓存 hit
error: build failed
std: error: failed to read compiled module: No such file or directory
std: note: compiled module file is 'gcm.cache/std.gcm'
std: note: imports must be built before being imported
imgui.app: error: failed to read compiled module: Bad import dependency

根因

imgui 包的模块 import std。消费方 main.cpp 只有:

import imgui.core;
import imgui.app;

它自己不 import std

  • 缓存 miss 时,包在本地被编译,这个动作本身就把 std BMI 边带进了构建图 ⇒
    gcm.cache/std.gcm 存在 ⇒ 一切正常。
  • 缓存 hit 时,包的 BMI 被直接恢复进消费方的 gcm.cache但没有任何东西把
    std BMI 边加进消费方的构建图
    std.gcm 根本不存在 ⇒ 被恢复的
    imgui.app.gcm 读不到它要的 std

两条都成立,互为佐证:

变量 结果
mcpp build --cache off OK(绕开缓存,包本地编译)
消费方 main.cpp 加一行 import std; OK(std 边因此进图)
原样 + 缓存命中 FAIL

所以缺的不是 key 的某一轴,而是:恢复一个包的 BMI 时,必须把它传递依赖的
std(以及任何它 import 而消费方图里没有的模块)一并纳入消费方的构建图。

为什么它看起来像「升级把我弄坏了」

第一个构建它的人(缓存 miss)永远是好的,之后每个人(缓存 hit)都坏。
所以现象是「以前能跑,现在不行」,而实际上和版本无关 —— 我最初正是被这个顺序
误导,把它归因成跨版本投毒;用同一个版本跑两个项目就能证伪。

影响

任何 import std 的索引包,只要消费方自己不 import std,第二次起就构建失败,
而错误信息(No such file or directory / Bad import dependency)完全不指向缓存。
imgui 模板是现成的例子 —— 它生成的 main.cpp 就不 import std

绕过

  • mcpp build --cache off
  • 或消费方源码里显式 import std;
  • 或删 ~/.mcpp/build-cache/v1/pkg/<ns>/<pkg>@<ver>/(只回到 miss,下一个项目还会再犯)

环境

mcpp 2026.8.10.12026.8.8.2 / 2026.8.8.4 同样复现,早于最近这批改动)、
gcc 16.1.0、x86_64-linux-gnu。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions