工作中有时会碰到可执行程序运行时使用指定目录下的动态库,若是直接更改环境变量,可能会对其他程序形成影响,因而可以在编译时使用-Wl,rpath来指定运行时路径。
例如/home/lib下存在libtest.so,/home/test下存在test.c和libtest.so文件linux创建用户并指定目录,编译出的可执行文件依赖动态库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.solinux系统,把库文件名的头lib和尾.so除去就是库名了。
例如当我们使用第三方提供的库名子叫libtest.so,这么我们只要把libtest.so拷贝到/usr/lib里,编译时加上-ltest参数,我们能够用上libtest.so库了(其实要用libtest.so库里的函数,我们还须要与libtest.so配套的头文件)。
对于置于/lib和/usr/lib和/usr/local/lib里的库直接用-l参数能够链接了adobe air linux,但若果库文件没放到这三个目录里,而是放到其他目录里,若此时我们只用-l参数的话,链接还是会出错,出错信息大约是:
/usr/bin/ld: cannot find -lxx
也就是说链接程序ld在那3个目录里找不到libxx.solinux创建用户并指定目录,这个时侯另外一个参数-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