C++ 通过`-l<;libname>;`vs通过'lib<;libname>;。直接连接到链接器?

C++ 通过`-l<;libname>;`vs通过'lib<;libname>;。直接连接到链接器?,c++,c,unix,linker,C++,C,Unix,Linker,假设我有两个文件 // a.c int a() {return 1;} // b.c int a(); int b() {return a();} 我将它们分别编译成a.o和b.o 在尝试创建可执行或共享库时,可以调用gcc a.o b.o-o libab.so-shared。但我也注意到,我们也可以调用gccb.o-L.-L:a.o-o libab.so-shared来生成(显然)相同的输出。令我惊讶的是,即使运行gcc a.o-L-L:b.o-shared也会产生一个既有a()又有b()

假设我有两个文件

// a.c
int a() {return 1;}

// b.c
int a();
int b() {return a();}
我将它们分别编译成
a.o
b.o

在尝试创建可执行或共享库时,可以调用
gcc a.o b.o-o libab.so-shared
。但我也注意到,我们也可以调用
gccb.o-L.-L:a.o-o libab.so-shared
来生成(显然)相同的输出。令我惊讶的是,即使运行
gcc a.o-L-L:b.o-shared
也会产生一个既有
a()
又有
b()
的库。(链接器不应该丢弃未使用的库
b.o
,因为
a.o
不依赖于它吗?)

后两个可能传递
a
,就好像
a.o
是一个库一样。现在,如果我运行
ar rcs liba.a a.o
gcc b.o-L-L:liba.a-shared
gcc b.o liba.a-shared
这两个命令都运行正常,并给出相同的输出

然而,我也看到过这样的情况:这个技巧不起作用,导致未定义的引用。因此,我的问题是:标题是:作为一个库传递一个对象和作为一个普通对象文件之间的区别,当涉及到C++(?)/P>时,有什么不同吗? 这个问题出现在一个大得多的项目中。很抱歉缺少mcve,因为我似乎无法隔离问题

-l
传递与将
lib.a
直接传递到链接器有什么区别

传递
-llibname.so
将使GNU链接器在搜索符号时只遍历库一次(不在
--whole archive
选项之后)。将
.a
文件直接指定给链接器,使链接器可以搜索
中所有对象文件中的每个符号。a
文件可以搜索每个符号,而不是只搜索一次

从(我的)重点:

-图书馆

在命令中写入此选项的位置会有所不同;链接器按照指定的顺序搜索和处理库和对象文件。因此,'foo.o-lzbar.o'在文件foo.o之后、bar.o之前搜索库'z'。如果bar.o引用“z”中的函数,则可能不会加载这些函数

发件人:

-l名称规范

链接器将只在命令行上指定的位置搜索存档一次。如果存档定义了在命令行存档之前出现的某个对象中未定义的符号,则链接器将包含存档中的相应文件。但是,稍后出现在命令行上的对象中的未定义符号不会导致链接器再次搜索存档

作为一个库传递一个对象和作为一个普通对象文件之间的区别是什么,当涉及到C+++< /P>时,有什么不同吗? 这取决于实施情况。从最一般的意义上讲,Unix风格的链接器(例如,您正在询问如何在库搜索路径中通过

-l
选项搜索命名的对象),而如果您直接命名文件,则必须指定确切的文件

此外,如果使用
-l
选项指定要链接的文件,则在一般情况下,链接器通过在“lib”前面加上“.a”或以其他方式(例如也搜索或代替搜索“.so”文件)从参数构造文件名。(当参数的第一个字符为
时,您似乎正在使用的GNU链接器提供了此行为的例外。在这种情况下,它将参数的其余部分作为确切的文件名,并搜索该文件名。)

许多链接器还接受在命令行上指定的显式库名称(例如,
libfoo.a
而不是
-lfoo
),因此它们需要能够确定每个文件的类型。通常,这是通过检查文件,而不是依赖其名称。GNU
ld
,至少将此文件类型检测扩展到通过
-l
选项指定的文件

在命令行上以任何特定形式指定对象和库的顺序对于典型的链接器实现都很重要。例如,指定

引用文件的选项,如'-l'或'-T',会导致文件 在命令行中选项出现的位置读取, 相对于对象文件和其他文件选项

这很重要,因为

链接器将只在存档所在的位置搜索存档一次 在命令行上指定。如果存档定义了一个符号 在档案之前出现的某个对象中未定义 在命令行上,链接器将包含相应的文件 从档案中。但是,对象中出现的未定义符号 稍后,命令行将不会导致链接器搜索 再次存档

但当然

您可以在命令行上多次列出同一存档

文档对此并不完全清楚,但根据经验,在上面使用“归档”一词意义重大。实际上,只有“只搜索一次”的规定适用于归档文件——静态库。首先,GNU链接器命令行上不同的普通对象文件和共享库的相对顺序,无论如何指定,都不会影响符号分辨率

因此,是的,无论您是向(GNU)链接器指定常规对象文件还是静态归档或共享库,它们的顺序都很重要,但指定它们的方式并不重要

我也看到过这样的情况:这个技巧不起作用,结果是未定义的引用

使用GNU链接器,这将是因为真正缺少库或对象,或者是因为静态归档相对于其他对象文件或归档的顺序不合适。其他一些链接器更具吸引力