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

时间:2015-08-07 00:13:45

标签: gcc linker libraries

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

#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;
}

如果我在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并成功链接:

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

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

这种行为在某些时候发生了变化吗?或者它总是这样,我只是困惑?

1 个答案:

答案 0 :(得分:1)

我确认您使用gcc 5.1和。观察到的意外链接顺序行为 我也有gcc 4.9.2的传统行为。我推断这个 新颖性来自gcc 5.x,你的工具链是gcc 5.x.可能是它 是工具链构建的特定于发行版的异常。我的工具链是根据ubuntu 14.04。

新颖的行为只会影响动态库。我可以看到是什么导致了它 如果我用详细模式(-v)与gcc 4.9.2以及gcc 5.1链接,在需要之前放置-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链接传递选项--as-needed 在4个地方,而gcc 5.1连接只通过3. gcc 4.9.2通过--as-needed 这是第5次引用“线”的第一次:

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

gcc 5.1没有将它传递给那里。此后,两个链接都通过此选项 相同的3个地方,从第13个“线”开始:

-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,它没有。这个选项的效果 是通知链接器动态库libm(或任何动态库 在选项的范围内遇到)只有在遇到时才链接 在链接中的一个点,它可以满足一些未解决的符号。在里面 没有这个选项,在链接的给定点,动态库是通过 无论是否存在任何关联,默认都被认为是必要的 它可以满足的未解决的符号。见the documentation of --as-needed

因此gcc 4.9.2链接不会链接libm,尽管它出现在。{1}}上 命令行,因为它出现在mathtest.o - --as-needed之前 现在还没有libm满足的尚未解决的引用。 gcc 5.1 链接链接libm,因为它出现在--as-needed点的命令行上 没有生效。