链接时,不同静态库中的同一对象文件

Same object file in different static libraries when linking

本文关键字:对象 文件 静态 链接      更新时间:2023-10-16
clang++ ... foo.cpp ... -o dir1/foo.o
clang++ ... foo.cpp ... -o dir2/foo.o
//The only difference beween the above two clang++ command lines
//is the output directory
llvm-ar ... dir1/lib1.a ...  dir1/foo.o ...
llvm-ar ... dir2/lib2.a ...  dir2/foo.o ...
clang++ ... dir1/lib1.a dir2/lib2.a ... -o lib.so

生成 lib.so 时,foo.cpp 中的重复符号会发生什么情况?是否有任何标志要求不生成符号重复错误?

当同一个对象文件出现在提供的多个库中时,链接多个静态库不会导致任何重复符号错误(默认情况下(。

这是因为链接器不会将静态库"合并"到最终的可执行文件中。它仅将提供的目标文件合并到可执行文件中。链接器从左到右处理对象文件和存档库的列表。遇到静态库时,链接器会检查是否有任何库提供的对象文件定义了当前未定义的符号。然后,也只有这样,才会拉入该对象文件。

在您的示例中:

clang++ ... dir1/lib1.a dir2/lib2.a ... -o lib.so

请考虑另外两个对象文件:

clang++ obj1.o dir1/lib1.a dir2/lib2.a obj2.o -o lib.so

如果obj1.o引用foo.cpp中存在的符号:

  1. 链接器将处理并添加obj1.olib.so,注意所述符号是未定义的。
  2. 链接器将打开dir1/lib1.a并检查存档中包含的任何对象文件是否定义了所述符号。由于foo.o定义了符号,因此foo.o将被添加到lib.so并且符号将被标记为已定义。
  3. 链接器将打开dir2/lib2.a。但是当前没有未定义的符号,因此将忽略重复的对象文件。
  4. 链接器将处理obj2.o并将其添加到lib.so。链接器不会返回并重新处理lib1.alib2.a

因此,不应引发重复符号错误(默认情况下,在 Linux 上(。若要更改此行为,可以使用链接器选项--whole-archive

clang++ ... -Wl,--whole-archive dir1/lib1.a dir2/lib2.a -Wl,--no-whole-archive ... -o lib.so

使用--whole-archive指定存档库中的所有对象文件都将添加到输出中。然后,上述命令会导致foo.cpp中的任何符号出现"多重定义"错误。

这个答案描述了 Linux 上的行为,我相信 AIX 是不同的,并且总是将所有遇到的对象文件(来自静态库(添加到输出中。