库在 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
未生效。
我一直认为库必须在任何依赖它们的目标文件之后列出,但是考虑到这个简单的程序:
#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
未生效。