并行构建 Visual Studio 解决方案会丢失一些用于静态库的 PDB [英] Building Visual Studio solution in parallel loses some PDBs for static libraries

查看:22
本文介绍了并行构建 Visual Studio 解决方案会丢失一些用于静态库的 PDB的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a Visual Studio solution with 12 C++ projects. Half of the projects build static libraries, and the other half build native desktop executables.

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

When I rebuild the entire solution from Visual Studio 2019's menu (Build > Rebuild Solution), it appears to work--I get functional, debuggable executables. However, some of the PDBs for some of the static libraries are missing. When I dig into the build log, I see a lot of linker warnings like this:

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

wingui.lib(text.obj) : warning LNK4099: PDB 'wingui.pdb' was not found with 'wingui.lib(text.obj)' or at 'D:\code\aid\apps\vcell\x64\Debug\wingui.pdb'; linking object as if no debug info

确实,wingui.pdb通常丢失,但偶尔它会在它应该在的地方生成.如果我关闭构建中的并行性,它总是存在的.竞争条件?

Indeed, wingui.pdb is usually missing, but occasionally it's generated right where it should be. And if I turn off the parallelism in the build, it's always there. Race condition?

于 2021 年 7 月 24 日更新

使用 Sysinternals 工具集中的 procmon,我在干净重建期间将所有操作记录到 wingui.pdb.总结如下:

Using procmon from the Sysinternals toolset, I logged all the operations to wingui.pdb during a clean rebuild. Here's a summary:

  1. MSBuild 查找 wingui.pdb 并发现它不存在.
  2. CL 创建它,写入它,读回一些,再写入一些,然后关闭它.
  3. MSBuild 打开 wingui.pdb设置 FILE_DISPOSITION_DELETE,然后关闭文件.嗯?
  4. mspdbsrv 多次尝试打开 wingui.pdb.当然,每次尝试都失败了,因为 MSBuild 删除了它.
  1. MSBuild looks for wingui.pdb and learns it doesn't exist.
  2. CL creates it, writes it, reads some of it back, writes some more, and then closes it.
  3. MSBuild opens wingui.pdb, sets FILE_DISPOSITION_DELETE, and then closes the file. Huh?
  4. mspdbsrv tries to open wingui.pdb several times. Each attempt fails, of course, because MSBuild deleted it.

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

Can anyone explain step 3? Why would MSBuild mark a freshly made PDB file for deletion?

推荐答案

我认为这归结为 Rebuild 和 Clean + Build 的区别,也提到了 此处.

I think this boils down to the Difference between Rebuild and Clean + Build, which is also mentioned here.

编辑于 2021-07-25

逐个项目重建工作.它首先进行清洁"项目的步骤,然后是构建.清理项目意味着从项目的中间目录 $(IntDir) 中删除构建工件.虽然每个项目都有自己的中间目录,但最终目标(如 PDB 文件)被写入同一个输出目录——主项目的输出目录.

Rebuild works project-by-project. It first does the "clean" step for the project and then a build. Cleaning a project means deleting the build artifacts from the project's intermediate directory $(IntDir). While each project has its own intermediate directory, final targets (like the PDB files) are written to the same output directory--the output directory of the main project.

在我的解决方案中,每个静态库 X 至少被其他两个项目引用:X_test 和应用程序 A.由于这些依赖关系,项目 X 将排在项目 X_test 和 A 之前.首先,项目 X 被清理从以前的构建中清除工件,然后在其中间目录中生成新的目标文件.Project X 的构建通过在公共输出目录中生成其输出(LIB 和 PDB 文件)来完成.

In my solutions, each static library X is referenced by at least two other projects: X_test and the application A. Because of these dependencies, project X will be scheduled before both projects X_test and A. First, project X is cleaned by purging artifacts from previous builds, and then it produces fresh object files in its intermediate directory. Project X's build finishes by producing its outputs--the LIB and PDB files--in the common output directory.

假设下一个计划是 X_test 项目.它首先清除它的中间目录,重建它的对象,然后从公共输出目录链接 X 的 LIB 和 PDB 文件.到目前为止,一切都很好.

Let's say project X_test is scheduled next. It begins by purging its intermediate directory, rebuilding its objects, and then linking against X's LIB and PDB files from the common output directory. So far, so good.

最后,项目 A 以清除其构建工件开始.这并不意味着它会删除其中间目录中的每个文件.相反,有一组模式,包括项目的特定输出(例如,A.exe)和其他一些通配符,包括 *.pdb.这些通配符模式应用于中间目录(至少).

Finally project A begins by purging its build artifacts. This does not mean it deletes every file in its intermediate directory. Instead, there are a set of patterns, including a project's specific output (e.g., A.exe) and some wildcards for others, including *.pdb. These wild card patterns are applied to the intermediate directory (at least).

这里的关键是:我的解决方案设置为 A 的中间目录也是公共输出目录.因此,当项目 A 开始时,它会删除 A.exe*.pdb(等等).这将静态库 X.lib 留在了预期的位置,但它的伴侣 X.pdb 不见了.

And here's the kicker: my solutions are set up so that A's intermediate directory is also the common output directory. So as project A begins, it deletes A.exe and *.pdb (among others). That leaves the static library X.lib where it's expected, but its companion X.pdb is gone.

如果 Rebuild 是并行完成的,A 和 X_test 项目会竞争,所以 A 的清除也可能导致 X_test 的链接器警告.

And if the Rebuild is done in parallel, the A and X_test projects can race, so A's purge might cause linker warnings for X_test as well.

这篇关于并行构建 Visual Studio 解决方案会丢失一些用于静态库的 PDB的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆