我一直认为必须在之后列出依赖于它们的任何目标文件的,但是给出了这个简单的程序:
#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
如果我首先将源代码编译为目标文件然后如上所述链接它,我会得到相同的行为。
这种行为在某些时候发生了变化吗?或者它总是这样,我只是困惑?
答案 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
点的命令行上
没有生效。