C++ 链接时不同静态库中的相同对象文件

C++ 链接时不同静态库中的相同对象文件,c++,clang,static-linking,C++,Clang,Static Linking,生成lib.so时,foo.cpp中的重复符号会发生什么变化?是否需要任何标志来不生成符号复制错误?当提供的多个库中出现相同的对象文件时,链接多个静态库不会导致任何重复符号错误(默认情况下) 这是因为链接器不会将静态库“组合”到最终的可执行文件中。它只将提供的对象文件合并到可执行文件中。链接器从左到右处理对象文件和归档库的列表。遇到静态库时,链接器会检查库提供的任何对象文件是否定义了当前未定义的符号。然后,也只有到那时,才会拉入该对象文件 在您的示例中: clang++ ... foo.cpp

生成lib.so时,foo.cpp中的重复符号会发生什么变化?是否需要任何标志来不生成符号复制错误?

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

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

在您的示例中:

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
考虑另外两个对象文件:

clang++ ... dir1/lib1.a dir2/lib2.a ... -o lib.so
如果
obj1.o
引用了
foo.cpp
中存在的符号:

  • 链接器将处理并将
    obj1.o
    添加到
    lib.so
    ,注意所述符号未定义
  • 链接器将打开
    dir1/lib1.a
    ,并检查存档中包含的任何对象文件是否定义了所述符号。因为
    foo.o
    定义了符号,所以
    foo.o
    将添加到
    lib中。因此
    将标记为已定义符号
  • 链接器将打开
    dir2/lib2.a
    。但当前没有未定义的符号,因此将忽略重复的对象文件
  • 链接器将处理并将
    obj2.o
    添加到
    lib.so
    。链接器不会返回并重新处理
    lib1.a
    lib2.a
  • 因此,不应引发重复符号错误(默认情况下,在Linux上)。要更改此行为,您可以使用链接器选项
    --whole archive

    clang++ obj1.o dir1/lib1.a dir2/lib2.a obj2.o -o lib.so
    
    使用
    --整个存档
    将指定存档库中的所有对象文件添加到输出中。然后,上述命令会导致
    foo.cpp
    中的任何符号出现“多重定义”错误


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

    如果“clang++obj1.o dir1/lib1.a obj2.o dir2/lib2.a-o lib.so”以及obj1和obj2都引用foo.o,那么foo.o中的全局符号将出现重复符号错误,对吗?或者链接器只是使用前面添加的foo.o中的符号,而从不查看第二个foo.o?请认为链接器只是从.a中选择方法,然后将其放入结果中。如果链接器将.a中的整个.o添加到结果中,则最好在每个源文件中使用尽可能少的代码设计静态库。如果“obj1和obj2都引用foo.o”,则仍然不会有重复的符号。处理obj2时,不需要再次查找,因为所有引用的符号都被视为已解析。(链接器正在构建一个已知符号的表)。“如果链接器将.a中的整个.o添加到结果中,静态库最好使用尽可能少的代码进行设计”-从技术上讲,链接器提取的是部分而不是整个对象文件。默认情况下,.text部分包含所有函数,但您可以在编译库时使用“-ffunction部分”将它们拆分以避免浪费空间
    clang++ ... -Wl,--whole-archive dir1/lib1.a dir2/lib2.a -Wl,--no-whole-archive ... -o lib.so