首页 > 解决方案 > 并行构建 Visual Studio 解决方案会丢失一些静态库的 PDB

问题描述

我有一个包含 12 个 C++ 项目的 Visual Studio 解决方案。一半的项目构建静态库,另一半构建本地桌面可执行文件。

当我从 Visual Studio 2019 的菜单(构建 > 重建解决方案)重建整个解决方案时,它似乎可以工作——我得到了功能性、可调试的可执行文件。但是,缺少某些静态库的某些 PDB。当我深入研究构建日志时,我看到很多这样的链接器警告:

wingui.lib(text.obj):警告 LNK4099:在 'wingui.lib(text.obj)' 或 'D:\code\aid\apps\vcell\x64\Debug\ 中找不到 PDB 'wingui.pdb' wingui.pdb'; 链接对象好像没有调试信息

确实,wingui.pdb通常丢失,但偶尔会在应有的位置生成。如果我关闭构建中的并行性,它总是存在的。比赛条件?

2021-07-24 更新

使用 Sysinternals 工具集中的 procmon,我wingui.pdb在干净重建期间记录了所有操作。这是一个摘要:

  1. MSBuild 查找wingui.pdb并发现它不存在。
  2. CL 创建它,写入它,读回一些,再写入一些,然后关闭它。
  3. MSBuild 打开wingui.pdb设置FILE_DISPOSITION_DELETE,然后关闭文件。 嗯?
  4. mspdbsrv 尝试打开wingui.pdb几次。当然,每次尝试都会失败,因为 MSBuild 删除了它。

谁能解释第3步?为什么 MSBuild 会将新制作的 PDB 文件标记为删除?

标签: c++visual-studiomsbuild

解决方案


我认为这归结为Rebuild 和 Clean + Build 之间的差异,这里也提到了这一点。

2021-07-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 的链接器警告。


推荐阅读