使用 MSVC 编译时,msdpb* 文件的正确用法是什么?

What is the proper usage of msdpb* files when compiling with MSVC

本文关键字:用法 是什么 文件 编译 MSVC msdpb 使用      更新时间:2023-10-16

互联网上有很多关于"缺少mspdb140.dll"的问题,以及其他关于缺少"mspdb*"DLL的类似问题。有几种不同的解决方案,包括:

  • 重新安装视觉工作室
  • 删除 mspdb140.dll,它应该包含在 PATH 变量中
  • 将 mspdb140.dll(和其他文件(添加到<msvc-install-dir><subpath>

就我而言,我在 docker 容器中使用了 msvc 2019 安装程序的构建工具,然后为 msvc 2017 和 2019 安装了两个构建工具。如果我然后去C:BuildToolsVCToolsMSVC14.16.27023binHostX64,有两个文件夹:x64x86。如果我ls -Recurse -Filter "*mspdb*"编写 powershell 命令,我会得到以下输出:

Directory: C:BuildToolsVCToolsMSVC14.16.27023binHostX64x64
mspdb140.dll
mspdbcmf.exe
mspdbcore.dll
mspdbsrv.exe
mspdbst.dll
Directory: C:BuildToolsVCToolsMSVC14.16.27023binHostX64x641033
mspdbcmfui.dll

不过,HostX64x86目录中没有这些文件。如果我以 x64 为目标构建,一切正常,但以 x86 为目标,发布和调试构建都会出错。发布版本具有:

ERROR: C:BuildToolsVCToolsMSVC14.16.27023binHostX64x86cl.exe
...
c1xx: fatal error C1356: unable to find mspdbcore.dll

调试版本具有:

ERROR: C:BuildToolsVCToolsMSVC14.16.27023binHostX64x86cl.exe
...
c1xx: fatal error C1356: unable to find mspdb140.dll

这些构建使用 Qt 和 Qbs,Qbs 使用 vcvarsall.bat 来查找所需的环境变量。当安装了多个 msvc 工具链时,Qbs 中存在一个错误,这使得 Qbs 总是选择最新的一个。为了解决这个问题,我手动移动 vcvarsall.bat并在每个构建作业中将其替换为以下内容:

call %~dp0vcvarsall_real.bat %1 store 10.0.17134.0 -vcvars_ver=14.16.27023 || exit /b 1

这迫使 vcvarsall 选择我想要的工具链 14.16.27023。

我设法通过简单地复制 x64 目标存在的 DLL 和 EXE 文件来修复这两个编译错误,除了mspdbcmfui.dll.没有理由不复制最后一个 DLL,因为我只是在试验。即使程序编译,我真的不知道我在做什么,这些文件在哪里使用,或者为什么某些目标缺少它们!不必在我的构建环境中手动复制文件会感觉更好。

我还检查了Visual Studio 2017 Professional的本地安装,然后我与HostX64\x64的文件名称相同,但是对于HostX64\x86,我得到以下输出:

C:Program Files (x86)Microsoft Visual Studio2017WDProfesionalVCToolsMSVC14.16.27023binHostx64x86
...
mspdb140.dll
mspdbcore.dll

只有两个 DLL!

在 docker 映像中,我还有 MSVC 2019 的生成工具,并且所有主机和目标组合都具有所有 DLL 和 EXE。

总结一下:

  • 为什么在某些情况下缺少 DLL
  • 解决此问题的正确方法是什么?
  • Visual Studio 编译与使用 vcvarsall.bat 和外部工具有何不同,因为它显然能够在不复制 DLL/EXE 的情况下进行编译!

我仍然希望有人能解释更多关于这些文件存在的原因,如何正确使用它们,为什么它们在某些地方丢失,以及Visual Studio似乎如何能够编译即使缺少文件。与此同时,我发现:

我已经安装了 MSVC 2019 的构建工具,所以我转到文件夹C:BuildToolsVCToolsMSVC14.22.27905binHostx64并运行以下 powershell 命令:

(ls -Recurse "mspdb*").FullName | % { Get-FileHash $_ } | Sort-Object -Property Hash

并得到这个输出:

Hash                                                                   Path
--------------------------------------------------------------------------------------------------------------------------------------------
658D21DF98781D7C137FA213C3F3C2222C5D20A0F75BEB4929703406241379FA       C:BuildToolsVCToolsMSVC14.22.27905binHostx64x86mspdbcmf.exe
658D21DF98781D7C137FA213C3F3C2222C5D20A0F75BEB4929703406241379FA       C:BuildToolsVCToolsMSVC14.22.27905binHostx64x64mspdbcmf.exe
9664EE9A457B444E0D5A2F6A73A896375966BCF3864BBCD6B76AFEF496EC954C       C:BuildToolsVCToolsMSVC14.22.27905binHostx64x64mspdbcore.dll
9664EE9A457B444E0D5A2F6A73A896375966BCF3864BBCD6B76AFEF496EC954C       C:BuildToolsVCToolsMSVC14.22.27905binHostx64x86mspdbcore.dll
A056C5CC109CB6BFABBA3982E5739B57C2C6AEBEBDF41FB6DD17586ED4FA7F13       C:BuildToolsVCToolsMSVC14.22.27905binHostx64x86mspdbsrv.exe
A056C5CC109CB6BFABBA3982E5739B57C2C6AEBEBDF41FB6DD17586ED4FA7F13       C:BuildToolsVCToolsMSVC14.22.27905binHostx64x64mspdbsrv.exe
C48FC0A0BE36C70974CD180DD0DB22BB1EA84585BBE0B23583C6FEDCAEA0C76F       C:BuildToolsVCToolsMSVC14.22.27905binHostx64x861033mspdbcmfui.dll
C48FC0A0BE36C70974CD180DD0DB22BB1EA84585BBE0B23583C6FEDCAEA0C76F       C:BuildToolsVCToolsMSVC14.22.27905binHostx64x641033mspdbcmfui.dll
E6F6DF7DAD04699078D14D02BA57A19E332367507B860E03356AF2EEA86C3D68       C:BuildToolsVCToolsMSVC14.22.27905binHostx64x64mspdb140.dll
E6F6DF7DAD04699078D14D02BA57A19E332367507B860E03356AF2EEA86C3D68       C:BuildToolsVCToolsMSVC14.22.27905binHostx64x86mspdb140.dll
ECC40C0574AC6B93E3ACFC3EB95882D5391A2AC10E9ACC4444D418E5D5014135       C:BuildToolsVCToolsMSVC14.22.27905binHostx64x86mspdbst.dll
ECC40C0574AC6B93E3ACFC3EB95882D5391A2AC10E9ACC4444D418E5D5014135       C:BuildToolsVCToolsMSVC14.22.27905binHostx64x64mspdbst.dll

mspdb开头的所有文件在x86x64之间与目标完全相同。如果我在Hostx86文件夹中尝试相同的操作,则目标之间的文件也完全相同,但与其他主机相比不同。

我认为在MSVC 2017中为同一主机的不同目标重复使用这些文件应该是安全的。复制这些文件后我的编译成功,所以不可能完全错误!