gcc 使用-Wl,-rpath 解决 so 库版本冲突

马谦马谦马谦 Linux评论2,979字数 1291阅读 4 分 18 秒阅读模式

一、 问题描述

最近工作中遇到了一个问题:项目需要合入其他部门的模块,但是其中的一个共用共享库被更新了。因为项目很大,如果直接在我们的环境中替换更新这个库,很有可能会影响到其他模块。祖传的代码流传了差不多 20 年,涉及的模块也十分之多,贸然升级的风险很难评估。但是不替换这个库第三方模块又跑不起来,一度头痛。

刚开始是想到了以下几 个方法:

1. 设置 LD_LIBRARY_PATH 环境变量,修改查找路径的优先级。

2. 修改 so 库名

对于第一种方法是有效的:在程序目录下加个 lib 目录,然后 export LD_LIBRARY_PATH 把当前路径放到第一搜索顺序,能解决这个问题。但是,环境变量时当前所有程序共享的,其他程序的搜索目录也是这里第一,所以这里的结果就和直接升级库没有区别。同样,修改/etc/ld.so.conf 的原理也是一样。

第二种方法本来是认为比较靠谱的,但是测试发现共享库并不是根据文件名来的,修改库名无效。 so 库内部还有个真实的名字,可以通过 readelf -d lib*.so 来查看:

所以上面两种方法就被排除了,后面查了很久也没有找到合适的办法,崩溃。。。

最后去请教大佬就被告知了可以使用 -Wl,-rpath 选项来解决这个问题,试了一下确实可以。

二、-Wl,-rpath 和-Wl,-rpath-link 选项

2.1 -Wl,-rpath

加上 -Wl,-rpath 选项的的作用就是指定 「程序运行时」 的库搜索目录,是一个链接选项,生效于设置环境变量之前。

我们已经知道,共享库的查找顺序为:

1. LD_LIBRARY_PATH 环境变量的目录

2. ld.so.conf 高速缓冲文件中的目录

3. 系统的默认库目录如 /lib, /lib64

-Wl,-rpath 可以让程序在第一步搜索之前先搜索它所指定的目录,通过一个例子来说明:

add.h 和 add.c 用于生成一个 so 库,实现了一个简单的加法,main.c 中引用共享库计算 1 + 2:

编好后运行依赖库:

可以看到,libadd.so 这个库是没有找到的,程序也无法运行,要运行它必须要把当前目录加到环境变量或者库搜索路径中去。

但是如果在链接的时候加上 -Wl,-rpath 选项之后:

依赖库的查找路径就找到了,程序能正常运行。

2.2 -Wl,rpath-link

-Wl,rpath-link 是设置编译链接时候的顺序,例如 app 运行依赖 libadd.so,但是 libadd.so 又依赖 libadd_ex.so,rpath-link 就是指定 libadd_ex.so 的路径。和 -Wl,rpath 相比工作的时间不同,一个在链接期间,一个在运行期间。

三、其他相关

程序从编译到链接的过程分析

linux 静态库和动态库的使用方法

linux 程序运行找不到共享库的解决方法

 
马谦马谦马谦
  • 本文由 马谦马谦马谦 发表于 2018 年 9 月 23 日 20:59:44
  • 转载请务必保留本文链接:https://www.dyxmq.cn/linux/gcc-option-wl-rpath.html
CentOS5 YUM源 CentOS

CentOS5 YUM 源

centos5 已停止了维护,国内大部分的源也停止维护,找了很久都没有找到可用的源。最后才发现,centos 早期的源都已经 vault.centos.org 网站下,国内的镜像源也都改成了 centos-va...
openssl命令的用法 Linux

openssl 命令的用法

openssl 是目前使用最广泛的 ssl 库之一,除了提供全面的 ssl 加密库以外,还提供了一些基础的命令行工具用于测试,目前绝大多数的软件都是使用 openssl 库来进行 ssl 交互,很多系统默认都自带了 op...
匿名

发表评论

匿名网友
:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:
确定

拖动滑块以完成验证