我最近在尝试使用 Unreal Build Tool 的 Artifact Cache 功能来加速本地编译,配置如下所示:
xml 复制编辑 <BuildConfiguration> ... <bArtifactRead>true</bArtifactRead><bArtifactWrite>true</bArtifactWrite><bLogArtifactCacheMisses>true</bLogArtifactCacheMisses><ArtifactDirectory>Saved/Artifacts</ArtifactDirectory> </BuildConfiguration>
一开始编译缓存运行得很理想,所有模块都成功命中缓存。
但当我修改了某个项目中的 .cpp文件内容之后,我发现编译依然命中所有缓存,没有任何模块被重新编译。在进一步排查后,我怀疑问题出在 Unity Build(联合编译)机制 上。简单来说:
如果一个 .cpp文件被包含进 Unity Build 文件(自动生成的那类
,用于包含多个源码文件),而该 Unity 文件本身没有变化(比如文件内容或包含列表没变),那么它的 Hash 值不会更新,导致 Artifact Cache 依然命中原始缓存,即使源文件内容已经改变。这就可能导致:
- 修改代码却未触发重新编译,行为异常;
- 缓存命中的是旧版本.obj文件,构建结果不准确;
- 缓存 Key 失效机制依赖 Unity 文件本身的变化,而不是源.cpp的直接变化。
我的疑问是:
- 这是否是 Artifact Cache 当前在 Unity Build 下的已知限制?
- 是否有推荐的解决方案?例如在开发调试阶段为部分模块禁用 Unity Build(如设置 bUseUnityBuild)?
- 是否可以更细粒度地控制缓存失效机制,以便更准确反映代码变化?
如果有相关经验或建议,欢迎分享。谢谢!
重现步骤
我在使用 Unreal Build Tool 的 Artifact 缓存功能来加速项目编译,配置如下:
xml 复制编辑 <BuildConfiguration> ... <bArtifactRead>true</bArtifactRead><bArtifactWrite>true</bArtifactWrite><bLogArtifactCacheMisses>true</bLogArtifactCacheMisses><ArtifactDirectory>Saved/Artifacts</ArtifactDirectory> </BuildConfiguration>
编译 LyraStarterGame 项目后,所有模块成功生成并写入缓存;紧接着再次编译,所有编译项也都正确命中缓存,表现正常。[Image Removed]接下来,我测试缓存失效机制:
- 找到类似Module.LyraGame.2.cpp 的文件(这是 UE 默认启用联合编译生成的 Unity 文件)。
- 修改该 Unity 文件中 include的某个源cpp文件,确保更改内容足够复杂,理论上应触发重新编译。
- 重新执行编译,结果发现:缓存仍然全部命中,没有触发重新编译。
这与预期不符。按理说,Module.LyraGame.2.cpp的缓存应该因为其包含的 .cpp
文件发生了变化而失效。
初步分析
我怀疑问题出在 Unity Build 机制 上:
UBT 在计算 Unity 文件(如 Module.LyraGame.2.cpp)的缓存 Key 时,仅考虑了该文件本身的哈希,而未递归检查它所包含的原始.cpp文件内容是否发生了变化。补充测试
关闭联合编译
添加 bUseUnity = false
后再做相同修改,缓存失效行为恢复正常,修改能正确触发编译。但首次编译时间显著增加,编译粒度变小,整体构建速度变慢。
我的疑问:
- 当前版本的 Artifact Cache 是否确实不支持 Unity Build 场景下的缓存精细变更检测?
- 是否存在可以兼顾编译速度与缓存准确性的方案?例如部分模块关闭 Unity Build,或引入增量缓存 Key 的机制?
- 有没有推荐的构建配置或实践来避免这一问题?
tuo.chen
(tuo.chen)
3
您好,unitybuild在收集源码的时候,会将修改过的文件移除出 unitybuild,加入adaptive列表,
编译的时候会出现 [Adaptive Build] Excluded from XXXModule unity file: XXX.cpp 的字样
如果您那边修改后并没有移出unitybuild,是否没有用Perforce或者git的代码管理工具?
tuo.chen
(tuo.chen)
5
那应该就是这个问题了,如果有用git或Perforce管理就不会有这个问题