如何合并多个PDB文件?

时间:2009-02-09 13:20:59

标签: visual-c++ command-line pdb-files

我们目前正在使用单一命令行工具在Windows和Linux上构建我们的产品。

Si far的工作很好,允许我们构建源代码,并且具有比我们以前的构建系统允许的更好的依赖性。这为我们带来了很好的增量和并行构建功能。

为了简要描述构建过程,我们得到了通常的结果:

.cpp -- cl.exe --> .obj and .pdb
multiple .obj and .pdb -- cl.exe --> single .dll .lib .pdb
multiple .obj and .pdb -- cl.exe --> single .exe .pdb

msvc C / C ++编译器充分支持它。

最近出现了构建一些静态库的需求。 根据我们收集的内容,构建静态库的过程是:

multiple .cpp -- cl.exe --> multiple .obj and a single .pdb
multiple .obj -- lib.exe --> a single .lib

单个.pdb意味着cl.exe只应对所有.cpp源执行一次。这种单一执行意味着我们无法并行化此静态库的构建。这真的很不幸。

我们进一步调查并根据文档(以及可用的命令行选项):

  • cl.exe不知道如何构建静态库
  • lib.exe不知道如何构建.pdb文件

有人知道合并多个PDB文件的方法吗?我们注定要为静态库建立慢速构建吗?像Incredibuild这样的工具如何解决这个问题呢?

4 个答案:

答案 0 :(得分:5)

我很长一段时间没有完成C ++,但是从这个article开始,这似乎是停止重新创建常用标题符号的性能技巧。

您可以尝试/ Z7在每个obj中嵌入信息,而不是创建PDB,然后使用rebase链接并重新创建它,如此article

答案 1 :(得分:5)

无需合并PDB文件。

使用/ Z7编译源文件,以避免在CL.EXE步骤中创建PDB。

使用LIB.EXE创建包含嵌入式调试信息的静态库。使用LINK.EXE而不是CL.EXE进行链接,使用/ PDB指定调试信息的位置。

如果您正在使用EXE和一个或多个DLL调试进程,请为调试器提供每个映像(EXE或DLL)的PDB。

答案 2 :(得分:2)

可以合并PDB文件,但只能通过cl.exe和link.exe来完成。 我不知道合并PDB文件的任何立法工具。

您可以使用/ PDB选项链接器(我检查过VC2005)来指定备用pdb文件名。

Microsoft建议还包括PDB文件(每个obj都有相应的PDB文件)以及.LIB文件。

您无法将.LIB文件中的PDB文件存档,我用VC2003尝试过,失败了。

使用/ Z7编译可以避免.LIB的PDB文件,但是目标文件很大,除非link.exe剥离调试信息。如果链接器没有/ debug选项,则无法调试exe / dll。

编译器(cl.exe)始终写入vcXX.pdb文件,除非您使用/ Fd选项指定其他名称。 即使您使用cl.exe“直接”生成可执行文件,它也会生成一个vc80.pdb文件,然后link.exe将生成与可执行文件相同的pdb文件名。

cl / Zi test.c

cl.exe - > vc80.pdb link.exe读取vc80.pdb(该名称嵌入在test.obj文件中) - > test.pdb

每次cl / Zi / c编译一个文件时,它都会尝试修改现有的vcXX.pdb文件,而不是覆盖它。

我通过一次又一次地使用编译器获得上述结论,然后捕获sysinternals的procexp结果并对其进行分析。希望它有所帮助。

答案 3 :(得分:1)

除非您想使用调试信息重新分发静态库,否则您实际上不需要合并任何PDB文件(或使用/Z7嵌入调试信息)。

正如@zhaorufei所提到的,当使用/Zi时,每个目标文件都包含对其PDB文件的引用,然后链接器将使用该文件。

只需使用/Fd为每个对象提供唯一的PDB文件:

> cl -c foo.cpp -Fo:target/foo.obj -Fd:target/foo.pdb -Zi
> cl -c bar.cpp -Fo:target/bar.obj -Fd:target/bar.pdb -Zi

> strings target/foo.obj | grep pdb
D:\Dev\sample\target\foo.pdb
> strings target/bar.obj | grep pdb
D:\Dev\sample\target\bar.pdb

这样做的好处是可以解决并发访问here共享PDB文件的问题,因此您可以按照自己的意愿并行化编译步骤。

然后像往常一样链接/存档目标文件。 VC ++已经将各种信息嵌入到目标文件中以将它们传递给链接器,例如运行时链接设置和依赖库 - PDB文件路径也不例外。从对象创建静态库不会删除引用:

> lib -out:target/all.lib target/foo.obj target/bar.obj
> strings target/all.lib | grep pdb
D:\Dev\sample\target\bar.pdb
D:\Dev\sample\target\foo.pdb

将此库链接到可执行文件或DLL时,链接器仍会从引用的PDB中提取调试信息,并将其添加到最终的PDB文件中。

我能看到的唯一警告是路径始终是绝对路径,因此如果您在链接之前将文件移动到本地或另一台机器上,这可能不起作用。