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
中存在的符号:
obj1.o
并将其添加到lib.so
,请注意该符号未定义。dir1/lib1.a
,并检查档案中包含的任何目标文件是否定义了该符号。因为foo.o
定义了符号,所以foo.o
将添加到lib.so
并将符号标记为已定义。dir2/lib2.a
。但是当前没有未定义的符号,因此重复的目标文件将被忽略。obj2.o
添加到lib.so
。链接器不会notlib1.a
或lib2.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是不同的,并且将始终将所有遇到的目标文件(来自静态库)添加到输出中。