Linux指定动态库路径
众所周知,Linux动态库的默认搜索路径是/lib
和/usr/lib
。动态库被创建后,一般都复制到这两个目录中。当程序执行时需要某动态库,并且该动态库还未加载到内存中,则系统会自动到这两个默认搜索路径中去查找相应的动态库文件,然后加载该文件到内存中,这样程序就可以使用该动态库中的函数,以及该动态库的其它资源了。在Linux 中,动态库的搜索路径除了默认的搜索路径外,还可以通过以下三种方法来指定。
在配置文件/etc/ld.so.conf
中指定动态库搜索路径。
可以通过编辑配置文件/etc/ld.so.conf
来指定动态库的搜索路径,该文件中每行为一个动态库搜索路径。每次编辑完该文件后,都必须运行命令ldconfig
使修改后的配置生效。
举一个例子:
所有源文件:
源文件1:lib_test.c
#include
void prt()
{
printf(“You found me!!!/n”);
}
源文件2:main.c
void prt();
int main()
{
prt();
return 0;
}
操作过程:
我们通过以下命令用源程序lib_test.c
来创建动态库 lib_test.so
。
# gcc –o lib_test.o -c lib_test.c
# gcc -shared -fPIC -o lib_test.so lib_test.o
或者直接一条指令:
#gcc –shared –fPIC –o lib_test.so lib_test.c
注意:
-fPIC
参数声明链接库的代码段是可以共享的,
-shared
参数声明编译为共享库。请注意这次我们编译的共享库的名字叫做
lib_test.so
,这也是Linux共享库的一个命名的惯例了:后缀使用so,而名称使用libxxxx
格式。
接着通过以下命令编译main.c
,生成目标程序main.out
。
# gcc -o main.out -L. –l_test main.c
请注意为什么是-l_test
?
然后把库文件移动到目录/root/lib
中。
# mkdir /root/lib
# mv lib_test.so /root/lib/ lib_test.so
最后编辑配置文件/etc/ld.so.conf
,在该文件中追加一行/root/lib
。
运行程序main.out
:
# ./main.out
./main.out: error while loading shared libraries: lib_test.so: cannot open shared object file: No such file or directory
出错了,系统未找到动态库lib_test.so
。找找原因,原来在编辑完配置文件/etc/ld.so.conf
后,没有运行命令ldconfig
,所以刚才的修改还未生效。我们运行ldconfig
后再试试。
# ldconfig
# ./main.out
You found me!!!
程序main.out
运行成功,并且打印出正确结果。
2.通过环境变量LD_LIBRARY_PATH
指定动态库搜索路径。
通过设定环境变量LD_LIBRARY_PATH
也可以指定动态库搜索路径。当通过该环境变量指定多个动态库搜索路径时,路径之间用冒号”:”分隔。下面通过例2来说明本方法。
举一个例子:
这次我们把上面得到的文件lib_test.so
移动到另一个地方去,如/root
下面,然后设置环境变量LD_LIBRARY_PATH
找到lib_test.so
。设置环境变量方法如下:
# export LD_LIBRARY_PATH=/root
然后运行:
#./main.out
You found me!!!
注意:设置环境变量LD_LIBRARY_PATH=/root
是不行的,非得export才行。
3.在编译目标代码时指定该程序的动态库搜索路径。
还可以在编译目标代码时指定程序的动态库搜索路径。-Wl,表示后面的参数将传给link程序ld(因为gcc可能会自动调用ld)。这里通过gcc 的参数”-Wl,-rpath
,”指定
举一个例子:
这次我们还把上面得到的文件lib_test.so
移动到另一个地方去,如/root/test/lib
下面,
因为我们需要在编译目标代码时指定可执行文件的动态库搜索路径,所以需要用gcc命令重新编译源程序main.c
(见程序2)来生成可执行文件main.out
。
# gcc -o main.out -L. –l_test -Wl,-rpath,/root/test/lib main.c
运行结果:
# ./main.out
You found me!!!
程序./main.out
运行成功,输出的结果正是main.c
中的函数prt
的运行结果。因此程序main.out
搜索到的动态库是/root/test/lib/lib_test.so
。
关于-Wl,rpath
的使用方法我再举一个例子,应该不难从中看出指定多个路径的方法:
gcc -Wl,-rpath,/home/arc/test,-rpath,/lib/,-rpath,/usr/lib/,-rpath,/usr/local/lib test.c
以上介绍了三种指定动态库搜索路径的方法,加上默认的动态库搜索路径/lib
和/usr/lib
,共五种动态库的搜索路径,那么它们搜索的先后顺序是什么呢?读者可以用下面的方法来试验一下:
(1) 用前面介绍的方法生成5个lib_test.so
放在5个不同的文件夹下面,要求每一个lib_test.so
都唯一对应一个搜索路径,并注意main.out
程序输出的不同。
(2) 运行main.out
,即可看出他是那个搜索路径下的,然后删除这个路径下的lib_test.so
,然后再运行。依此类推操作,即可推出搜索顺序。
可以得出动态库的搜索路径搜索的先后顺序是:
-
编译目标代码时指定的动态库搜索路径;
-
环境变量
LD_LIBRARY_PATH
指定的动态库搜索路径; -
配置文件
/etc/ld.so.conf
中指定的动态库搜索路径; -
默认的动态库搜索路径
/lib
; -
默认的动态库搜索路径
/usr/lib
。
在上述1、2、3指定动态库搜索路径时,都可指定多个动态库搜索路径,其搜索的先后顺序是按指定路径的先后顺序搜索的。有兴趣的读者自己验证。