1. 为何会出现undefined reference to 'xxxxx'错误?html
首先这是连接错误,不是编译错误,也就是说若是只有这个错误,说明你的程序源码本身没有问题,是你用编译器编译时参数用得不对,你没有指定连接程序要用到得库,好比你的程序里用到了一些数学函数,那么你就要在编译参数里指定程序要连接数学库,方法是在编译命令行里加入-lm。数据库
2.-l参数和-L参数编程
-l参数就是用来指定程序要连接的库,-l参数紧接着就是库名,那么库名跟真正的库文件名有什么关系呢?就拿数学库来讲,他的库名是m,他的库文件名是libm.so,很容易看出,把库文件名的头lib和尾.so去掉就是库名了。编程语言
-L参数跟着的是库文件所在的目录名。再好比咱们把libtest.so放在/aaa/bbb/ccc目录下,那连接参数就是-L/aaa/bbb/ccc -ltest另外,大部分libxxxx.so只是一个连接函数
3. -include和-I参数测试
-include用来包含头文件,但通常状况下包含头文件都在源码里用#include xxxxxx实现,-include参数不多用。-I参数是用来指定头文件目录,/usr/include目录通常是不用指定的,gcc知道去那里找,可是若是头文件不在/usr/include里咱们就要用-I参数指定了,好比头文件放在/myinclude目录里,那编译命令行就要加上-I/myinclude参数了,若是不加你会获得一个"xxxx.h: No such file or directory"的错误。-I参数能够用相对路径,好比头文件在当前目录,能够用-I.来指定ui
4.几个相关的环境变量spa
PKG_CONFIG_PATH:用来指定pkg-config用到的pc文件的路径,默认是 /usr/lib/pkgconfig,pc文件是文本文件,扩展名是.pc,里面定义开发包的安装路径,Libs参数和Cflags参数等等。.net
CC:用来指定c编译器。命令行
CXX:用来指定cxx编译器。
LIBS:跟上面的--libs做用差很少。
CFLAGS:跟上面的--cflags做用差很少。
CC,CXX,LIBS,CFLAGS手动编译时通常用不上,在作configure时有时用到,通常状况下不用管。
环境变量设定方法:export ENV_NAME=xxxxxxxxxxxxxxxxx
==============================================================================
[相关介绍]
应用程序(Applications)
应用程序一般都有固定的文件夹,系统通用程序放在/usr/bin,往后系统管理 员在本地计算机安装的程序一般放在/usr/local/bin或者/opt文件夹下。除了系统程序外,大部分我的用到的程序都放在/usr /local下,因此保持/usr的整洁十分重要。当升级或者重装系统的时候,只要把/usr/local的程序备份一下就能够了。
一些其余的程序有本身特定的文件夹,好比X Window系统,一般安装在/usr/X11中,或者/usr/X11R6。GNU的编译器GCC,一般放置在/usr/bin或者/usr/local/bin中,不一样的Linux版本可能位置稍有不一样。
头文件(Head Files)
在C语言和其余语言中,头文件声明了系统函数和库函数,而且定义了一些常量。对于 C语言,头文件基本上散落于/usr/include和它的子文件夹下。其余的编程语言的库函数分布在编译器定义的地方,好比在一些Linux版本中,X Window系统库函数分布在/usr/include/X11,GNU C++的库函数分布在/usr/include/g++。这些系统库函数的位置对于编译器来讲都是“标准位置”,即编译器可以自动搜寻这些位置。
若是想引用位于标准位置以外的头文件,咱们须要在调用编译器的时候加上-I标志,来显式的说明头文件所在文件夹。好比,
$ gcc -I/usr/openwin/include hello.c会告诉编译器除了标准位置外,还要去/usr/openwin/include看看有没有所需的头文件。详细状况见编译器的使用手册(man gcc)。
库函数(Library Files)
库函数就是函数的仓库,它们都通过编译,重用性不错。一般,库函数相互合做,来完成特定的任务。好比操控屏幕的库函数(cursers和ncursers库函数),数据库读取库函数(dbm库函数)等。
系统调用的标准库函数通常位于/lib以及/usr/lib。C编译器(精确点说,链接器)须要知道库函数的位置。默认状况下,它只搜索标准C库函数。
库函数文件一般开头字母是lib。后面的部分标示库函数的用途(好比C库函数用c标识, 数学库函数用m标示),小数点后的后缀代表库函数的类型:
去/usr/lib看一下,你会发现,库函数都有动态和静态两个版本。
与头文件同样,库函数一般放在标准位置,但咱们也能够经过-L标识符,来添加新的搜索文件夹,-l指定特定的库函数文件。好比
$ gcc -o x11fred -L/usr/openwin/lib x11fred.c -lX11
上述命令就会在编译期间,连接位于/usr/openwin/lib文件夹下的libX11函数库,编译生成x11fred。
静态连接库(Static Libraries)
最简单的函数库就是一些函数的简单集合。调用库函数中的函数时,须要在调用函数中include定义库函数的头文件。咱们用-l选项添加标准函数库以外的函数库。
静态函数库,也称为archives ,一般之后缀.a结尾。
咱们也能够建立维护本身的静态连接库函数。下面就介绍一下:
咱们建立的库函数包括两个函数,而后在后面的实例中调用其中之一。两个库函数名字分别是fred和bill,仅仅是输出字符串。
2. 接下来,咱们将这两个源文件编译为两个独立的目标文件。这里要用到GCC的-c选项。命令以下所示:
$ gcc -c fred.c bill.c
$ ls *.o
bill.o fred.o
3. 而后,写一个调用bill的测试函数,在此以前,最好为库函数创建一个头文件。头文件中有对库函数的声明。若是其余函数要调用库函数,必须在其代码中包含 头文件。也能够在fred.c 和bill.c中包含该头文件,有利于编译器发现错误。头文件lib.h的内容以下所示:
4. 测试函数program.c比较简单,代码以下:
5. 如今咱们能够编译测试一下程序了:
$ gcc -c program.c
$ gcc -o program program.o bill.o
$ ./program
bill: we passed Hello World
6. 接下来,咱们要建立一个函数库。利用ar函数创建归档文件(archive),而后将目标文件加入其中。$ ar crv libfoo.a bill.o fred.o
a - bill.o
a - fred.o
7. 如今可使用函数库中的函数了。咱们用-l指定函数库的名字。由于该函数库没有在标准文件夹中,咱们还须要用-L将当前文件夹"."添加到搜索路径中。编译命令以下所示:
$ gcc -o program program.o -L. -lfoo
共享连接库(Shared Libraries)
静态连接库的一个缺点是,若是咱们同时运行了许多程序,而且它们使用了同一个库函数,这样,在内存中会大量拷贝同一库函数。这样,就会浪费不少珍贵的内存和存储空间。使用了共享连接库的Linux就能够避免这个问题。
共享函数库和静态函数在同一个地方,只是后缀有所不一样。好比,在一个典型的Linux系统,标准的共享数序函数库是/usr/lib/libm.so。
当一个程序使用共享函数库时,在链接阶段并不把函数代码链接进来,而只是连接函数的一个引用。当最终的函数导入内存开始真正执行时,函数引用被解 析,共享函数库的代码才真正导入到内存中。这样,共享连接库的函数就能够被许多程序同时共享,而且只需存储一次就能够了。共享函数库的另外一个优势是,它可 以独立更新,与调用它的函数绝不影响。
原文出处:http://blog.chinaunix.net/uid-26959037-id-3542739.html