链接器出现问题-未定义参考
我的编译器遇到问题,告诉我要在库中使用的函数有"未定义的引用"。让我分享有关该问题的一些信息:
- 我正在用gcc为C进行交叉编译。
- 我正在调用一个库函数,该函数可以通过包含的标头访问,该标头包含另一个包含原型的标头。
- 我已经使用-I包含了标头目录,并且我确定已找到它。
- 我首先创建.o文件,然后在单独的命令中链接它们。
所以我想这可能是我添加库文件的顺序,但是我不确定订购它们的正确方法是什么。我尝试在.o文件之前和之后都包含headers文件夹。
一些建议可能很棒,也许还有关于链接程序如何执行其操作的解释。
谢谢!
对答案的回应
- 没有.a库文件,库中只有.h和.c,所以-l不适用
- 我对库文件的理解是,它只是头文件和源文件的集合,但是也许是从源文件创建的.o文件的集合?
- 没有正在创建的库对象文件,也许应该有??是的,我似乎不了解include和库之间的区别...我会努力解决这一问题的:-)
感谢所有回复!我学到了很多关于图书馆的知识。我想将所有答复作为可接受的答案:-)
解决方案
我想我们必须添加链接程序可以找到libraray的路径。在gcc / ld中,我们可以使用-L进行此操作,而libraray可以使用-l进行此操作。
-Ldir, --library-path=dir Search directory dir before standard search directories (this option must precede the -l option that searches that directory). -larch, --library=archive Include the archive file arch in the list of files to link.
Response to answers - there is no .a library file, just .h and .c in the library, so -l isn't approriate
然后,我们可能必须先创建天秤座?
gcc -c mylib.c -o mylib.o ar rcs libmylib.a mylib.o
标头提供函数声明和函数定义。要允许链接器找到该函数的实现(并摆脱未定义的引用),我们需要使用-l标志要求编译器驱动程序(gcc)链接该函数所驻留的特定库。例如,-lm将链接数学库。函数的手册页通常指定必须找到的库(如果有的话)才能找到函数。
如果链接器找不到指定的库,则可以使用-L开关(例如,-L / usr / local / lib)添加库搜索路径。我们还可以通过LIBRARY_PATH环境变量永久影响库路径。
以下是一些其他详细信息,可调试问题。按照惯例,库文件的名称以lib开头,并且(以其静态形式)具有.a扩展名。因此,系统默认数学库的静态链接版本(我们使用-lm链接的版本)通常位于/usr/lib/libm.a中。要查看给定库定义的符号,可以在库文件上运行nm --defined-only。在我的系统上,在libm.a上运行命令会给我类似以下的输出。
e_atan2.o: 00000000 T atan2 e_asinf.o: 00000000 T asinf e_asin.o: 00000000 T asin
要查看编译器使用的库路径以及默认情况下加载的库,可以使用-v选项调用gcc。再次在我的系统上,给出以下输出。
GNU assembler version 2.15 [FreeBSD] 2004-05-23 (i386-obrien-freebsd) using BFD version 2.15 [FreeBSD] 2004-05-23 /usr/bin/ld -V -dynamic-linker /libexec/ld-elf.so.1 /usr/lib/crt1.o /usr/lib/crti.o /usr/lib/crtbegin.o -L/usr/lib /var/tmp//ccIxJczl.o -lgcc -lc -lgcc /usr/lib/crtend.o /usr/lib/crtn.o
我担心我们会混合使用库和标头概念。
假设我们有一个库libmylib.a
,其中包含函数myfunc()
和一个相应的标头mylib.h
,用于定义其原型。在源文件" myapp.c"中,包含标头,可以直接包含标头,也可以包含包含标头的另一个标头。例如:
/* myapp.h ** Here I will include and define my stuff */ ... #include "mylib.h" ...
源文件如下所示:
/* myapp.c ** Here is my real code */ ... #include "myapp.h" ... /* Here I can use the function */ myfunc(3,"XYZ");
现在,我们可以编译它以获得myapp.o
:
gcc -c -I../mylib/includes myapp.c
注意,-I只是告诉gcc头文件在哪里,它们与库本身无关!
现在,我们可以将应用程序与真实库链接:
gcc -o myapp -L../mylib/libs myapp.o -lmylib
注意,-L
开关告诉gcc库在哪里,-l
告诉它将代码链接到库。
如果不执行此最后一步,则可能会遇到我们描述的问题。
可能还有其他更复杂的情况,但是从问题来看,我希望这足以解决问题。
听起来我们好像没有在库中编译.c文件来生成.o文件。链接器将在通过编译库而产生的.o文件中寻找原型的实现。
构建过程会编译库.c文件吗?
如果实际上只是源代码,为什么将它称为"库"?
发布makefile,以及我们要调用的库函数。即使是简单的gcc makefile,通常也有这样的一行:
LIBFLAGS =-lc -lpthread -lrt -lstdc++ -lShared -L../shared
在这种情况下,这意味着链接标准C库等