库在 gcc 命令行中出现的顺序重要吗?

Does the order in which libraries appear on the gcc command line matter?

我一直认为库必须在任何依赖它们的目标文件之后列出,但是考虑到这个简单的程序:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <math.h>

int main(int argc, char **argv) {
    double res;

    res = acos(2);
    printf("res = %f\n", res);
    return 0;
}

如果我 没有 link 在 libm 中构建它,它会按预期失败:

$ gcc -o mathtest mathtest.c 
/tmp/cc9x6HZA.o: In function `main':
mathtest.c:(.text+0x23): undefined reference to `acos'
collect2: error: ld returned 1 exit status

但我可以在源文件之前或之后列出 -lm,并且 link 成功:

gcc -o mathtest -lm mathtest.c
gcc -o mathtest mathtest.c -lm

如果我先将源代码编译为目标文件,然后 link 如上所述,我会得到相同的行为。

这种行为是否在某个时候发生了变化?还是一直都是这样,我只是一头雾水?

我确认了您在 gcc 5.1 和 另外,我对 gcc 4.9.2 有传统的行为。我会推断这 gcc 5.x 带来了新颖性,您的工具链是 gcc 5.x。可能吧 是工具链构建的发行版特定异常。我的工具链符合 ubuntu 14.04.

新行为仅影响 动态 库。我可以看到是什么原因造成的 如果我使用 gcc 4.9.2 和 gcc 5.1 link 处于详细模式 (-v),在需要它之前放置 -lm, 并检查详细输出中的差异。

从 gcc 4.9.2 我有(人工换行):

/usr/lib/gcc/x86_64-linux-gnu/4.9/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/4.9/liblto_plugin.so 
-plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/4.9/lto-wrapper -plugin-opt=-fresolution=/tmp/ccsHNLNB.res 
-plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc 
-plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --sysroot=/ --build-id 
--eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -dynamic-linker 
/lib64/ld-linux-x86-64.so.2 -z relro -o mathtest 
/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu/crt1.o 
/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu/crti.o 
/usr/lib/gcc/x86_64-linux-gnu/4.9/crtbegin.o -L/usr/lib/gcc/x86_64-linux-gnu/4.9 
-L/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu
-L/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../../lib -L/lib/x86_64-linux-gnu 
-L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib 
-L/usr/lib/gcc/x86_64-linux-gnu/4.9/../../.. -lm mathtest.o -lgcc --as-needed 
-lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed 
/usr/lib/gcc/x86_64-linux-gnu/4.9/crtend.o 
/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu/crtn.o

从 gcc 5.1 我有:

/usr/lib/gcc/x86_64-linux-gnu/5/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/5/liblto_plugin.so 
-plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/5/lto-wrapper -plugin-opt=-fresolution=/tmp/cc5hI8vd.res 
-plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc 
-plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --sysroot=/ --build-id 
--eh-frame-hdr -m elf_x86_64 --hash-style=gnu -dynamic-linker 
/lib64/ld-linux-x86-64.so.2 -z relro -o mathtest 
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crt1.o 
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crti.o 
/usr/lib/gcc/x86_64-linux-gnu/5/crtbegin.o -L/usr/lib/gcc/x86_64-linux-gnu/5 
-L/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu 
-L/usr/lib/gcc/x86_64-linux-gnu/5/../../../../lib -L/lib/x86_64-linux-gnu 
-L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib 
-L/usr/lib/gcc/x86_64-linux-gnu/5/../../.. -lm mathtest.o -lgcc --as-needed 
-lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed 
/usr/lib/gcc/x86_64-linux-gnu/5/crtend.o 
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crtn.o

相关区别在于 gcc 4.9.2 linkage 通过选项 --as-needed 在 4 个地方,而 gcc 5.1 linkage 仅在 3 个地方通过。gcc 4.9.2 通过 --as-needed 第一次在第 5 次引用 "line":

--eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -dynamic-linker

gcc 5.1 没有通过它。此后,两个 linkages 都通过了这个选项 同样的3个地方,从第13个开始"line":

-L/usr/lib/gcc/x86_64-linux-gnu/4.9/../../.. -lm mathtest.o -lgcc --as-needed

这意味着对于 gcc 4.9.2,"line" 13 上的库选项 -lm 属于 第一个范围--as-needed。对于 gcc 5.1,它没有。这个选项的效果 是通知 linker 动态库 libm (或任何动态库 在选项的范围内遇到)应 linked 只有 如果遇到 在link年龄的某个点,它可以满足一些未解决的符号。在里面 没有这个选项,在 linkage 的给定时间点,动态库是 默认被认为是 linkage 所需要的,无论是否还有任何 它可以满足的未解决的符号。参见 the documentation of --as-needed

因此 gcc 4.9.2 linkage 不会 link libm,尽管它出现在 命令行,因为在它出现的地方 - 在 mathtest.o - --as-needed 之前 生效,目前还没有 libm 满足的未解决参考。海湾合作委员会5.1 linkage will link libm 因为它出现在命令行上 --as-needed 未生效。