c++ - 链接时不同静态库中的相同目标文件

标签 c++ clang static-linking

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 中的重复符号会发生什么情况?是否需要任何标志才能不生成符号重复错误?

最佳答案

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

这是因为链接器不会将静态库“组合”成最终的可执行文件。它仅将提供的目标文件合并到可执行文件中。链接器从左到右处理目标文件和归档库的列表。当遇到静态库时,链接器会检查库提供的目标文件是否定义了当前 undefined symbol 。然后,也只有到那时,才会拉入该目标文件。

在您的示例中:

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.o 并将其添加到 lib.so,并注意该符号未定义。
  2. 链接器将打开dir1/lib1.a并检查存档中包含的任何目标文件是否定义了所述符号。由于 foo.o 定义了该符号,因此 foo.o 将被添加到 lib.so 并且该符号将被标记为已定义。
  3. 链接器将打开dir2/lib2.a。但当前没有 undefined symbol ,因此重复的目标文件将被忽略。
  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 是不同的,并且总是将所有遇到的对象文件(来自静态库)添加到输出中。

关于c++ - 链接时不同静态库中的相同目标文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59978787/

相关文章:

c++ - 有没有一种方法可以使用 catch 框架来比较流或文件?

c++:gcc 是否提供扩展的宏/函数,如 "countof"数组的大小?

c++ - 语义规则的编译时执行

当我使用 GNU C 库提供的非标准函数时,Clang 会警告我吗?

python - Protobuf 消息构造器

c++ - 返回类型 Vector

c++ - 隐藏成员函数模板 - 哪个编译器是正确的?

c++ - Visual Studio 2008 IDE - 静态链接 C Dll 库

c++ - Visual Studio 中静态链接 OpenSceneGraph 库的未解决外部问题

c++ - VS2015如何将静态库链接到其他库和可执行文件?