linux下动态库编译的依赖问题
这里主要是想试验一下,对一个具有多层嵌套的动态库进行编译时,是否要把最底层的库也包含进来的问题,结论是:只要直接依赖的库名称,不需要最底层库名称。
一,目录结构
ZZZ
├── add
│ ├── add.cpp
│ └── add.h
├── calc
│ ├── calc.cpp
│ └── calc.h
├── main
├── main.cpp
├── pkg
│ ├── pkg.cpp
│ └── pkg.h
└── sub
├── sub.cpp
└── sub.h
二,文件内容:
1, add模块内容:
[add.cpp ]
int add(int a, int b)
{
return a+b;
}
[add.h]
extern int add(int a, int b);
2, sub模块内容:
[sub.cpp]
int sub(int a, int b)
{
return a-b;
}
[sub.h]
extern int sub(int a, int b);
3, calc模块内容:
[calc.cpp]
#include "calc.h"
#include "add.h"
#include "sub.h"
#include <stdio.h>
void func(int a, int b)
{
int result = add(a,b);
printf("%d+%d=%d\n",a, b, result);
result = sub(a,b);
printf("%d-%d=%d\n",a, b, result);
}
[calc.h]
extern void func(int a, int b);
4, pkg模块: 对calc模块进行了简单封装
[pkg.cpp]
#include "pkg.h"
#include "calc.h"
void pkg_func()
{
func(100, 80);
}
[pkg.h]
extern void pkg_func();
5, main程序:调用pkg模块
[main.cpp]
#include "pkg.h"
int main()
{
pkg_func();
return 0;
}
三,编译:
ZZZ目录下:(单功能模块)
1,[add模块]
g++ -g -shared -fPIC add/add.* -o libadd.so
2, [sub模块]:(单功能模块)
g++ -g -shared -fPIC sub/sub.* -o libsub.so
3, [calc模块]: clac模块依赖于add和sub模块,用到了两者的头文件,并调用了接口
错误:g++ -g -shared -fPIC -Iadd -Isub calc/calc.* -o libcalc.so
(编译虽然可以过,但是参数不足,这种遗漏依赖库的问题现在不解决,在编译嵌套它的上层库时就会暴露出来)
正确:g++ -g -shared -fPIC -Iadd -Isub -ladd -lsub -L. calc/calc.* -o libcalc.so
4, [pkg模块]:封装calc模块
错误:g++ -g -shared -fPIC -Icalc pkg/pkg.* -o libpkg.so
正确:g++ -g -shared -fPIC -Icalc -lcalc -L. pkg/pkg.* -o libpkg.so
5, [main程序]
g++ -g -Ipkg -lpkg -L. main.cpp -o main
四,试验
我们知道各模块的依赖关系:pkg->calc->add+sub,让我们慢慢分析,通过3,4步的编译参数我们可以看出:
编译链接某个so的时候,系统并不检查接口是否可以导出,而只是检查编译是否通过。所以编译参数只包含依赖库的文件名是可以通过,但并不保证是正确的。(制作动态库的时候,到底有没有链接这个过程?,否则为什么在第一层调用库的时候就不报错呢)
1)g++ -g -Ipkg main.cpp -o main
/tmp/ccjKIuei.o: In function `main':
/home/TEST/ZZZ/main.cpp:5: undefined reference to `pkg_func()'
A: main.cpp里面没有找到pkg_func接口,没包含库名称怎么可能找得到接口呢?
2) g++ -g -Ipkg -lpkg main.cpp -o main
/usr/bin/ld: cannot find -lpkg
collect2: ld 返回 1
A: 没有找到库名,需要指定库目录
3)g++ -g -Ipkg -lpkg -L. main.cpp -o main
/tmp/cc4JknbM.o: In function `main':
/home/TEST/ZZZ/main.cpp:5: undefined reference to `pkg_func()'
./libpkg.so: undefined reference to `func(int, int)'
collect2: ld 返回 1
A: libpkg.so里没有找到func接口,说明libpkg.so库在编译时没有包含依赖库名称,执行第4步的正确编译命令。
4)g++ -g -Ipkg -lpkg -L. main.cpp -o main
/tmp/ccGpm3HQ.o: In function `main':
/home/TEST/ZZZ/main.cpp:5: undefined reference to `pkg_func()'
libcalc.so: undefined reference to `sub(int, int)'
libcalc.so: undefined reference to `add(int, int)'
collect2: ld 返回 1
A: libcalc.so里没找到add,sub接口,说明libcalc.so时在编译时没有包含依赖库名称,执行第3步正确编译命令。
5) g++ -g -Ipkg -lpkg -L. main.cpp -o main
100+80=180
100-80=20
五,引申:
现在要在main.cpp是需跨层调用add模块的add接口,需要做的操作是:
1)添加代码:main.cpp包含add.h头文件,增加add()函数代码,
2)添加编译选项:只需要添加-I选项即可,不需要再加-l选项的。
六,结论:
因为库具有叠加性,最上层库的接口中已经包含了中间层和最低层的导出接口了,这个可以使用ldd命令来查看。
所以在编译具有多层依赖的动态库时,你只需要包含当前库直接依赖的库名称即可,不需要再把它所依赖库的依赖库名称包含进来。以上面的例子来说,编译pkg模块库的时候,只需要把calc的库包含进来就行了。
linux下动态库编译的依赖问题的更多相关文章
- 谈谈Linux下动态库查找路径的问题 ldconfig LD_LIBRARY_PATH PKG_CONFIG_PATH
谈谈Linux下动态库查找路径的问题 ldconfig LD_LIBRARY_PATH PKG_CONFIG_PATH 转载自:http://blog.chinaunix.net/xmlrpc.ph ...
- 深入理解LINUX下动态库链接器/加载器ld-linux.so.2
[ld-linux-x86-64.so.2] 最近在Linux 环境下开发,搞了好几天 Compiler 和 linker,觉得有必要来写一篇关于Linux环境下 ld.so的文章了,google上搜 ...
- Linux下动态库生成和使用
Linux下动态库生成和使用 一.动态库的基本概念 1.动态链接库是程序运行时加载的库,当动态链接库正确安装后,所有的程序都可以使用动态库来运行程序.动态链接库是目标文件的集合,目标文件在动态链接库中 ...
- Linux 下动态库 / 静态库(依赖)
一. 依赖动态库的动态库 libfun.so依赖动态库libtest.so(libfun.so动态库里的函数intnothing()调用了libtest.so里的intmytest()函数),而mai ...
- Linux下动态库查找路径的问题
说到和动态库查找路径相关的问题,总体上可以分为两类: 第一类: 通过源代码编译程序时出现的找不到某个依赖包的问题,而如果此时你恰好已经按照它的要求确确实实.千真万确.天地良心地把依赖库给装好了, ...
- 谈谈Linux下动态库查找路径的问题
学习到了一个阶段之后,就需要不断的总结.沉淀.清零,然后才能继续"上路".回想起自己当年刚接触Linux时,不管是用源码包编译程序,还是程序运行时出现的和动态库的各种恩恩怨怨,心里 ...
- [转]谈谈Linux下动态库查找路径的问题
http://blog.chinaunix.net/uid-23069658-id-4028681.html 学习到了一个阶段之后,就需要不断的总结.沉淀.清零,然后才能继续“上路”.回想起自己当年刚 ...
- 转:谈谈Linux下动态库查找路径的问题
http://blog.chinaunix.net/uid-23069658-id-4028681.html 学习到了一个阶段之后,就需要不断的总结.沉淀.清零,然后才能继续“上路”.回想起自己当年刚 ...
- LINUX下动态库及版本号控制
针对同一动态组件的不同版本链接和加载. 一.概念 DLL HELL字面意思是DLL"灾难",是由于com组件(动态库)升级引起的程序不能运行的情况 ...
随机推荐
- windows条件下,Ping加上时间戳,并保存到文件,适用于测试网络
在c盘下面新建文件 ping.vbs 在 ping.vbs中输入代码如下: Dim args, flag, unsuccOut args="" otherout="&qu ...
- 快笑死,侯捷研究MFC的原因
与我研究VCL框架代码的原因一模一样:就是N年了,感觉自己还是没有掌握Delphi,惊叹别人各种各样神奇的效果,自己却不会,更不知为什么这样做,离高手的距离还有十万八千里.而且编程的时候,就像侯捷说的 ...
- TWinControl与TControl的覆盖函数(TWinControl对TControl的10个消息覆盖函数,17个覆盖函数,私有虚函数仍可多态)
手工找出来,对比一下,有助于VCL框架的理解.----------------------------------------------------------------------------- ...
- CentOS防火墙操作实例(启动、停止、开、闭端口)
注:防火墙的基本操作命令: 查询防火墙状态: [root@localhost ~]# service iptables status<回车> 停止防火墙: [root@localh ...
- 设置 Firewalld 防火墙控制对系统的访问
1.检查 server101 的网卡,记住第二个网卡的名称 [root@server101 ~]# nmcli device DEVICE TYPE STATE CONNECTION br0 brid ...
- java cache过期策略两种实现,一个基于list轮询一个基于timer定时
最近项目要引入缓存机制,但是不想引入分布式的缓存框架,所以自己就写了一个轻量级的缓存实现,有两个版本,一个是通过timer实现其超时过期处理,另外一个是通过list轮询. 首先要了解下ja ...
- DataGridView过滤区分大小写问题
DataTable上的过滤方法: 一.可以用DataTable.Select("条件"),返回DataRow[]格式的结果集. DataRow[] drArr = dt.Selec ...
- JSP列表形式显示数据库中的数据 OracleCachedRowSet 实例
现在数据库中有一张用户表,希望用户在jsp页面中输入用户名和密码以及 用户类型,在servlet中插入数据库后,在另一个jsp页面中把数据库中所有的用户名和类型都以列表的形式列出来 可以用Ora ...
- 利用SOLR搭建企业搜索平台 之——MultiCore
Solr Multicore 是 solr 1.3 的新特性.其目是一个solr实例,可以有多个搜索应用. 下面着手来将solr给出的一个example跑出来.这篇文章是基于<利用SOLR搭建企 ...
- How to install cacti With Nginx
转载于:https://github.com/blackyboy/Ubuntu-Linux-Stuffs/blob/master/How-to-install-Cacti-Monitoring-Ser ...