c++ - 并行构建 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
在干净重建期间记录了所有操作。这是一个摘要:
- MSBuild 查找
wingui.pdb
并发现它不存在。 - CL 创建它,写入它,读回一些,再写入一些,然后关闭它。
- MSBuild 打开
wingui.pdb
、设置FILE_DISPOSITION_DELETE
,然后关闭文件。 嗯? - mspdbsrv 尝试打开
wingui.pdb
几次。当然,每次尝试都会失败,因为 MSBuild 删除了它。
谁能解释第3步?为什么 MSBuild 会将新制作的 PDB 文件标记为删除?
解决方案
我认为这归结为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 的链接器警告。
推荐阅读
- windows - Powershell - 如何将当前会话的所有文本输出作为字符串获取?
- javascript - 如何修复nodemon“块范围声明......”错误?
- curl - 使用 curl 将多个文件上传到 slack
- arrays - 如何在Powershell中合并字符串的多维数组
- javascript - 按会话显示数据
- c# - SerialPort SerialStream 在读取循环中泄漏内存
- maven - Maven shade插件没有创建“src/main/resources”目录,而是将文件直接放在根目录下
- sql - SQL - 列不会求和
- javascript - 使用 ReactJS 存储和编辑数据
- python - cv::copyMakeBorder 中的 cv2.error,当我运行 python train.py --data data/hat.data --cfg cfg/yolov3-tiny.cfg 使用 yolo v3