linux 运行时加载不上动态库 解决方法(转)

1. 连接和运行时库文件搜索路径到设置

    库文件在连接(静态库和共享库)和运行(仅限于使用共享库的程序)时被使用,其搜索路径是在系统中进行设置的。一般 Linux 系统把 /lib 和 /usr/lib 两个目录作为默认的库搜索路径,所以使用这两个目录中的库时不需要进行设置搜索路径即可直接使用。对于处于默认库搜索路径之外的库,需要将库的位置添加到库的搜索路径之中。设置库文件的搜索路径有下列两种方式,可任选其一使用:

(1). 在 /etc/ld.so.conf 文件中添加库的搜索路径。(或者在/etc/ld.so.conf.d 下新建一个.conf文件,将搜索路径一行一个加入-junziyang)

将自己可能存放库文件的路径都加入到/etc /ld.so.conf中是明智的选择添加方法也极其简单,将库文件的绝对路径直接写进去就OK了,一行一个。例如:

/usr/X11R6/lib

/usr/local/lib

/opt/lib 

    需要注意的是:这种搜索路径的设置方式对于程序连接时的库(包括共享库和静态库)的定位已经足够了,但是对于使用了共享库的程序的执行还是不够的。这是因为为了加快程序执行时对共享库的定位速度,避免使用搜索路径查找共享库的低效率,所以是直接读取库列表文件 /etc/ld.so.cache 从中进行搜索的。/etc/ld.so.cache 是一个非文本的数据文件,不能直接编辑,它是根据 /etc/ld.so.conf 中设置的搜索路径由 /sbin/ldconfig 命令将这些搜索路径下的共享库文件集中在一起而生成的(ldconfig 命令要以 root 权限执行)。

    因此,为了保证程序执行时对库的定位,在 /etc/ld.so.conf 中进行了库搜索路径的设置之后,还必须要运行 /sbin/ldconfig 命令更新 /etc/ld.so.cache 文件之后才可以。ldconfig ,简单的说,它的作用就是将/etc/ld.so.conf列出的路径下的库文件缓存到/etc/ld.so.cache 以供使用。因此当安装完一些库文件,(例如刚安装好glib),或者修改ld.so.conf增加新的库路径后,需要运行一下 /sbin/ldconfig使所有的库文件都被缓存到ld.so.cache中,如果没做,即使库文件明明就在/usr/lib下的,也是不会被使用的,结果编译过程中抱错,缺少xxx库,去查看发现明明就在那放着,搞的想大骂computer蠢猪一个。

    在程序连接时,对于库文件(静态库和共享库)的搜索路径,除了上面的设置方式之外,还可以通过 -L 参数显式指定。因为用 -L 设置的路径将被优先搜索,所以在连接的时候通常都会以这种方式直接指定要连接的库的路径。 

    这种设置方式需要 root 权限,以改变 /etc/ld.so.conf 文件并执行 /sbin/ldconfig 命令。而且,当系统重新启动后,所有的基于 GTK2 的程序在运行时都将使用新安装的 GTK+ 库。不幸的是,由于 GTK+ 版本的改变,这有时会给应用程序带来兼容性的问题,造成某些程序运行不正常。为了避免出现上面的这些情况,在 GTK+ 及其依赖库的安装过程中对于库的搜索路径的设置将采用另一种方式进行。这种设置方式不需要 root 权限,设置也简单。

(2). 在环境变量 LD_LIBRARY_PATH 中指明库的搜索路径。

设置方式:

export LD_LIBRARY_PATH=/opt/gtk/lib:$LD_LIBRARY_PATH

可以用下面的命令查看 LD_LIBRAY_PATH 的设置内容:

echo $LD_LIBRARY_PATH

至此,库的两种设置就完成了。

2.交叉编译时候如何配置连接库的搜索路径

    交叉编译的时候不能使用本地(i686机器,即PC机器,研发机器)机器上的库,但是在做编译链接的时候默认的是使用本地库,即/usr/lib, /lib两个目录。因此,在交叉编译的时候,要采取一些方法使得在编译链接的时候找到需要的库。

    首先,要知道:编译的时候只需要头文档,真正实际的库文档在链接的时候用到。 (这是我的理解,假如有不对的地方,敬请网上各位大侠指教) 然后,讲讲如何在交叉编译链接的时候找到需要的库。

(1)交叉编译时候直接使用-L和-I参数指定搜索非标准的库文档和头文档的路径。例如:

arm-linux-gcc test.c -L/usr/local/arm/2.95.3/arm-linux/lib -I/usr/local/arm/2.95.3/arm-linux/include

(2)使用ld.so.conf文档,将用到的库所在文档目录添加到此文档中,然后使用ldconfig命令刷新缓存。

(3)使用如下命令:

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/arm/2.95.3/arm-linux-lib 

参见《ld.so.conf 文档和PKG_CONFIG_PATH变量》这篇文章。

通过环境变量LD_LIBRARY_PATH指定动态库搜索路径(!)。

通过设定环境变量LD_LIBRARY_PATH也可以指定动态库搜索路径。当通过该环境变量指定多个动态库搜索路径时,路径之间用冒号":"分隔。

不过LD_LIBRARY_PATH的设定作用是全局的,过多的使用可能会影响到其他应用程序的运行,所以多用在调试。(LD_LIBRARY_PATH 的缺陷和使用准则,可以参考《Why LD_LIBRARY_PATH is bad》 )。通常情况下推荐还是使用gcc的-R或-rpath选项来在编译时就指定库的查找路径,并且该库的路径信息保存在可执行文件中,运行时它会直接到该路径查找库,避免了使用LD_LIBRARY_PATH环境变量查找。

(4)交叉编译时使用软件的configure参数。例如我编译minigui-1.3.3,使用如下配置:

#!/bin/bash

rm -f config.cache config.status

./configure --build=i686-linux --host=arm-linux --target=arm-linux \

CFLAGS=-I/usr/local/arm/2.95.3/arm-linux/include \

LDFLAGS=-L/usr/local/arm/2.95.3/arm-linux/lib \

--prefix=/usr/local/arm/2.95.3/arm-linux \

--enable-lite \

--disable-galqvfb \

--disable-qvfbial \

--disable-vbfsupport \

--disable-ttfsupport \

--disable-type1support \

--disable-imegb2312py \

--enable-extfullgif \

--enable-extskin \

--disable-videoqvfb \

--disable-videoecoslcd

这里我配置了CFLAGS和LDFLAGS参数,这样一来,我就不用去修改每个Makefile里-L和-I参数了,也不用再去配置 LD_LIBRARY_PATH或改写ld.so.conf文档了。


Linux下动态库使用小结


1. 静态库和动态库的基本概念

    静态库,是在可执行程序连接时就已经加入到执行码中,在物理上成为执行程序的一部分;使用静态库编译的程序运行时无需该库文件支持,哪里都可以用,但是生成的可执行文件较大。动态库,是在可执行程序启动时加载到执行程序中,可以被多个可执行程序共享使用。使用动态库编译生成的程序相对较小,但运行时需要库文件支持,如果机器里没有这些库文件就不能运行。

2. 如何使用动态库

    如何程序在连接时使用了共享库,就必须在运行的时候能够找到共享库的位置。linux的可执行程序在执行的时候默认是先搜索/lib和/usr/lib这两个目录然后按照/etc/ld.so.conf里面的配置搜索绝对路径。同时,Linux也提供了环境变量LD_LIBRARY_PATH供用户选择使用,用户可以通过设定它来查找除默认路径之外的其他路径,如查找/work/lib路径,你可以在/etc/rc.d/rc.local或其他系统启动后即可执行到的脚本添加如下语句:LD_LIBRARY_PATH =/work/lib:$(LD_LIBRARY_PATH)。并且LD_LIBRARY_PATH路径优先于系统默认路径之前查找(详细参考《使用 LD_LIBRARY_PATH》)。

    不过LD_LIBRARY_PATH的设定作用是全局的,过多的使用可能会影响到其他应用程序的运行,所以多用在调试。(LD_LIBRARY_PATH 的缺陷和使用准则,可以参考《Why LD_LIBRARY_PATH is bad》)。通常情况下推荐还是使用gcc的-R或-rpath选项来在编译时就指定库的查找路径,并且该库的路径信息保存在可执行文件中,运行时它会直接到该路径查找库,避免了使用LD_LIBRARY_PATH环境变量查找。

3.库的链接时路径和运行时路径

    现代连接器在处理动态库时将链接时路径(Link-time path)和运行时路径(Run-time path)分开,用户可以通过-L指定连接时库的路径,通过-R(或-rpath)指定程序运行时库的路径,大大提高了库应用的灵活性。比如我们做嵌入式移植时#arm-linux-gcc $(CFLAGS) –o target –L/work/lib/zlib/ -llibz-1.2.3 (work/lib/zlib下是交叉编译好的zlib库),将target编译好后我们只要把zlib库拷贝到开发板的系统默认路径下即可。或者通过- rpath(或-R )、LD_LIBRARY_PATH指定查找路径。

时间: 2024-12-23 17:47:30

linux 运行时加载不上动态库 解决方法(转)的相关文章

动态链接库DLL的加载:隐式加载(载入时加载)和显式加载(运行时加载)

静态链接库在链接时,编译器会将 .obj 文件和 .LIB 文件组织成一个 .exe 文件,程序运行时,将全部数据加载到内存. 如果程序体积较大,功能较为复杂,那么加载到内存中的时间就会比较长,最直接的一个例子就是双击打开一个软件,要很久才能看到界面.这是静态链接库的一个弊端. 动态链接库有两种加载方式:隐式加载和显示加载. 隐式加载又叫载入时加载,指在主程序载入内存时搜索DLL,并将DLL载入内存.隐式加载也会有静态链接库的问题,如果程序稍大,加载时间就会过长,用户不能接受. 显式加载又叫运行

如何在运行时加载C++函数和类

如何在运行时加载C++函数和类 标签(空格分隔): 编程 Problem 有些时候你想在运行时加载一个lib或者function or class,这种事情经常发生在你开发一个plugin或者module时遇到. 在C语言里,你可以轻松的利用dlopen, dlsym, dlclose来做到,但是在C++的世界里却没那么简单了.困难就在C++语言的name mangling上,还有一部分就是dlopen函数是用纯C语言写的,不提供load classes功能. 在解析如何load functio

Android对第三方类库运行时加载

首先,把需要运行时加载的类库,放到项目的其他目录,如新建一个thirdlibs的目录.然后用dx命令,对下面的类库进行压缩,做成dex文件. dx --dex --output=../assets/ *.jar 这会在assets下面生成一个classes.dex文件,压缩成classes.zip文件. 新建一个类,用来加载类库 import java.io.File; import java.io.FileOutputStream; import java.io.FilenameFilter;

如何让linux加载当前目录的动态库

debian从7.0开始支持multiarch,64位库的路径改到/usr/lib/x86_64-linux-gnu了,mint.ubuntu这些衍生版有没有跟着改我就不清楚了. deepin linux 是基于debian的,所以库路径也是/usr/lib/x86_64-linux-gnu # 如何让linux加载当前目录的动态库 --------------------------- linux的excutable在执行的时候缺省是先搜索/lib和/usr/lib这两个目录,然后按照ld.s

commonJs的运行时加载和es6的编译时加载

参考 : https://www.cnblogs.com/jerrypig/p/8145206.html 1.commonJs的运行时加载 2.ES6编译时加载 原文地址:https://www.cnblogs.com/wfblog/p/9589934.html

Android Gradle编译so库或运行时出现 text relocations 崩溃的正确解决方法

1.so库编译时出现 这种情况一般是使用了新版的NDK编译造成的,新版的ndk将warning视为error, 解决方法: 在Android.mk里面加入#LOCAL_DISABLE_FATAL_LINKER_WARNINGS := true 这种方法编译的so库不能运行在target api为23以上的机器. 2.Android运行时崩溃提示 这种情况主要是因为从 API 23 开始,共享对象将不得包含文本重定位.也就是说,代码必须按原样加载,不得对其进行修改.这种方法减少了加载时间,并提高了

JAVA之中出现无法加载主类的情况解决方法

j今天打代码的时候出现了无法加载主类的情况,我就收集了一些,java无法加载主类的方法 ava无法加载主类解决办法 今天启动项目,又遇到找不到或无法加载主类的情况,清除项目后无法编译,class文件下没有.class文件,至少遇到3次这个问题了,隔一段时间就出现这个问题,而且每次解决的方法都还不相同,这个问题的标识就是项目上有红色差号或者叹号,原因诸多也说不清楚,有的时候是jar包缺或者引入了无用的jar包,有时候开发软件编译停顿了反应慢等等,今天特意总结解决此问题的方法,和大家分享一下: 1.

AsyncTasLoader不进行加载操作的原因及解决方法

使用AsyncTaskLoader加载数据.但是LoadInBackground却不会被回调.这是什么情况?我要怎么解决这个问题?如果你和我一样有这样的疑问.你可以移步至我的blog的这篇文章找到答案. 文章地址: http://kohoh1992.github.io/AsyncTaskLoaderDontWork/ 哦,对了.忘记补充了,这里的文章全部都是我个人blog上的副本.如果你对我的blog有兴趣,请移步至 http://kohoh1992.github.io

Spring配置自动加载执行多次的解决方法

首先我的情况网上的方法都没用,这个是反复加载Service的问题,具体不说了 解决方法如下: 单独弄一个配置文件,需要自动加载的全部放里面去.不要忘了改web.xml让它扫描 配置文档里面一共三种方法,用自定义那个,如下 <task:scheduled-tasks> <task:scheduled ref="TestService" method="Test" cron="00 00,10,20,30,40,50 * * * *"