并行构建 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之间的区别

Visual Studio - 并行化构建不会提高性能

如何使用 BatchBuild 并行构建多个 C++ Visual Studio v2015+ 配置

如何在 Visual Studio 2010 中并行化数据驱动的单元测试?

Visual Studio Cordova iOS 构建服务器设置

Visual Studio 2013 解决方案构建不按构建顺序