一般我们在Linux下执行某些外部程序的时候可能会提示找不到共享库的错误, 比如:
error while loading shared libraries: libevent-1.4.so.2: cannot open shared object file: No such file or directory
原因一般有两个, 一个是操作系统里确实没有包含该共享库(lib*.so.*文件)或者共享库版本不对, 遇到这种情况那就去网上下载并安装上即可.
另外一个原因就是已经安装了该共享库, 但执行需要调用该共享库的程序的时候, 程序按照默认共享库路径找不到该共享库文件.
所以安装共享库后要注意共享库路径设置问题, 如下:
1) 如果共享库文件安装到了/lib或/usr/lib目录下, 那么需执行一下ldconfig命令
ldconfig命令的用途, 主要是在默认搜寻目录(/lib和/usr/lib)以及动态库配置文件/etc/ld.so.conf内所列的目录下, 搜索出可共享的动态链接库(格式如lib*.so*), 进而创建出动态装入程序(ld.so)所需的连接和缓存文件. 缓存文件默认为/etc/ld.so.cache, 此文件保存已排好序的动态链接库名字列表.
2) 如果共享库文件安装到了/usr/local/lib(很多开源的共享库都会安装到该目录下)或其它"非/lib或/usr/lib"目录下, 那么在执行ldconfig命令前, 还要把新共享库目录加入到共享库配置文件/etc/ld.so.conf中, 如下:
# cat /etc/ld.so.conf
include ld.so.conf.d/*.conf
# echo "/usr/local/lib" >> /etc/ld.so.conf
# ldconfig
3) 如果共享库文件安装到了其它"非/lib或/usr/lib" 目录下, 但是又不想在/etc/ld.so.conf中加路径(或者是没有权限加路径). 那可以export一个全局变量LD_LIBRARY_PATH, 然后运行程序的时候就会去这个目录中找共享库.
LD_LIBRARY_PATH的意思是告诉loader在哪些目录中可以找到共享库. 可以设置多个搜索目录, 这些目录之间用冒号分隔开. 比如安装了一个MySQL到/usr/local/mysql目录下, 其中有一大堆库文件在/usr/local/mysql/lib下面, 则可以在.bashrc或.bash_profile或shell里加入以下语句即可:
export LD_LIBRARY_PATH=/usr/local/mysql/lib:$LD_LIBRARY_PATH
一般来讲这只是一种临时的解决方案, 在没有权限或临时需要的时候使用.
如果程序需要的库文件比系统目前存在的库文件版本低,可以做一个链接。比如:
error while loading shared libraries: libncurses.so.4: cannot open shared
object file: No such file or directory
ls /usr/lib/libncu*
/usr/lib/libncurses.a /usr/lib/libncurses.so.5
/usr/lib/libncurses.so /usr/lib/libncurses.so.5.3
可见虽然没有libncurses.so.4,但有libncurses.so.5,是可以向下兼容的
建一个链接就好了
ln -s /usr/lib/libncurses.so.5.3 /usr/lib/libncurses.so.4
------------------
一.一般安装动态库方式
#./configure
#make
#make install
这样,动态库一般安装在/lib、/usr/lib、/usr/local/lib、自定义目录下。
二.找不到共享库文件的原因
1.压根就没有此共享库,也就是说系统中根本就没有此库或者说没装,这时,从网上下载一些词库装上去即可;
2.已经安装了该共享库, 但执行需要调用该共享库的程序的时候, 程序按照默认的路径找不到共享库,这也是众多人面对的情形,下面主要针对此原因进行说明。
三.linux寻找动态链接库的顺序
1.编译代码时指定的动态库搜索路径,这里说明一下,不是Makefile中的-L等指定的目录;
2.环境变量LD_LIBRARY_PATH指定的动态库搜索路径;
3.配置文件/etc/ld.so.conf指定的动态库搜索路径;
4.系统默认搜索路径/lib;
5.系统默认搜索路径/usr/lib.
四.基于顺序的解决方法
1.编译时指定目录:
在程序文件中的.dynamic段包含了一个叫DT_RPATH的项,是一个以冒号分隔的库文件搜索目录列表,用以搜索动态库。
在编译程序时,加入 ”-WI,-rpath =目录“选项,即将动态库文件搜索路径加入到可执行的连接文件中,如一个程序main需要使用libaa.so库,
则编译如下,gcc -o main -L. -laa -WI,rpath=./ main.c ,即在执行main程序时,main会先在当前目录./下查找所需要的动态库文件。
2.LD_LIBRARY_PATH指定目录:
LD_LIBRARY_PATH为环境变量,可以export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:动态库目录,可以在运行程序时的终端上键入,
此时,其只对当前的登录有效,即关闭此终端后失效;在~/.bashrc或.bash_profile中添加一行后并source ~/.bashrc,这样可以永久使用。
3.加入/etc/ld.so.conf文件:
一般此文件的内容为:include /etc/ld.so.conf.d/*.conf
在其下面添加一行动态库的搜索目录,然后在终端输入ldconfig命令即可。
ldconfig是个什么东东?它是一个linux程序,通常在/sbin下,是root权限的,简单的说,它的作用是将/etc/ld.so.conf列出的路径下的库文件
缓存到/etc/ld.so.cache中以供使用,因此在改动库文件后一定要运行ldconfig.
4和5.将库文件放在这两个系统默认搜索路径下即可。
五.明明安装了高版本,但是还是嫌库版本低
如经常在论坛上看到有人问"为什么我已经安装了glib-2.4.x,但是编译gtk -2.4.x 还是提示glib版本太低阿?
这就涉及到PKG_CONFIG_PATH环境变量。
一般在编译安装库时,会出现类似如下情形(编译gtk -2.4.13):
checking forpkg-config... /usr/bin/pkg-config
checking for glib-2.0 >= 2.4.0 atk >= 1.0.1 pango >= 1.4.0... Package glib-2.0 was not found in the pkg-config
search path.
Perhaps you should add the directory containing `glib-2.0.pc'to thePKG_CONFIG_PATH environment variable
No package 'glib-2.0' found
configure: error: Library requirements (glib-2.0 >= 2.4.0 atk >= 1.0.1 pango >= 1.4.0) not met; consider adjusting
the PKG_CONFIG_PATH environment variable if your libraries are in a nonstandard prefix so pkg-config can findthem.
那这三个红色表明的是干什么用的呢?
pkg-config用来向configure程序提供系统软件信息,如软件的版本、库的版本、路径等,这些信息都放在*.pc下。
如库装在了/usr/local下,则对应的.pc文件一般在/usr/local/lib/pkgconfig下,要将此目录添加到PKG_CONFIG_PATH中。
也就是说,在执行./configure时,pkg-config会查找PKG_CONFIG_PATH指定目录下的.pc文件来提供系统软件的信息。