链接选项-rpath的一个问题记录
问题简述
大概是这么一个情况,有一个过去已经写好的程序,这个程序用于处理网络通信,接收一些操作指令。具体的指令操作通过运行时加载动态库的形式进行扩展。(类似于net-snmp二次开发的一种形式)
问题是这样的,用于扩展功能的动态库,其本身又链接了一系列的动态库,这些库的位置与这个扩展用的动态库存放的位置是相对的。大概如下
程序 program | | 运行时加载(dlopen/LoadLibrary等) sodir/lib1.so | 相对路径存放 sodir/lib2/lib2.so
问题在于编译lib1.so
的时候,并不知道将来lib1.so
会存放于相对程序program
的工作路径的什么位置,导致不知道lib2.so
的位置在哪里。
如果链接的时候直接使用-rpath=./lib2
的话,这就需要lib2.so
在程序工作路径下的lib2
目录下方可,因为运行时加载路径并不是相对于lib1.so
而是相对于program
的。
这里还有一个问题,那就是如果lib2.so还有依赖,且生成lib2.so的时候没有使用-rpath选项
那就比较麻烦了,因为没有相对路径,必须放置在系统默认的so搜索路径或者在/etc/ld.so.conf
中添加。
假定lib2.so
依赖lib3.so
,那么即便是将lib3.so
加入到lib1.so
的链接选项中,也不会链接进去(很早之前的时候ld程序应该是把所以的都链接进去的,不管有没有使用,但最近我测试都是没有的,应该是默认使用--as-needed
选项),所以查找的时候没有使用lib1.so
中指定的runpath
路径。这个可以使用readelf -d lib1.so
命令查看。这个可以给ld
添加--no-as-needed
选项来强制链接所有指定的库,而不是仅仅链接需要的。
解决办法
当前没有好的解决办法。
一个简单的方法是写一个libwarp
来包装一下lib1
,在libwarp
中先设置一下LD_LIBRARY_PATH
环境变量(设置自身进程的没有用,要设置父进程或全局的(加载自身进程的进程)),加上自身所在的路径(dladdr
/GetModulePath
获取),然后再使用ldopen
的方式加载lib1
。而程序则按照原来加载lib1.so
的方式加载libwarp.so
即可。
这种方式实现起来比较麻烦,需要把自己终结之后重新启动以使环境变量生效,不如直接写一个脚本去运行program
,在这之前去设置LD_LIBRARY_PATH
环境变量。
这个问题大概可以用下面的代码来表示(就不详细叙述了)
https://files.cnblogs.com/files/oloroso/sopath.tar.gz
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理