为什么使用 GCC 时库链接器标志有时必须放在最后?

发布于 2025-01-08 11:53:07 字数 927 浏览 0 评论 0原文

我正在编写一个使用 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

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

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

I'm writing a small C program that uses librt. I'm quite surprised that the program won't compile if I place the link flag at the start instead of at the end:

At the moment, to compile the program I do:

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

If I were to do the following, it will fail to find the functions in librt:

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

Yet, this works with other libraries. I found the issue when attempting to use a simple Makefile. make actually compiled prog.c without liking first (using -c flag) and then did the linking.

This is the Makefile:

CC = gcc

CFLAGS = -std=gnu99

LIBS= -lrt

LDFLAGS := -lrt


prog: prog.o

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

The output I would get when typing make would be:

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

I have now crafted a Makefile that puts the linking at the end of the gcc line, however I'm puzzled why it doesn't work if the linking flag is at the start.

I would appreciate if anybody can explain this to me. Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

浅忆 2025-01-15 11:53:07

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

就您而言,当它处理 librt 时,它没有未定义的符号。处理 proc 导致clock_gettime 成为未定义的符号。 gcc 不会返回并在 librt 中查找未定义的符号。

因此,您应该始终首先拥有代码,然后是库,最后是平台提供的库。

希望这有帮助。

As the linker processes each module (be it a library or a object file), it attempts to resolve each undefined symbol while potentially adding to its list of undefined symbols. When it gets to the end of the list of modules, it either has resolved all undefined symbols and is successful or it reports undefined symbols.

In your case, when it processed librt, it had no undefined symbols. Processing proc resulted in clock_gettime being an undefined symbol. gcc will not go back and look in librt for the undefined symbols.

For that reason, you should always have your code first, followed by your libraries, followed by platform provided libraries.

Hope this helps.

じее 2025-01-15 11:53:07

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

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

因此,如果您过早指定库,链接器将扫描它,但不会找到任何感兴趣的内容。然后链接器继续处理编译器生成的目标文件并找到需要解析的引用,但它已经扫描了库并且不会再费心再次查找。

From the ld (the GNU linker) documentation (http://sourceware.org/binutils/docs/ld/Options.html#Options):

The linker will search an archive only once, at the location where it is specified on the command line. If the archive defines a symbol which was undefined in some object which appeared before the archive on the command line, the linker will include the appropriate file(s) from the archive. However, an undefined symbol in an object appearing later on the command line will not cause the linker to search the archive again.

So if you specify the library too early, the linker will scan it, but not find anything of interest. Then the linker moves on to the object file produced by the compiler and finds references that need to be resolved, but it has already scanned the library and won't bother looking there again.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文