---此文章同步自我的CSDN博客---
一.运行时动态库:not found
今天在使用linux编写c/c++程序时,需要用到第三方的动态库文件。刚开始编译完后,运行提示找不到动态库文件.我就使用了ldd命令查看了一下,发现是有一个库文件显示"not found”,如下图所示;
对于库文件未找到,因为编译、链接都没有问题,那就是运行链接动态库时找不到动态库了。对于运行链接动态库时找不到动态库的方法,最基本的解决方法就两种:
第一种方法:找到缺少的动态库(由于编译和链接时候的使用到了这个动态库,所以很容易找得到),将其加到/lib,/usr/lib中的一个文件夹下,这几个文件夹是系统默认的搜索路径。将库文件放置在其中,运行时就可以搜索到了。
第二种方法:设置临时增加链接动态库的路径;使用
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:《your_lib_path》
比如我的libpaho-mqtt3cs.so.1在/home/mqtt/MQTT-c/lib目录下,那我使用的是:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/mqtt/MQTT-c/lib
这种方法设置的是临时的,系统重启之后就没了。当然也可以设置为持久的,这里就不过多讲述。
还有一种方法是不常用的,更改配置文件:
第三种方法:/etc/ld.so.cache中缓存了动态库路径,可以通过修改配置文件/etc/ld.so.conf中指定的动态库搜索路径,然后执行ldconfig命令来改变。
不过,我又想了一下,感觉这几种方法都不适合我现在的情况,这些都是事后补救的方法。首先,我不可能每次需要用到一个第三方的动态库的时候都要往几个系统默认的文件夹里面扔,这会导致这几个文件夹越来越大,越来越乱;再者,我也不想每次都设置临时动态库搜索路径,每个程序这么做的话得设置多少次啊,而且也导致文件夹变多,总归不好;而更改配置我就更不推荐了,会导致配置文件越来越乱。
我又google了一下,找到了一个命令,适合我目前的情况:指定程序运行时会在指定文件下寻找第三方的动态库。
-第四种方法:在链接时语句后面添加如下命令:
-Wl,-rpath=《my_thirdparty_lib_path》
对比一下添加前后的Makefile语句。not found时的语句:
更改之后的语句:
我们来看看更改之后的编译结果:
可以看到,我的libpaho-mqtt3cs.so.1从我在文章开头时的【not found】变成了有来源了,而绿色部分的路径就是我刚刚Makefile中的-Wl,-rpath=之后的路径。
二.介绍-Wl,-rpath=
因为今天是-Wl,-rpath解决了我的问题,而且发现网上搜到的资料不够详细,我在这里就介绍一下这个方法。
-Wl,-rpath=《your_lib_dir》是为程序添加一个运行时库文件搜索路径的命令,在使用gcc编译链接时添加即可。
其中,有两个单独的部分-Wl和-rpath组成。
-Wl
这个是gcc的参数,表示编译器将后面的参数传递给链接器ld。
请注意此处的W是大写的。
-rpath
使用man ld命令查看手册,找到了-rpath的讲解:
Add a directory to the runtime library search path. This is used when linking an ELF executable with shared objects. All -rpath arguments are concatenated and passed to the runtime linker, which uses them to locate shared objects at runtime. The -rpath option is also used when locating shared objects which are needed by shared objects explicitly included in the link; see the description of the -rpath-link option. If -rpath is not used when linking an ELF executable, the contents of the environment variable "LD_RUN_PATH" will be used if it is defined.
大体就以下这几个意思:
1. 添加一个文件夹作为运行时库的搜索路径。在将ELF可执行文件与共享对象链接时使用此选项;
2. 在链接时,一些动态库明确的链接了其他动态库, 则-rpath选项也可用于定位这些链接的动态库(没太理解这个);
3. 在运行链接时,会优先搜索-rpath的路径,再去搜索LD_RUN_PATH的路径。
至此,该命令也算是能够完成我对程序的需求了。即通过-Wl,-rpath=《lib_path》可添加文件夹作为动态库搜索路径,并记录在程序ELF可执行程序中。我们调用程序时回去我们写入的目录中查找我们的第三方库文件。