最近自己的项目中遇到一个问题:
编译一个动态库,动态库中使用了静态库的函数如下图所述 问题来了怎么编译最终得到一个带有静态链接的动态库libxxx.so? 生成静态库libxxx1 gcc -o xxx1.o -c xxx1.c ar -r xxx1.o libxxx1.a 生成静态库libxxx2gcc -o xxx2.o -c xxx2.c ar -r xxx2.o libxxx2.a 生成静态库libxxx3gcc -o xxx3.o -c xxx3.c ar -r xxx3.o libxxx3.a 生成动态库libxxx.so gcc -o libdynamic.so dynamic.o -shared -fPIC -L. -lxxx1 -lxxx2 -lxxx3gcc报错: 于是网上看了一篇文章解决方案是把静态库编译的过程加上了-fPIC和-shared选项。然后进行编译和链接再生成动态库被程序所使用。最为关键的一些变化为:回到以上静态库生成指令中 gcc -o xxx1.o -fPIC -shared -c xxx1.c gcc -o xxx2.o -fPIC -shared -c xxx2.c gcc -o xxx3.o -fPIC -shared -c xxx3.c 这样一来不禁要问:既然是静态库,加上了这两选项编译出来的结果到底是动态库还是静态库?那原本的问题岂不是变为动态库链接动态库了? 之后结合个人调试和总结看看有没有其他方法可以解决此类问题(动态库调用静态库中的函数) 1,静态库被其他程序调用,编译结果为把静态库的函数“拷贝”到目标程序中。 2,而动态库这没有相关的“拷贝”动作。只是做了一个链接,程序运行时会自动的到默认路径下搜索动态库,并且调用执行。 明确以上两个概念之后再来看看实际的情况 代码转自: http://www.cnblogs.com/nobugtodebug/archive/2012/11/07/e6cd72c67b3dd843f40d7ce919f7336a.html
以上代码中很清楚的可以看到如下实时。生成一个动态库,这个动态库依中的函数实现依赖于一个静态库。满足要分析的应用场景。那么为什么按照博客中描述的方法操作gcc,但是结果和我预期的有出入呢? 问题在于两点: 第一点:使用 -fPIC -shared 两个选项编译了静态库,这个库还是静态属性吗?假设一个静态库已经被其他软件和工程广泛使用了,现在修改了这个静态库属性后是不是会影响其他的软件? 第二点:为什么不能编译出我们预期效果的动态库? 看看博客中的操作: gcc -o static.o -c static.c ar -r libstatic.a static.o 做个静态库libstatic.a,然后只编译dynamic.c不链接。 接着使用 gcc -o libdynamic.so -shared -fPIC -L. -lstatic dynamic.o 生成一个名为libdynamic.so动态库。 一切准备就绪,要用测试软件测试了 gcc main.c -L. -ldynamic -o main 链接错误 我们分析一下原因: 使用命令 nm 查看可执行程序的符号和函数等 nm libdynamic.so 00001f18 a _DYNAMIC 这个U 后面的函数正是静态库中想要使用的函数,前面这个U 表示:该符号在当前文件中是未定义的,即该符号的定义在别的文件中。 看来这个动态库名字是对的,但是内容还不全。怎么办?修改gcc命令如下: gcc -o libdynamic1.so -shared -fPIC dynamic.o -L. -lstatic 这条命令是告诉gcc先要把dynamic.o这个编译后未链接的文件中没有定义的符号链接先处理掉,也就是把U开始的函数先链接。随后再把这个未连接的文件作为动态库来处理,最后生成一个动态库。 有了动态库libdynamic1.so,再使用nm看看输出结果: 00001f18 a _DYNAMIC 这下这个函数变为 属性变为T了,T的含义是:该符号位于代码区text section。 使用命令:gcc main.c -L. -ldynamic1 -o main 执行main后一切都有了,静态库中的函数信息最后是动态库中的信息。 总结: gcc使用的时候带有参数,这些参数的先后顺序直接导致了编译的结果。特别是在做库文件的过程中,有时候看似编译没有报错,但是运行时候就会有问题。这些问题多数出现在链接阶段。 文中有不足之处请大家指点,谢谢 |
|