传递给链接器的库顺序

时间:2015-12-28 05:49:23

标签: c gcc linker ubuntu-14.04 suse

在我生命中的某个时间点,传递给gcc的图书馆的顺序很重要。您将gcc的库列表从最大依赖项传递到最不依赖项。例如,请考虑以下源代码:

testlib.c

include <math.h>

double proxy_sqrt(double x)
{
    return sqrt(x);
}

testlib.h

double proxy_sqrt(double);

使用-testlib.c

#include "testlib.h"

int main(int argc, char* argv[])
{
    proxy_sqrt(36);
    return 0;
}

然后编译并链接:

gcc -c -o testlib.o testlib.c
ar rvs testlib.a testlib.o
gcc -o use-testlib use-testlib.c testlib.a -lm

请注意,使用最依赖最少顺序的最后一步。

但是这个(无效?)订单适用于SLES12

gcc -o use-testlib use-testlib.c -lm testlib.a 

但在Ubuntu 14.04上失败了....

gcc -o use-testlib use-testlib.c -lm testlib.a
testlib.a(testlib.o): In function `proxy_sqrt':
testlib.c:(.text+0x1b): undefined reference to `sqrt'
collect2: error: ld returned 1 exit status

任何人都知道为什么?

2个编译器的详细输出显示在以下链接中:

sles12

http://pastebin.com/sKe8B7V9

ubuntu14.04

http://pastebin.com/vf8fTaE2

2 个答案:

答案 0 :(得分:2)

查看链接器(collect2)命令与--as-needed--no-as-needed选项之间的差异:

  

SLES 12

/usr/lib64/gcc/x86_64-suse-linux/4.8/collect2 --build-id --eh-frame-hdr \
    -m elf_x86_64 -dynamic-linker … /tmp/ccgoQd94.o -lm testlib.a -lgcc \
    --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s \
    --no-as-needed /usr/lib64/gcc/x86_64-suse-linux/4.8/crtend.o \
    /usr/lib64/gcc/x86_64-suse-linux/4.8/../../../../lib64/crtn.o
  

Ubuntu 14

/usr/lib/gcc/x86_64-linux-gnu/4.8/collect2 --sysroot=/ --build-id --eh-frame-hdr \
    -m elf_x86_64 --hash-style=gnu --as-needed -dynamic-linker … \
    /tmp/cciheQTH.o -lm testlib.a -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.8/crtend.o \
    /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crtn.o

在Ubuntu 14的选项开始时使用--as-needed会改变与SLES 12相比的行为。据说,这是为了让事情变得更容易。我仍然坚信 - 它似乎为代码在移动时提供了新的解决方法。

答案 1 :(得分:0)

对库进行分组会导致重复搜索组中的每个库,直到不再解析引用为止。

没有分组,每个库只按从左到右的顺序搜索一次。

(可以在命令行上重复库名称以帮助解决此类问题)

来自gcc链接器的手册页:http://linux.die.net/man/1/ld

- start-group archives --end-group

档案应该是档案文件列表。它们可以是显式文件名,也可以是-l选项。

重复搜索指定的存档,直到没有创建新的未定义引用。通常,只按命令行中指定的顺序搜索存档一次。如果需要该存档中的符号来解析稍后在命令行中显示的存档中的对象引用的未定义符号,则链接器将无法解析该引用。通过对存档进行分组,可以反复搜索所有存档,直到所有可能的引用都得到解决。

使用此选项会产生显着的性能损失。最好只在两个或多个档案之间存在不可避免的循环引用时才使用它。