库在gcc命令行上出现的顺序是否重要? [英] Does the order in which libraries appear on the gcc command line matter?

查看:115
本文介绍了库在gcc命令行上出现的顺序是否重要?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  #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\\\
,res);
返回0;

$ / code>

如果我在<$ em> c $ c> libm ,它按预期失败:

  $ gcc -o mathtest mathtest.c 
/tmp/cc9x6HZA.o在函数`main'中:
mathtest.c :( .text + 0x23):对`acos'的未定义引用
collect2:error:ld returned 1 exit状态

但是我可以列出 -lm

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

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



这种行为在某些时候是否改变了?或者它总是这样,我只是困惑?

解决方案

我确认您观察到的意外链接顺序行为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 I有人工包线:

  /usr/lib/gcc/x86_64-linux-gnu/4.9/collect2  - 插件/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/crt io
/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 - 需要的
- lgcc_s - 不需要-lc -lgcc - 需要-lgcc_s - 不需要
/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开始,我有:
$ b $ pre $ / 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链接通过选项 - 根据需要
在4个位置,而gcc 5.1链接仅在3个位置传递它。gcc 4.9.2 pass - 第一次在第五位引用的行中提供:

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

gcc 5.1没有通过它。之后,这两个联系都会以
的形式通过这个选项,从第13个行开始,这3个地方是相同的:

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

这意味着对于gcc 4.9.2,line13上的库选项 -lm 落入
第一个 - 根据需要的范围。对于海湾合作委员会5.1它不。此选项
的作用是通知链接程序动态库 libm (或者在选项范围内遇到
的任何动态库)应如果在链接中某个未满足符号的链接点遇到
,那么它只能链接。在
没有这个选项的情况下,在链接的给定点,一个动态库是
默认被认为是需要链接的,不管是否还有任何
未解析的符号它可以满足。请参阅 - 按需使用的文档
因此,gcc 4.9.2链接不会链接 libm ,尽管它出现了在
命令行上,因为它出现的地方 - 在 mathtest.o - - 根据需要
有效的,并且还没有未解析的引用满足 libm 满足。 gcc 5.1
linkage 会链接 libm ,因为它出现在命令行中的 - as需要
不生效。


I always thought that libraries had to be listed after any object files that depended on them, but given this simple program:

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

If I build it without linking in libm, it fails as expected:

$ 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

But I can list -lm either before or after the source file and it links successfully:

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

And I get the same behavior if I compile the source to an object file first and then link it as above.

Did this behavior change at some point? Or was it always like this, and I was just confused?

解决方案

I confirm the unexpected link-order behaviour that you observe with gcc 5.1 and also that I have the traditional behaviour with gcc 4.9.2. I would infer that this novelty comes in with gcc 5.x, and that your toolchain is gcc 5.x. Possibly it is a distro-specific anomaly of the toolchain build. My toolchain is as per ubuntu 14.04.

The novel behaviour only affects dynamic libraries. I can see what is causing it if I link in verbose mode (-v) with gcc 4.9.2 and also with gcc 5.1, placing -lm before it is needed, and examine the differences in the verbose output.

From gcc 4.9.2 I have (with artifical line-wrapping):

/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

And from gcc 5.1 I have:

/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

The relevant difference is that the gcc 4.9.2 linkage passes the option --as-needed in 4 places whereas the gcc 5.1 linkage passes it in only 3. gcc 4.9.2 passes --as-needed for the first time at the the 5th quoted "line":

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

gcc 5.1 does not pass it there. Thereafter, both linkages pass this option at the same 3 places, starting as the 13th "line":

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

This means that for gcc 4.9.2, the library option -lm on "line" 13 falls within the scope of the first --as-needed. For gcc 5.1 it does not. The effect of this option is to inform the linker that the dynamic library libm (or any dynamic library that is encountered in the option's scope) shall be linked only if it is encountered at a point in the linkage at which it can satisfy some unresolved symbols. In the absence of this option, at a given point in the linkage, a dynamic library is by default deemed to be needed for the linkage regardless of whether there are yet any unresolved symbols that it can satisfy. See the documentation of --as-needed

Thus the gcc 4.9.2 linkage will not link libm, although it appears on the commandline, because at the point where it appears - before mathtest.o - --as-needed is in force and there are as yet no unresolved references that libm satisfies. The gcc 5.1 linkage will link libm because it appears on the commandline at a point where --as-needed is not in force.

这篇关于库在gcc命令行上出现的顺序是否重要?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆