如何删除警告LNK4099:找不到PDB'lib.pdb'

在静态编译的链接阶段,在Windows上构build时,LNK4099可能会发生警告。

例如,当使用nmake和VC10构build时,我得到了一系列LNK4099警告,如:

libcurl_a_debug.lib(rc2_cbc.obj) : warning LNK4099: PDB 'lib.pdb' was not found with 'libcurl_a_debug.lib(rc2_cbc.obj)' or at 'C:\dev\scaler\center\dlux\lib.pdb'; linking object as if no debug info 

StackOverflow提供了一个很好的问题的概述 ,但不是理解它所需的细节。

而不是忽略警告或禁用警告 ,我想修复我的生成中的makefile以消除这个问题。

问题如何出现? 我如何消除警告的原因?

了解底层问题是警告中提到的库缺少调试符号文件(.pdb)。 库文件包含对基于对象文件的.pdb的静态引用。 当另一个库使用库并使用静态编译时,Visual Studio会将所有符号收集到一个.pdb中,并更新对象文件中的.pdb引用。 但是,如果找不到符号,就会离开旧路。

通过重新编译警告中提到的库来修复警告,并确保编译器可以访问每个引用的库的.pdb。 这包括确定找不到哪个.pdb文件,然后进行更改以确保可以找到.pdb。

哪个目标文件(以及库)是我们遗漏了符号(.pdb)的?

@goth 提供了一个博客链接,解释.pdb引用来自哪里 ,但这里是我的总结:

一个库包含一些目标文件。 每个目标文件都包含调试符号的路径。 我们可以使用工具提取这些信息。 根据目标文件和路径,我们可以找出哪些调试符号文件(.pdb)找不到。

  1. 打开Visual Studio命令提示符。 这将创建一个具有访问Visual Studio工具所需的环境变量的命令shell。 (应该在“开始”菜单中的“Visual Studio工具”下,但是这会有所不同)

  2. 使用lib工具的/list选项获取库中目标文件的内部路径。 例如

 C:\dev\libcurl\win\lib>lib /list libcurl_a_debug.lib > list_of_object_files_in_library.txt C:\dev\scaler\center\agent\thirdparty\libcurl\win\lib>more list_of_object_files_in_library.txt Microsoft (R) Library Manager Version 10.00.40219.01 Copyright (C) Microsoft Corporation. All rights reserved. ..\builds\libcurl-vc10-x86-debug-static-ssl-static-ipv6-spnego-obj-lib/file.obj ..\builds\libcurl-vc10-x86-debug-static-ssl-static-ipv6-spnego-obj-lib/timeval.obj ..\builds\libcurl-vc10-x86-debug-static-ssl-static-ipv6-spnego-obj-lib/rc2_cbc.obj ... 
  1. 使用路径,使用lib工具的/extract选项提取目标文件。
 C:\dev\scaler\center\agent\thirdparty\libcurl\win\lib>lib /extract:..\builds\libcurl-vc10-x86-debug-static-ssl-static-ipv6-spnego-obj-lib/timeval.obj libcurl_a_debug.lib Microsoft (R) Library Manager Version 10.00.40219.01 Copyright (C) Microsoft Corporation. All rights reserved. 
  1. 目标文件包含一个名为.debug$T的调试部分,我们可以使用dumpbin工具进行提取。 例如
 C:\dev\scaler\center\agent\thirdparty\libcurl\win\lib>dumpbin /section:.debug$T /rawdata rc2_cbc.obj > dump_of_object_file_debug_info.txt C:\dev\scaler\center\agent\thirdparty\libcurl\win\lib>more dump_of_object_file_debug_info.txt Microsoft (R) COFF/PE Dumper Version 10.00.40219.01 Copyright (C) Microsoft Corporation. All rights reserved. Dump of file ./rc2_cbc.obj File Type: COFF OBJECT SECTION HEADER #9 .debug$T name 0 physical address 0 virtual address 5C size of raw data 1D53 file pointer to raw data (00001D53 to 00001DAE) 0 file pointer to relocation table 0 file pointer to line numbers 0 number of relocations 0 number of line numbers 42100040 flags Initialized Data Discardable 1 byte align Read Only RAW DATA #9 00000000: 04 00 00 00 56 00 15 15 03 7A 47 A3 3D 4A 8C 4B ....V....zGú=JK 00000010: A2 A5 26 D3 D6 57 15 46 3A 00 00 00 73 3A 5C 73 óÑ&ËÍW.F:...s:\s 00000020: 63 61 6C 65 78 2E 6E 65 77 5C 63 65 6E 74 72 6F caler.new\center 00000030: 5C 6F 70 65 6E 73 73 6C 5C 62 75 69 6C 64 5C 6F \openssl\build\o 00000040: 70 65 6E 73 73 6C 2D 31 2E 30 2E 30 62 5C 74 6D penssl-1.0.0b\tm 00000050: 70 33 32 5C 6C 69 62 2E 70 64 62 00 p32\lib.pdb. Summary 5C .debug$T 

在上面,你会看到目标文件显示它的调试符号s:\scaler.new\center\openssl\build\openssl-1.0.0b\tmp32\lib.pdb 因此,问题出在我们构建libcurl使用的openssl库时生成的.pdb。

如何将调试符号添加到生成警告的库中?

/ Fd选项管理.pdb符号文件的名称和位置 。 例如,编译libcurl时,我使用了以下标志:

 ... !IF DEFINED(VC10) NT_MAK_FLAGS = APP_CFLAG="/GX /GZ /MTd /Fdtmp32.dbg/app" LIB_CFLAG="/Zl /Z7 /Fdtmp32.dbg/lib" !ENDIF ... 

lib.pdb的符号文件名及其相对于构建的路径由/Fdtmp32.dbg/lib给出。

问题是NT_MAK_FLAGS被重用于编译openssl时生成的一些库。 结果是, lib.pdb最后一个库之外, lib.pdb被破坏(覆盖)。 为了解决这个问题,每个库应该被赋予一个唯一的名字。 为了进一步简化问题,请确保编译位置与libcurl构建在同一个树中。

这发生在我的图书馆.lib,也许附加的图像将帮助其他人。 在我的情况下,我不得不确保.lib和.pdb文件在同一个目录中,所以请注意$(OutDir)是如何出现在设置中的。

确保目录是相同的

当我将一个旧的32位VS2010项目导入VS2013并将其设置为64位时,我认为他们没有对齐。

所以我最终得到这个(好)的情况:

.lib和.pdb放在同一个目录下