并行构建 Visual Studio 解决方案会丢失一些静态库的 PDB
Posted
技术标签:
【中文标题】并行构建 Visual Studio 解决方案会丢失一些静态库的 PDB【英文标题】:Building Visual Studio solution in parallel loses some PDBs for static libraries 【发布时间】:2021-07-24 05:36:58 【问题描述】:我有一个包含 12 个 C++ 项目的 Visual Studio 解决方案。一半的项目构建静态库,另一半构建原生桌面可执行文件。
当我从 Visual Studio 2019 的菜单(构建 > 重建解决方案)重建整个解决方案时,它似乎可以工作——我得到了功能性、可调试的可执行文件。但是,缺少某些静态库的某些 PDB。当我深入研究构建日志时,我看到很多这样的链接器警告:
wingui.lib(text.obj):警告 LNK4099:在 'wingui.lib(text.obj)' 或 'D:\code\aid\apps\vcell\x64 中找不到 PDB 'wingui.pdb' \调试\wingui.pdb';链接对象好像没有调试信息
确实,wingui.pdb
通常会丢失,但偶尔它会在应有的位置生成。如果我关闭构建中的并行性,它总是存在的。比赛条件?
2021 年 7 月 24 日更新
使用 Sysinternals 工具集中的 procmon,我在干净重建期间将所有操作记录到 wingui.pdb
。总结如下:
-
MSBuild 查找
wingui.pdb
并发现它不存在。
CL 创建它,写入它,读回其中的一部分,再写入一些,然后关闭它。
MSBuild 打开wingui.pdb
,设置FILE_DISPOSITION_DELETE
,然后关闭文件。 嗯?
mspdbsrv 多次尝试打开wingui.pdb
。当然,每次尝试都失败了,因为 MSBuild 删除了它。
谁能解释第 3 步?为什么 MSBuild 会将新制作的 PDB 文件标记为删除?
【问题讨论】:
【参考方案1】:我认为这归结为Difference between Rebuild and Clean + Build,也提到了here。
于 2021 年 7 月 25 日编辑
重建工程逐个项目。它首先为项目执行“清理”步骤,然后进行构建。清理项目意味着从项目的中间目录 $(IntDir) 中删除构建工件。虽然每个项目都有自己的中间目录,但最终目标(如 PDB 文件)被写入相同的输出目录——主项目的输出目录。
在我的解决方案中,每个静态库 X 至少被两个其他项目引用:X_test 和应用程序 A。由于这些依赖关系,项目 X 将在项目 X_test 和 A 之前调度。首先,项目 X 由从以前的构建中清除工件,然后在其中间目录中生成新的对象文件。项目 X 的构建通过在公共输出目录中生成其输出(LIB 和 PDB 文件)来完成。
假设项目 X_test 是下一个计划。它首先清除其中间目录,重建其对象,然后从公共输出目录链接 X 的 LIB 和 PDB 文件。到目前为止,一切顺利。
最后,项目 A 从清除其构建工件开始。这并不意味着它会删除其中间目录中的每个文件。相反,有一组模式,包括项目的特定输出(例如,A.exe
)和其他一些通配符,包括*.pdb
。这些通配符模式(至少)应用于中间目录。
这里是关键:我的解决方案设置为使 A 的中间目录也是公共输出目录。因此,当项目 A 开始时,它会删除 A.exe
和 *.pdb
(以及其他)。这将静态库 X.lib
留在了预期的位置,但它的同伴 X.pdb
不见了。
如果重建是并行完成的,A 和 X_test 项目可以竞争,所以 A 的清除也可能导致 X_test 的链接器警告。
【讨论】:
以上是关于并行构建 Visual Studio 解决方案会丢失一些静态库的 PDB的主要内容,如果未能解决你的问题,请参考以下文章
Visual Studio中Rebuild和Clean + Build之间的区别
如何使用 BatchBuild 并行构建多个 C++ Visual Studio v2015+ 配置
如何在 Visual Studio 2010 中并行化数据驱动的单元测试?