Linux 使用 -Wl,rpath设置动态库的指定搜索路径

工作中有时会遇到可执行程序运行时使用指定目录下的动态库,若是直接修改环境变量,可能会对其他程序产生影响,因此可以在编译时使用-Wl,rpath来指定运行时路径。

比如 /home/lib 下存在 libtest.so , /home/test 下存在 test.c 和 libtest.so文件,编译出的可执行文件依赖动态库 libtest.so

/home
  |--lib
       -libtest.so  

  |--test
       - test.c
       - libtest.so 

假设想让可执行文件运行时使用lib下的动态库,可以使用如下命令

gcc -o test test.c -L./ libtest.so -Wl,-rpath='$ORIGIN/../lib'

其中 -L./ libtest.so 表示编译时使用当前目录下的 libtest.so 进行编译
-Wl,-rpath=’$ORIGIN/…/lib’ 表示运行可执行文件时,从 …/lib 中寻找所需要的动态库。

可以使用ldd命令查看可执行程序的依赖

# ldd test
  libtest.so  => /home/test/../lib/libtest.so

通过 ldd 命令可知,test 运行时使用的动态库路径为 /home/test/…/lib

还有一种情况是可执行程序test使用的动态库为 libtest.so 而编译时使用的是libtest.so.1.1

比如目录就结构如下

/home
  |--lib
       -libtest.so.1.1  

  |--test
       - test.c
       - libtest.so.1.1

编译生成可执行文件

gcc -o test test.c -L./ libtest.so.1.1 -Wl,-rpath='$ORIGIN/../lib'

运行 ldd 时发现找不到动态库 libtest.so

# ldd test
  libtest.so  => not found 

原因是运行test时他需要的动态库的名字为libtest.so 而 lib 中存放的是libtest.so.1.1, 名字不一样,因此找不到动态库。

解决办法

1、可以把 lib 下的 libtest.so.1.1 名字改为 libtest.so

2、也可以在 lib 下创建一个 libtest.so.1.1 的软连接

# cd lib
# ln -s libtest.so.1.1 libtest.so
# ls
 libtest.so   libtest.so.1.1

# ldd test
   libtest.so  => /home/test/../lib/libtest.so

附:
我们编译程序时会常常遇到如下你几个参数
-I (大写的i)
-L (大写l)
-l (小写l)
接下来对这几个参数进行简单的讲解。

先举个例子:

gcc -o test test.c -I /home/test/include -L/home/test/lib -ltest
编译test时:
-I /home/test/include 表示将 /home/test/include 目录作为第一个寻找头文件的目录,其寻找的顺序是:

/home/test/include --> /usr/include --> /usr/local/include

-L/home/test/lib 表示将 /home/test/lib 目录作为第一个寻找库文件的目录,其寻找的顺序是:

/home/test/lib --> /lib -> /usr/lib --> /usr/local/lib

-ltest 表示在上面的lib的路径中寻找 libtest.so 动态库文件(如果 gcc 编译选项中加入了“-static”表示寻找 libtest.a 静态库文件),程序链接的库名是test。

-l参数就是用来指定程序要链接的库,-l参数紧接着就是库名,那库名跟真正的库文件名有什么关系呢?
比如数学库,他的库名是 m,他的库文件名是 libm.so,把库文件名的头 lib和尾 .so 去掉就是库名了。

比如当我们使用第三方提供的库名字叫libtest.so,那么我们只要把 libtest.so拷贝到 /usr/lib 里,编译时加上 -ltest 参数,我们就能用上 libtest.so 库了(当然要用 libtest.so 库里的函数,我们还需要与 libtest.so 配套的头文件)。

对于放在 /lib 和 /usr/lib 和 /usr/local/lib 里的库直接用-l参数就能链接了,但如果库文件没放在这三个目录里,而是放在其他目录里,若此时我们只用-l参数的话,链接还是会出错,出错信息大概是:
/usr/bin/ld: cannot find -lxx

也就是说链接程序ld在那3个目录里找不到 libxx.so,这个时候另外一个参数-L就派上用场了。

比如我们使用 test 库 它放在 /usr/test/lib 目录下,我们编译时就要用
-L/usr/test/lib -ltest 参数,-L 参数跟着的是库文件所在的目录名。

再比如我们把libtest.so放在 /var/bbb 目录下,那链接参数就是
-L/var/bbb -ltest

另外,大部分libxx.so只是一个链接,比如libm.so它链接到 lib/libm.so.6,/lib/libm.so.6 又链接到 /lib/libm-2.3.2.so,

如果没有这样的链接,我们运行可执行程序时可能还是会出错,因为 ld 只会找libxx.so。

所以如果你要用到 xx 库,而只有 libxx.so.x 或者 libxx-x.x.x.so 时,做一个软链接就可以了。

命令如下:
ln  -s  libxx-x.x.x.so  libxx.so

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值