【问题标题】:Why does the library linker flag sometimes have to go at the end using GCC?为什么库链接器标志有时必须在最后使用 GCC?
【发布时间】:2012-02-23 16:36:08
【问题描述】:

我正在编写一个使用 librt 的小型 C 程序。如果我将链接标志放在开头而不是结尾,程序将无法编译,这让我感到非常惊讶:

目前,要编译我所做的程序:

gcc -o prog prog.c -lrt -std=gnu99

如果我要执行以下操作,它将无法在 librt 中找到函数:

gcc -std=gnu99 -lrt -o prog prog.c

然而,这适用于其他库。我在尝试使用简单的 Makefile 时发现了这个问题。 make 实际上编译 prog.c 而不是先喜欢(使用 -c 标志)然后进行链接。

这是 Makefile:

CC = gcc

CFLAGS = -std=gnu99

LIBS= -lrt

LDFLAGS := -lrt


prog: prog.o

        $(CC) -o prog prog.c -lrt -std=gnu99

我在输入 make 时得到的输出是:

gcc -std=gnu99   -c -o prog.o prog.c
gcc -lrt  prog.o   -o prog
prog.o: In function `main':
prog.c:(.text+0xe6): undefined reference to `clock_gettime'
prog.c:(.text+0x2fc): undefined reference to `clock_gettime'
collect2: ld returned 1 exit status
make: *** [buff] Error 1

我现在已经制作了一个将链接放在 gcc 行末尾的 Makefile,但是我很困惑为什么如果链接标志在开头它不起作用。

如果有人可以向我解释这一点,我将不胜感激。谢谢。

【问题讨论】:

  • 我对此不是 100%,但我认为链接器可能正在查看 librt 并决定它不需要任何东西,所以就把它扔掉。 librt 是静态库吗?
  • 查看这个问题的答案,了解为什么静态链接依赖于顺序:stackoverflow.com/questions/45135/linker-order-gcc
  • 可能与默认使用的链接器的 as-needed 选项有关。你可以试试gcc -std=gnu99 -Wl,-no-as-needed -lrt -o prog prog.c

标签: c++ c linux makefile posix


【解决方案1】:

当链接器处理每个模块(无论是库还是目标文件)时,它会尝试解析每个未定义符号,同时可能会添加到其未定义符号列表中。当它到达模块列表的末尾时,它要么解析了所有未定义的符号并成功,要么报告了未定义的符号。

在您的情况下,当它处理 librt 时,它没有未定义的符号。处理过程导致clock_gettime 是一个未定义的符号。 gcc 不会返回并在 librt 中查找未定义的符号。

因此,您应该始终将代码放在首位,然后是库,然后是平台提供的库。

希望这会有所帮助。

【讨论】:

  • 小注:目标文件的顺序并不重要;引用另一个目标文件中的符号的目标文件不一定要在命令行上出现在它之前。当然,如果您认为目标文件中的所有符号都包含在最终图像中,这是有道理的,即使还没有对它们的未定义引用,因此会被添加到已定义符号列表中,因此稍后引用在另一个目标文件中不会导致未定义的符号。
  • 感谢您的洞察,这很有帮助。
  • ld 是懒惰的,只通过 .o/.a 文件一次。与普通链接器(MS 的 link.exe 等)相反,它执行 2 次传递(+ 也可能生成代码)。
【解决方案2】:

来自ld(GNU 链接器)文档 (http://sourceware.org/binutils/docs/ld/Options.html#Options):

链接器只会在命令行中指定的位置搜索存档一次。如果存档定义了在命令行上出现在存档之前的某个对象中未定义的符号,则链接器将包含存档中的适当文件。但是,稍后在命令行上出现的对象中的未定义符号不会导致链接器再次搜索存档。

因此,如果您过早指定库,链接器将扫描它,但找不到任何感兴趣的内容。然后链接器转到编译器生成的目标文件并找到需要解析的引用,但它已经扫描了库,不会再去那里寻找。

【讨论】:

    猜你喜欢
    • 2018-05-21
    • 2010-11-05
    • 2020-09-07
    • 1970-01-01
    • 2023-03-16
    • 2011-10-01
    • 2011-02-23
    相关资源
    最近更新 更多