如何合并多个PDB文件?

问题描述 投票:0回答:4
我们目前正在使用单个命令行工具在 Windows 和 Linux 上构建我们的产品。

到目前为止,它工作得很好,允许我们从源代码构建,并且比我们以前的构建系统所允许的依赖关系更精细。这为我们带来了强大的增量和并行构建能力。

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

.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 这样的工具如何解决这个问题?

visual-c++ command-line pdb-files
4个回答
6
投票
无需合并PDB文件。

使用

/Z7

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

使用

LIB.EXE

 创建带有嵌入式调试信息的静态库。  使用 
LINK.EXE
 代替 
CL.EXE
 进行链接;通过 
/DEBUG
 生成 PDB;您还可以使用 
/PDB
 覆盖默认 PDB 名称(通常是可执行文件的基本名称)。

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


5
投票
我已经很长时间没有使用 C++ 了,但从这篇

文章来看,这似乎是一个性能技巧,旨在阻止重新创建公共标头的符号。

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

文章中所示。


2
投票
可以合并 PDB 文件,但只能通过 cl.exe 和 link.exe 完成。 我不知道有什么独立工具可以合并 PDB 文件。

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

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

你不能将PDB文件归档到.LIB文件中,我用VC2003尝试过,失败了。

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

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

cl /Zi 测试.c

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

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

我通过反复使用编译器得到了上述结论,然后捕获 sysinternals 的 procexp 结果并对其进行分析。希望有帮助。


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

这还有一个好处,它可以解决

此处提到的并发访问共享 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 文件中。

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

© www.soinside.com 2019 - 2024. All rights reserved.