静态库(.a)与动态库(.so)
静态库:在编译过程中将库函数的代码直接加入到生成的可执行程序中,程序运行过程中不需要利用库函数。
静态库的东西都要以静态链接的方式来生成。由于代码就在可执行程序中,所以它执行起来比较快,但是,它造成了可执行程序的臃肿。
共享库(动态库):编译时,只是在生成的可执行程序中简单指定需要使用的库函数信息,在程序执行的时候才与函数建立映射关系。(接口,.so,不需要重新编译,所以升级快)。
创建静态库:
静态函数库是一组目标文件(*.o)的集合。一般,一个函数一个.o,以免造成浪费。
多个.o文件放到一块就成了一个库。
创建步骤:
1、生成.o文件 gcc -c add.c minus.c ------生成add.o和minus.o
2、打包 ar -crs libmath.a add.o minus.o
用gcc编译时:gcc -o exe test.c -L.(路径) -l math(名字) -I ../include/
有必要说一下ar这个函数:(不过这些都用得少!)
用途:创建和修改库函数,或从库函数提取目标文件。
主要参数:
-rs -----将目标文件加入到库中,并产生索引文件。
-ds -----将目标文件从库中删除,并产生索引文件。
-x -----不修改库文件,从库中提取列表中列出的目标文件。
假如libmath.a中有add.o和minus.o,现在我想把另外一个mod.o也加到libmath.a中,
ar -rs libmath.a mod.o这样mod.o就被加入到libmath.a库中了。
又如,我要从库中将mod.o提取出来,ar -x libmath.a mod.o
如果想删除libmath.a中的mod.o,则 ar -ds libmath.a mod.o
gcc编译时有一个容易忽略的顺序问题:
静态库不能先于原程序链接,这是因为开始时还没有任何未定义的符号,库中的内容不会被链入,
所以应该注意将静态库的使用(-l选项)都写在最后。
因为gcc扫描是有顺序的:
E U D
所有的.o集合 未定义符号集合 已定义的符号集合
如果全是.o而没有.a的话,顺序没影响:如,
gcc -o main.o add.o 和gcc -o add.o main.o 都可以编译过去。
有一个命令可以列出库中所包含的信息:nm -s libmath.a
创建共享库:
gcc -shared -fPIC -o libtest.so test1.o test2.o
编译使用了共享库的程序:
gcc -o exe -L.(路径) -ltest test.c
使用了共享库的程序,在运行时库路径的搜索问题:
1.拷贝动态库文件到/lib或/usr/lib去
$ cp libalg.so /usr/lib or $cp libalg.so /lib
2.在/etc/ld.so.conf 添加库的路径(/home/xxx/lib),然后执行ldconfig命令生效
3.改变环境变量LD_LIBRARY_PATH
$ export LD_LIBRARY_PATH=/home/xxx/lib/
4 在编译时指定库的搜索路径,
-Wl,-rpath=/home/xxx/lib (应该是库在系统中的绝对路径)
如:gcc -o exe test.c ./libtest.so -Wl,rpath,$PWD
注:建议使用后两种方法。
与库和路径相关选项:
-I dir 在dir这个目录寻找被include的文件
-L dir 在dir这个目录寻找被-l的库
-lname 链接库文件名为libname.a或libname.so的库
-fpic或-fPIC 产生位置无关的目标代码,以构造共享库(shared library),
即用于生成位置无关的共享库
-static 禁止与共享库链接,若没有,则优先选择共享库链接
-shared 产生共享库,在创建共享函数库时使用