Linux下有静态链接库和动态链接库两种,本文就其区别,生成静态库动态库的有关gcc命令以及生成静态库动态库的方法作一介绍。
一.静态库和动态库的区别:
1.静态链接库的后缀名是.a,动态链接库的后缀名是.so;
2.静态链接库是指程序在编译链接的过程中所有使用到的函数库都会被加载到目标文件中,这种处理方式的优点是编译后的执行程序不需要外部函数库的支持,同样的这种处理方式既是它的优点,同时也是它的缺点,那就是如果静态函数库改变了此时的程序就必须重新进行编译链接。
3.动态库相对静态函库来说动态库的体积相对较小,是因为动态函数库在编译的时候并没有加载到目标文件中。由于动态函数库没有整合到你的程序中,是在程序运行时动态的申请和调用,所以程序的运行环境中必须存在相应的库。因为动态函数库并不影响你的程序,所以它的升级相对简单。
二.生成静态库动态库的有关gcc命令
要明白linux下是如何生成静态库和动态库的,首先需要了解gcc的常见命令:
1).无选项编译链接。eg:gcc test.c //会默认生成a.out可执行程序
2).-E:进行预处理和编译,生成汇编文件 eg:gcc -E test.c //会生成test.i文件
3).-S:进行预处理,编译,汇编等步骤 eg:gcc -S test.c //生成test.s文件
4).-c:直接生成二进制目标文件,eg:gcc -c test.c //生成test.o文件
5).-o:对生成的目标进行重命名,eg:gcc -o test test.c 或者是 gcc test.c -o test
//生成test的可执行文件,这个可执行文件紧挨着参数'-o'
6).-g:在编译的时候用于debug调试信息,用于gdb调试
7).-share:此选项尽量的使用动态库,所以生成文件比较小,但是必须是系统存在动态库。
8).-shared:生成共享目标文件,通常用在建立共享库。
9).-static:链接时使用静态链接,但是要保证系统中有静态库。
10).-llibrary:定制编译的时候使用的库 ,eg:gcc -lpthread test.c //在编译的时候要依赖pthread这个库
11).-Ldir:定制编译的时候搜索库的路径。如果是自己编写的库,可以用它来定制搜索目录,否则编译器只在标准库目录里面找,dir就是目录的名字。
12).-C:在预处理的时候不删除注释信息,一般和-E使用。
13).-pipe:使用管道代替编译中的临时文件,eg:gcc -pipe -o test test.c
14).-include file:包含某个代码,相当于在文件中加入#include,eg:gcc test -include /root/file.h
15).-Idir:当你使用#include”file”的时候,会先到你定制的目录里面查找
16).-I-:取消前一个参数的功能。一般在-Idir之后使用
三.如何生成静态库和动态库
1.生成静态库
静态库的操作工具 gcc和ar命令,它的产生分两步:
1).由源文件编译生成一堆".o"文件,每个.o文件中都包含这个编译单元的符号表
2).ar命令将很多.o文件生成.a文件,生成静态库,eg:ar cr xxx.a xxx.o将创建静态库
详细操作如下:
-
(1)把代码编译为目标文件形式:
# gcc -c liberr.c -o liberr.o
(2)使用工具ar创建一个存档文件:
# ar rcs liberr.a liberr.o
(3)编译程序时把程序和liberr.a链接起来:
# gcc errtest.c -o errtest -static -L./ -lerr
2.生成动态库
无论是静态库和动态库都是由一大堆.o文件生成的,在上述gcc命令的简介中我们知道利用-shared可以创建动态库。eg;gcc -shared -fPCI -o xxx.so xxx.o.
"PCI"命令行标记告诉GCC产生的代码不要包含对函数和变量具体内存位置的引用,这是因为现在还无法知道使用该消息代码的应用程序会将它连接到哪一段内存地址空间。这样编译出的xxx.o可以被用于建立共享链接库。
实现动态库的方法:
(1)首先编译目标文件:
# gcc -fPIC -g -c liberr.c -o liberr.o
(2)然后链接库:
#gcc -g -shared -Wl,-soname,liberr.so -o liberr.so.1.0.0 liberr.o -lc
(3)把生成的动态库liberr.so.1.0.0拷贝到/usr/lib目录里:
#cp liberr.so.1.0.0 /usr/lib
(4)进入/usr/lib目录建立两个链接文件:
#cd /usr/lib
#ln -s liberr.so.1.0.0 liberr.so.1
#ln -s liberr.so.1.0.0 liberr.so
(5)编译程序时和动态库链接起来:
#gcc errtest.c -o errtest -lerr
如何查看一个可执行程序依赖于哪些库?
ldd+文件名,可以查看一个可执行程序依赖的共享库