代码之家  ›  专栏  ›  技术社区  ›  sashang

传递给链接器的库的顺序

  •  1
  • sashang  · 技术社区  · 9 年前

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

    测试库.c

    include <math.h>
    
    double proxy_sqrt(double x)
    {
        return sqrt(x);
    }
    

    测试库.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
    

    有人知道为什么吗?

    下面的链接显示了两个编译器的详细输出:

    雪崩12

    http://pastebin.com/sKe8B7V9

    2004年4月14日

    http://pastebin.com/vf8fTaE2

    2 回复  |  直到 9 年前
        1
  •  2
  •   Jonathan Leffler    9 年前

    查看链接器中的差异( 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
    

    使用 --根据需要 与SLES 12相比,Ubuntu 14的选项一开始就改变了事物的行为。众所周知,这是为了让事情变得更容易。我仍然坚信,它似乎为代码移动时的破解提供了新的途径。

        2
  •  0
  •   user3629249    9 年前

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

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

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

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

    --开始组存档--结束组

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

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

    使用此选项会带来显著的性能成本。最好只在两个或多个档案之间存在不可避免的循环引用时使用它。