为什么使用 GCC 时库链接器标志有时必须放在最后?
我正在编写一个使用 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
当链接器处理每个模块(无论是库还是目标文件)时,它会尝试解析每个未定义的符号,同时可能会添加到其未定义符号列表中。当到达模块列表的末尾时,它要么已解析所有未定义的符号并成功,要么报告未定义的符号。
就您而言,当它处理 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.
来自
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):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.