1. 问题描述
目录结构如下:
编译build.sh
脚本为:
gcc main.c -L. -ltlcpsocket -o main
编译后
运行可执行程序main,提示找不到动态链接库
默认情况下Linux系统到/lib
或 /lib64
下寻找链接库,如果连接库在这两个地方没有那么就会出现这个问题,即便我们的动态链接库与可执行程序位于同一个目录内。
我们使用gcc的-L
参数指定了编译时的连接库所在目录位置,因此程序可以顺利编译。
在运行时,程序启动时需要加载动态链接库,上述问题就是在运行时找不到链接库导致。
2. 查看程序链接库
通过ldd
查看可执行程序链接库
ldd [可执行程序名称]
例如:
可以看到这里的libtlcpsocket.so
链接库提示没有找到,其几个链接库都找到对应的内存地址。
通过readelf
查看可执行程序链接库详细情况
readelf -d [可执行程序]
可以看到这里的链接库都是没有路径的只有链接库名称。
3. 解决方案
gcc设置添加了运行时的链接库查询位置,使用 **-Wl,-rpath,**参数
gcc main.c -Wl,-rpath,'$ORIGIN'/. -L. -ltlcpsocket -o version
注意:
-Wl,-rpath,
后的路径为$ORIGIN
+.
,表示./.
,$ORIGIN
代表了可执行文件所在的地址,程序在编译时该符号会保留在可执行文件,运行时替换为具体路径。 [ 1 ] ^{[1]} [1]
编译后我们再通过ldd
和 readelf
查看
可以看到ldd提示已经可以找到所有的链接库。
在readelf
中增加了RUNPATH
条目表示运行时动态库的路径。
4. 参考文献
[1]. csdn . 指定运行时动态库搜索位置 . 元口 . 2020.09 . https://blog.csdn.net/qq_41230365/article/details/108721527
[2]. 简书 . 使用rpath解决指定动态库链接目录问题 . 鱼大鱼 . 2019.11 . https://www.jianshu.com/p/83503c0c4d3d