到目前为止,它工作得很好,允许我们从源代码构建,并且比我们以前的构建系统所允许的依赖关系更精细。这为我们带来了强大的增量和并行构建能力。
为了简要描述构建过程,我们得到通常的:
.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文件
使用
/Z7
编译源文件,以避免在
CL.EXE
步骤中创建 PDB。使用
LIB.EXE
创建带有嵌入式调试信息的静态库。 使用
LINK.EXE
代替
CL.EXE
进行链接;通过
/DEBUG
生成 PDB;您还可以使用
/PDB
覆盖默认 PDB 名称(通常是可执行文件的基本名称)。如果您正在使用 EXE 和一个或多个 DLL 调试进程,请为调试器提供每个映像(EXE 或 DLL)的 PDB。
文章来看,这似乎是一个性能技巧,旨在阻止重新创建公共标头的符号。
您可以尝试 /Z7 在每个 obj 中嵌入信息,而不是创建 PDB,然后使用 rebase 链接并重新创建它,如本文章中所示。
您可以使用链接器的 /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 结果并对其进行分析。希望有帮助。
重新分发带有调试信息的静态库,否则实际上不需要合并任何PDB文件(或使用/Z7
嵌入调试信息)。正如 @zhaorufei 提到的,使用
/Zi
时,每个目标文件都包含对其 PDB 文件的引用,链接器随后会使用该文件。只需使用 即可为每个对象提供唯一的 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 文件中。
我能看到的唯一警告是路径始终是绝对的,因此如果您在链接之前将文件移动到本地或另一台计算机,这可能不起作用。