linux 下 奇怪的 动态库 依赖问题

本文详细解析了在Linux环境下编译静态库和动态库时如何正确配置头文件和库文件的方法,特别是针对多库依赖场景给出了实用建议。

 转:http://fanwei51880.blog.163.com/blog/static/3240674020111145285375/

 

总结如下:
1)当你在编译生成静态库的时候, 只需要相应的依赖库库的头文件即可. 只有在你想生成so,或可执行文件 时, 才需要lib库.
   对于你没有用到的lib, 但是不包含又编译失败, 那么只包含其头文件即可.
2)如果你同时使用了多个库,而库之间又相互依赖,那么在链接是,把最底层的依赖库放在最右侧.否则可能会链接失败
3)如果我已经把最底层的库放在最后边了,还是链接失败怎么办?
请检查是否依赖了同名的其他的库. 自己查看链接库的路径


对1)的说明
如果你不用该so, 那么你就不要将他的lib放在你的makefile里面! 否则运行时会依赖该so的.
案例:

      我的cgi, cp到正式环境, 居然开始依赖 mysql的so, 奇怪, 我的项目中并无用到mysql. 然后,makefile中去掉mysql相关的 头文件, 以及lib, 却发现 没有mysql的头文件还编译不过去, 因为我用的另一个库tlib用到了mysql, fuck, 怎么办?

答案: 只把mysql的头文件 路径等加到 makefile里面, 这样gcc有了头文件至少可以编译过去. 然后, 在连接的时候, 由于你的代码并没有真正用到mysql, 所以不会去连接mysql相关的东东. 所以, 直接链接通过.

分析: 虽然tlib用到了mysql, 但是由于tlib是一个非常庞大的静态库, 其里面依赖的内容非常多, 而我只用到了tlib里面的一小部分功能(且不含mysql), 所以, 我只需把mysql头文件加上即可. 链接时时不会真正用到mysql的没有lib. 除非我用到tlib里面的相关mysql接口.


如果你想生成静态库:
linux下, 如果你的项目(是个静态库)的依赖某个库(不管动态库还是静态库), 当你在编译生成静态库的时候, 只需要相应的依赖库库的头文件即可.
(因为, linux的.a本身就是一堆.o的集合, .o也就是一堆cpp文件的编译结果, 并没有开始执行链接)
举例:
  libcomm.a 就是这样, 虽然依赖的很多的库, 比如html_template, mysql, MARKUPSTL, 但只需他们的头文件即可.
USED = \
       MARKUPSTL \
       NETCLIENTEX \
       HTML_TEMPLATE \
       TLIB \


INC  = \
    $(foreach i, $(USED), $(INC_$(i)))

#看到没, LIB 为空!!!
LIB  = 



如果你想生成so,或可执行文件 
1)那么你必须包含上你需要的lib, 而且, 如果你 通过 -lxxx, 那么gcc默认后首先尝试链接 xxx的动态库libxxx.so.1(libxxx.so.1是libxxx.so的符号链接文件, 并不是真正的libxxx.so, 但是会指向libxxx.so), 如果找不到libxxx.so.1,然后寻找xxx的静态库libxxx.a.
2)同时, 如果你没有用到某个lib的话, 一定不要包含其lib, 如果编译不通过, 最多只需包含其头文件即可.
就像我上面的案例一样, 没有用到mysql, 却包含而来mysql的lib, 导致在运行机上找不到 mysql.so 而运行失败, 去掉mysql的lib, 只保留mysql的 头文件, 可以链接过去, 并且可以正常运行.

2)如果你同时使用了多个库,而库之间又相互依赖,那么在链接是,把最底层的依赖库放在最右侧.否则可能会链接失败
  g++ -o $(target) liba libb libc
  如果liba 依赖libb, libb依赖libc, 那么请把libc放在最后面.
  如果 g++ -o $(target) liba libc libb会导致libb的链接失败. 
  有一种情况离开,liba也依赖libc,并且依赖关系和libb对libc的依赖的接口一样, 那么把libc放在中间不会报错,但最好不要这么做.
 
3)如果我已经把最底层的库放在最后边了,还是链接失败怎么办?
   检查是否连接到了相同名字的其他的库.  我又一次就是如此,系统系统中存在多个network的库, 虽然我把正确的network库放在了最后面,但是由于其他库包含路径下也有老的同名的network库,导致我链接失败.

库依赖的查看

使用ldd命令来查看执行文件依赖于哪些库。

该命令用于判断某个可执行的 binary 档案含有什么动态函式库。
[root@test root]# ldd [-vdr] [filename]
参数说明:
--version  打印ldd的版本号
-v --verbose  打印所有信息,例如包括符号的版本信息
-d --data-relocs  执行符号重部署,并报告缺少的目标对象(只对ELF格式适用)
-r --function-relocs  对目标对象和函数执行重新部署,并报告缺少的目标对象和函数(只对ELF格式适用)
--help 用法信息。

如果命令行中给定的库名字包含'/',这个程序的libc5版本将使用它作为库名字;否则它将在标准位置搜索库。运行一个当前目录下的共享库,加前缀"./"。

转载于:https://www.cnblogs.com/pengdonglin137/p/3471907.html

### Linux 下解决 'undefined reference to typeinfo for' 链接错误 在 Linux 环境下,当使用 G++ 编译程序时遇到 `'undefined reference to typeinfo for'` 错误,通常是因为链接器无法找到某些库函数或类定义的相关实现。这种问题可能由多种原因引起,例如缺少必要的库文件、不正确的链接顺序或者使用的标准库版本不匹配。 #### 原因分析 此类错误通常是由于以下几个原因之一引起的: 1. **未正确指定依赖库**:如果某个符号来自外部库,则需要显式告诉链接器该库的位置以及名称[^2]。 2. **链接顺序不当**:C++ 中的静态库链接具有严格的顺序要求。如果目标文件先于其所需的库被传递给链接器,则可能导致此错误[^4]。 3. **ABI 不兼容**:不同版本的标准库 (如 GCC 和 libstdc++) 可能存在 ABI 差异,这会引发类似的链接错误[^1]。 4. **头文件与实际库版本不符**:开发环境中安装了多个版本的相同库,而编译和链接阶段引用的是不同的版本[^3]。 #### 解决方法 以下是几种常见的解决方案: ##### 方法一:确认并添加缺失的库 确保所有必需的第三方库均已正确包含到项目构建配置中。对于 Oracle OCCI 库为例,应该通过 `-locci` 参数来引入它,并且还需要加上 `-lclntsh` 来支持底层 OCI 功能: ```bash g++ -o myapp main.cpp dbAccessor.o -I$ORACLE_HOME/include -L$ORACLE_HOME/lib -locci -lclntsh ``` ##### 方法二:调整库链接顺序 按照 C++ 的规则,在命令行上应将 `.o` 文件放在前面,随后才是它们所依赖的具体库名。这样可以避免因为解析次序而导致找不到符号的情况发生: ```bash g++ -o output file1.o file2.o -llibrary_name ``` ##### 方法三:升级工具链至最新稳定版 有时旧版本的 GNU Compiler Collection(GCC) 或者 Standard Template Library(STL) 实现存在问题,尝试更新整个开发环境可能会解决问题。可以通过以下方式检查当前 gcc 版本并与官方推荐保持一致: ```bash gcc --version sudo apt-get update && sudo apt-get install build-essential ``` ##### 方法四:强制重新生成 Makefile 或清理缓存 有时候残留的目标文件也可能导致奇怪的行为,因此建议彻底清除之前的中间产物再重试一次完整的构建流程: ```makefile clean: rm -rf *.o a.out all: clean g++ -Wall -O2 source_files.cc -o executable $(LIBRARIES) ``` ##### 方法五:验证动态加载路径设置 假如应用程序运行期间仍然报错提示找不到共享对象(.so),那么可能是 LD_LIBRARY_PATH 环境变量没有正确指向这些额外资源所在目录。临时测试可以用下面的方法执行脚本前预设好相应值: ```bash export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path/to/libs/ ./your_executable ``` ### 总结 综上所述,“undefined reference to typeinfo for” 类型的链接错误主要是由于遗漏必要组件或是操作失误造成。针对具体实例采取适当措施即可有效排除障碍。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值