Linux静态库(含依赖库)实战与简析

来源:互联网 发布:格斗术软件 编辑:程序博客网 时间:2024/06/04 22:25

Linux静态库含有依赖关系时,事情就变得有些棘手了。

下面是举例假设用户目录下的工程目录如下:

~├─p1│      p1.c│      p1.h│├─p2│      p2.c│      p2.h│└─ptest       test.c
三个目录p1、p2、ptest,分别有源文件p1.c、p2.c、test.c 分别代表着三个工程。其中,ptest调用p2中的函数,p2又调用p1中的函数。

下面贴出源文件的内容:

p1:

//p1.hvoid myprint(void);

//p1.c#include<stdio.h>void myprint(void){        printf("I am p1's a.\n");}

p2:

//p2.hvoid myprint2(void);

//p2.c#include<stdio.h>#include"../p1/p1.h"void myprint2(void){        myprint();  //调用p1中的函数        printf("I am p2's a.\n");}

ptest:

//test.c#include "../p1/p1.h"#include "../p2/p2.h"int main(void){        myprint2();  //调用2中的函数。        return 0;}

下面将p1、p2都封装成静态库,供ptest工程调用:

p1:

编译,ar打包:

$gcc -c p1.c$ar cq libp1.a p1.o

p2:

$gcc -c p2.c$ar cq libp2.a p2.o

ptest:

$gcc test.c ../p2/libp2.a ../p1/libp1.a -o test
注意,上面p1、p2依赖库的顺序不能写错。

此时生成 test程序,运行:

$ ./testI am p1's a.I am p2's a.


-----------------------------俺是华丽的分割线-----------------------
从以上工程结构可以得出:

1、静态库的实质,就是将编译好的目标文件(.o)打包(使用ar)封装起来,并留有一个.h文件作为调用接口(interface),日后有其他文件若有调用,只要把接口文件include进来,在编译的时候,指出静态库路径即可。

2、当静态库有依赖关系时,在调用依赖者时,必须还要包含被依赖者的接口、库文件。如上面例子中,p2(依赖者)依赖于p1(被依赖者),ptest调用p2的时候,必须连p1也要包含进来才能编译成功。此处的"包含"意思指包含接口头文件和静态库路径。

3、库引用,ldd命令可以查看某个可执行文件的库引用情况,这里我检测一下ptest工程的可执行文件test:

$ ldd test        linux-gate.so.1 =>  (0x0056e000)        libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0x00110000)        /lib/ld-linux.so.2 (0x007cb000)
可以看到它所引用的都是系统库,事实是:我们引用的两个库libp1.a 和libp2.a由于是静态库的缘故,故而在编译的时候,直接加载到程序里,合并了。所以看不到它们的引用。这就是静态库的特点(也可以说是与动态库的区别)。

0 0
原创粉丝点击