谈谈Linux下动态库查找路径的问题

2023-11-08

		                <p></p>
        </div>
       <div class="Blog_wz1" style="word-wrap: break-word;">
					<span style="font-size:16px;">&nbsp; &nbsp;&nbsp;学习到了一个阶段之后,就需要不断的总结、沉淀、清零,然后才能继续“上路”。回想起自己当年刚接触Linux时,不管是用源码包编译程序,还是程序运行时出现的和动态库的各种恩恩怨怨,心里那真叫一个难受。那时候脑袋里曾经也犯过嘀咕,为啥Linux不弄成windows那样呢,装个软件那个麻烦不说,连运行软件都这么恼火呢?如果那样的话就不叫Linux了。借用小米公司CEO雷军一句话:小米,为发烧而生。我认为:Linux,为真理而在。特别是为那些喜欢折腾,热衷技术背后原理和实现细节的人们而生。</span><br>



   说到和动态库查找路径相关的问题,总体上可以分为两类:

   第一类:通过源代码编译程序时出现的找不到某个依赖包的问题,而如果此时你恰好已经按照它的要求确确实实、千真万确、天地良心地把依赖库给装好了,它还给你耍混、犯二,有一股折腾不死人不偿命的劲儿,那让人真是气儿不打一处来,如果Linux此时有头有脸,你是不是特想抽它丫两大嘴巴;

   第二类:就是在运行程序的时候,明明把那个程序需要的依赖包都已经安装的妥妥的了,可运行的时候人家就告诉你说“error while loading shared libraries: libxxx.so.y: cannot open shared object file: No such file or directory”,任凭你怎么折腾都没用。此时你要是心想“撤吧,哥们,Linux太TM欺负人了,不带这么玩儿的”,那你就大错特错了,只要你抱着“美好的事情的总会发生”和“办法永远比问题多”的信念坚持下去,你就一定会成功。话的意思有点自欺欺人,精神鸦片的味道在里面,但确实是这么个理儿。

   

   上面两类问题最大的原因就是,你没弄白它们的机制和原理。你看到的只是现象,当年学马克思主义主义哲学原理的时候,老师怎么教导我们的?要透过现象看本质。如果你把上面两中应用的原理搞清了,那问题不就自然而然的迎刃而解了么。下面咱们就一一探讨一下这两个问题,以便对新进学习Linux的朋友们起一个的参考资料的作用。



    问题1:通过源代码安装程序

    通过源码包安装程序时,主要用到了“三大步”策略:configure、make和make install 。出问题最多的就是在configure阶段,很多初学者由于不知道configure的那么多参数该怎么用,所以往往为了省事,一句简单的“./configure”下去,百分之八九十都能成功,可问题往往就出在剩下的百分之十几上面了。这让我们又一次相信了,小概率事件的发生对事情的影响是多么的深远。在安装的configure阶段,为了检测安装安装环境是否满足,通常情况下都是通过一个叫做pkg-config的工具来检测它需要依赖的动态库是否存在,这个工具我们在上一篇博文已经认识过了。pkg-config通常情况都是位于/usr/bin目录下,是个可执行程序。在configure阶段,通常都会用pkg-config来判断所依赖的动态库是否存在。现在问题就是,这个工具是如何判断的呢?它的依据是什么?当这两个问题弄明白了,真相也就大白了。



   一般当我们安装完某个程序后,如果它提供了动态库的功能,在源码中都会有一个或多个以pc结尾的文件,当执行完make install后这些pc文件拷贝到${prefix}/lib/pkgconfig这个目录里,这里的prefix就是我们在configure阶段时通过配置参数–prefix指定的,缺省情况这个值就是/usr/local,所以这些pc文件最终会被拷贝到/usr/local/lib/pkgconfig目录下。可能有人会问,这些pc文件有啥用呢?我们随便打开一个来瞅瞅:

[root@localhost ~]# cat /usr/local/lib/pkgconfig/librtmp.pc
prefix=/usr/local
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
incdir=${prefix}/include


Name: librtmp
Description: RTMP implementation
Version: v2.3
Requires: libssl,libcrypto
URL: http://rtmpdump.mplayerhq.hu
Libs: -L${libdir} -lrtmp -lz
Cflags: -I${incdir}

   跟我们configure阶段相关的主要集中在Libs和Cflags两项上面,如果你此时再执行下面这两条命令,就全明白了:
[root@localhost ~]# pkg-config --cflags librtmp
-I/usr/local/include
[root@localhost ~]# pkg-config --libs librtmp
-L/usr/local/lib -lrtmp -lz -lssl -lcrypto

   也就是说,pkg-config把我们以前需要在Makefile里指定编译和链接时所需要用到的参数从手工硬编码的模式变成了自动完成,节约了多少跨平台移植的兼容性问题,我们是不是得感谢人家十八辈儿祖宗。假如说,如果我们将要的编译的软件包依赖librtmp这个动态库,那么此时在我系统上这个检测就算通过了。当然这只是第一步,检测过了不一定兼容,这里我们只讨论能不能找到依赖库的问题,兼容性问题那都不是个事儿,人家要啥版本你好生伺候就是了,这个没得商量,最好也不要商量,童叟无欺,不然后果很严重。好了,如果说找不到某个库该怎么办。 前提是你确确实实已经安装了它需要的库, 不用多想,原因只有一个,pkg-config找不到这个与这个库对应的pc文件。为什么会找不到呢,原因又有两点:
   1、pkg-config搜索了所有它认为合适的目录都没找着这个库对应的pc文件的下落;
   2、这个库在发布时根本就没有提供它的pc文件。
   这里,我们严重“抗议、鄙视+抵制”第二种情况的软件包,而且也尽量不要它,一个出来混都不自报家门的家伙,肯定也好不到哪里去。那么,现在问题就只剩下一个了:pkg-config的查找路径是哪里?

   pkg-config较老的版本里,缺省情况下会到/usr/lib/pkgconfig、/usr/loca/lib/pkgconfig、/usr/share/pkgconfig等目录下去搜索pc文件,据我所知在0.23以及之后的版本里pkg-config的源码里已经没有关于缺省搜索路径的任何硬编码的成分了,至于具体从哪个版本开始我也没有去追究,还望有知道的朋友分享一下。取而代之的是,当你看pkg-config的man手册时会有下面一段话:

pkg-config retrieves information about packages from special metadata files. These files are  named  after the  package,  with  the extension .pc.
By default, pkg-config looks in the directory prefix/lib/pkgconfig for these files; it will also look in the colon-separated (on Windows, semicolon-separated) list of directories specified by the PKG_CONFIG_PATH environment variable.

   以及这点补充:
PKG_CONFIG_PATH
    A colon-separated (on Windows, semicolon-separated) list of directories to search  for  .pc  files. The  default directory will always be searched after searching the path; the default is libdir/pkg-config:datadir/pkgconfig where libdir is the libdir where pkg-config and  datadir  is  the  datadir where pkg-config was installed.


   上面提到的prefix、libdir和datadir,就是安装pkg-config时被设定好的,具体情况是:
   1、如果你是通过yum和rpm包安装的
        prefix=/usr
       libdir=${prefix}/lib=/usr/lib
       datadir=${prefix}/share=/usr/share
   2、如果你是通过源码包安装的,且没有指定prefix的值(指定的情况同1)
       prefix=/usr/local
       libdir=${prefix}/lib=/usr/local/lib
       datadir=${prefix}/share=/usr/local/share 

   pkg-config在查找对应软件包的信息时的缺省搜索路径已经很清楚了,有一点写错了,不是${ libdir}/pkg-config,而应该是${libdir}/pkgconfig和${ datadir}/pkgconfig 。如果你软件包对应的pc文件都不在这两个目录下时,pkg-config肯定找不到 。既然原因都已经找到了,那解决办法也就多种多样了。
   方案一: 我们可以在安装我们那个被依赖的软件包时,在configure阶段用--prefix参数把安装目录指定到/usr目录下;
   方案二: 也可以按照上面说的,通过一个名叫PKG_CONFIG_PATH的环境变量来向pkg-config指明我们自己的pc文件所在的路径,不过要注意的是PKG_CONFIG_PATH所指定的路径优先级比较高,pkg-config会先进行搜索,完了之后才是去搜索 缺省路径。
   前者的优点是以后再通过源码安装软件时少了不少麻烦,缺点是用户自己的软件包和系统软件 混到一起不方便管理,所以实际使用中,后者用的要多一些。

    方案二在实际操作中有两种实现方式:
   1、针对没有root权限的情况,大多数情况都是执行:
export PKG_CONFIG_PATH=/your/local/path:$PKG_CONFIG_PATH

   然后,在configure时就绝对没问题了。
   2、在用户的家目录下的 .bash_profile文件里 或系统文件 /etc/profile 的末尾添加上面一行也成,都可以。
   至此, 动态库查找问题的 第一种情况就彻底解决了。想了解pc文件的更多细节的,可以参考 http://people.freedesktop.org/~dbn/pkg-config-guide.html  ; 想学习pkg-config工具更多用法的朋友建议看man手册。

    问题2:程序运行时出现libxxx.so.y => not found
   这种情况,在我以前的博文“ Linux系统下动态库和静态库那点事儿 ”里已经提到一部分,这里就把它补充完整。在那篇博文里,我用的配置文件或者“ldconfig 动态库所在路径” 的方式解决的,也是99%的场合下的解决办法,那是针对有root权限的用户的解决办法。没有root权限运行软件时,Linux也为 我们提供了一个名为 LD_LIBRARY_PATH的环境变量来解决运行时动态库查找路径的解决方案。同样地,由这个环境变量所指定的路径会被装载器 /lib/ld-2.12.so优先查找,然后才是动态库库缓存文件 /etc/ld.so.cache ,风采瞬间 就被 LD_LIBRARY_PATH给抢完了, /etc/ld.so.cache表示很不高兴。 针对 LD_LIBRARY_PATH 环境变量 这种情况, 绝对是临时不能再临时解决方案了,如果只是测试用,用export像解决PKG_CONFIG_PATH 一样的方式干净利索就行了, 千万不要在实际生产上线的运维环境里把“export LD_LIBRARY_PATH=...” 添加到 .bash_profile或者 /etc/profile里,不然到时候悔得你肠子都绿了不可。

   其实 PKG_CONFIG_PATH 和 LD_LIBRARY_PATH经常被很多人误用,特别是新手们在解决问题时,也不分青红皂白,逮着了就是一顿狂export,根据实际场合,运气好了说不定问题还真就解决,点儿背了折腾一天半宿也是白忙活。其实要是留点心,还是挺容易明白的:
    PKG_CONFIG_PATH从字面意思上翻译,就是“软件包的配置路径”,这不很明显了么,编译软件时如果出现找不到所依赖的动态库时都全靠PKG_CONFIG_PATH了;
    LD_LIBRARY_PATH也很直白了“装载器的库路径”,LD是Loader的简写,在博文“段错误到底是何方妖孽”里我也曾提到过,在Linux系统启动一个程序的过程就叫做装载, 一个程序要执行时它或多或少的会依赖一些动态库(静态编译的除外 )。当你用“ldd 可执行程序名 ”查看一个软件启动时 所依赖的动态库,如果输出项有“libxxx.so.y=> not found ”一项,你这个软件100% 运行不起来。

   不信我们来做个试验:
[root@localhost ~]# echo $LD_LIBRARY_PATH    //嘛也没有

[root@localhost ~]# ldd /usr/local/bin/ffmpeg
        linux-gate.so.1 =>  (0x00914000)
        libavdevice.so.54 => /usr/local/lib/libavdevice.so.54 (0x007d0000)
        libavfilter.so.3 => /usr/local/lib/libavfilter.so.3 (0x001f3000)
        libavformat.so.54 => /usr/local/lib/libavformat.so.54 (0x002b5000)
        libavcodec.so.54 => /usr/local/lib/libavcodec.so.54 (0xb68dd000)
        libpostproc.so.52 => /usr/local/lib/libpostproc.so.52 (0x0083c000)
        libswresample.so.0 => /usr/local/lib/libswresample.so.0 (0x00a91000)
        libswscale.so.2 => /usr/local/lib/libswscale.so.2 (0x00d80000)
        libavutil.so.52 => /usr/local/lib/libavutil.so.52 (0x001a7000)
        libm.so.6 => /lib/libm.so.6 (0x0058b000)
        libpthread.so.0 => /lib/libpthread.so.0 (0x001d7000)
        libc.so.6 => /lib/libc.so.6 (0x005e2000)
        libasound.so.2 => /lib/libasound.so.2 (0x00ec5000)
        libdc1394.so.22 => /usr/local/lib/libdc1394.so.22 (0x00116000)
        librt.so.1 => /lib/librt.so.1 (0x00184000)
        libfreetype.so => /usr/local/lib/libfreetype.so (0x00411000)
        libass.so.4 => /usr/local/lib/libass.so.4 (0x0091a000)
        libssl.so.1.0.0 => /usr/local/lib/libssl.so.1.0.0 (0x0048c000)
        libcrypto.so.1.0.0 => /usr/local/lib/libcrypto.so.1.0.0 (0x00aa8000)
        librtmp.so.0 => /usr/local/lib/librtmp.so.0 (0x009dd000)
        libz.so.1 => /lib/libz.so.1 (0x0018d000)
        libx264.so.132 => /usr/local/lib/libx264.so.132 (0x00fb1000)
        libvorbisenc.so.2 => /usr/local/lib/libvorbisenc.so.2 (0x0194d000)
        libvorbis.so.0 => /usr/local/lib/libvorbis.so.0 (0x004e5000)
        libvo-aacenc.so.0 => /usr/local/lib/libvo-aacenc.so.0 (0x00799000)
        libtwolame.so.0 => /usr/local/lib/libtwolame.so.0 (0x0050d000)
        libtheoraenc.so.1 => /usr/local/lib/libtheoraenc.so.1 (0x0052d000)
        libtheoradec.so.1 => /usr/local/lib/libtheoradec.so.1 (0x00779000)
        libspeex.so.1 => /usr/local/lib/libspeex.so.1 (0x00c94000)
        libmp3lame.so.0 => /usr/local/lib/libmp3lame.so.0 (0x0088c000)
        libfaac.so.0 => /usr/local/lib/libfaac.so.0 (0x00573000)
        /lib/ld-linux.so.2 (0x005c2000)
        libdl.so.2 => /lib/libdl.so.2 (0x001a1000)
        libraw1394.so.11 => /usr/local/lib/libraw1394.so.11 (0x005b5000)
        libfribidi.so.0 => /usr/local/lib/libfribidi.so.0 (0x007b5000)
        libfontconfig.so.1 => /usr/local/lib/libfontconfig.so.1 (0x007ea000)
        libogg.so.0 => /usr/local/lib/libogg.so.0 (0x00583000)
        libexpat.so.1 => /lib/libexpat.so.1 (0x00933000)

   我的系统里没有设置 LD_LIBRARY_PATH 环境变量,上一篇博文里编译的ffmpeg运行时依赖的非常多的动态库。现在我们把其中的一个库libmp3lame.so.0从/usr/loca/lib下移动到/opt目录里,并执行ldconfig ,让libmp3lame.so.0彻底从/etc/ld.so.cache里面消失。其实libmp3lame.so.0只是libmp3lame.so.0.0.0的一个符号链接,我们真正需要移动的是后者,完了之后再执行ldd /usr/local/bin/ffmpeg时结果如下:

[root@localhost ~]# ldd /usr/local/bin/ffmpeg
        linux-gate.so.1 =>  (0x00249000)
        libavdevice.so.54 => /usr/local/lib/libavdevice.so.54 (0x00e12000)
        libavfilter.so.3 => /usr/local/lib/libavfilter.so.3 (0x00ccd000)
        libavformat.so.54 => /usr/local/lib/libavformat.so.54 (0x00891000)
        libavcodec.so.54 => /usr/local/lib/libavcodec.so.54 (0xb6877000)
        libpostproc.so.52 => /usr/local/lib/libpostproc.so.52 (0x001a6000)
        libswresample.so.0 => /usr/local/lib/libswresample.so.0 (0x00b8f000)
        libswscale.so.2 => /usr/local/lib/libswscale.so.2 (0x0024a000)
        libavutil.so.52 => /usr/local/lib/libavutil.so.52 (0x005d7000)
        libm.so.6 => /lib/libm.so.6 (0x007ad000)
        libpthread.so.0 => /lib/libpthread.so.0 (0x001f6000)
        libc.so.6 => /lib/libc.so.6 (0x0029f000)
        libasound.so.2 => /lib/libasound.so.2 (0x00604000)
        libdc1394.so.22 => /usr/local/lib/libdc1394.so.22 (0x00436000)
        librt.so.1 => /lib/librt.so.1 (0x00a06000)
        libfreetype.so => /usr/local/lib/libfreetype.so (0x0052d000)
        libass.so.4 => /usr/local/lib/libass.so.4 (0x00211000)
        libssl.so.1.0.0 => /usr/local/lib/libssl.so.1.0.0 (0x00eed000)
        libcrypto.so.1.0.0 => /usr/local/lib/libcrypto.so.1.0.0 (0x00f46000)
        librtmp.so.0 => /usr/local/lib/librtmp.so.0 (0x004b9000)
        libz.so.1 => /lib/libz.so.1 (0x0022a000)
        libx264.so.132 => /usr/local/lib/libx264.so.132 (0x0765d000)
        libvorbisenc.so.2 => /usr/local/lib/libvorbisenc.so.2 (0x00a0f000)
        libvorbis.so.0 => /usr/local/lib/libvorbis.so.0 (0x004ce000)
        libvo-aacenc.so.0 => /usr/local/lib/libvo-aacenc.so.0 (0x005a8000)
        libtwolame.so.0 => /usr/local/lib/libtwolame.so.0 (0x006f0000)
        libtheoraenc.so.1 => /usr/local/lib/libtheoraenc.so.1 (0x00710000)
        libtheoradec.so.1 => /usr/local/lib/libtheoradec.so.1 (0x00756000)
        libspeex.so.1 => /usr/local/lib/libspeex.so.1 (0x00770000)
        libmp3lame.so.0 => not found    //果然飘红了 :)
        libfaac.so.0 => /usr/local/lib/libfaac.so.0 (0x004a4000)
        /lib/ld-linux.so.2 (0x0050d000)
        libdl.so.2 => /lib/libdl.so.2 (0x0023e000)
        libraw1394.so.11 => /usr/local/lib/libraw1394.so.11 (0x004f6000)
        libfribidi.so.0 => /usr/local/lib/libfribidi.so.0 (0x0078a000)
        libfontconfig.so.1 => /usr/local/lib/libfontconfig.so.1 (0x007d7000)
        libogg.so.0 => /usr/local/lib/libogg.so.0 (0x00243000)
        libexpat.so.1 => /lib/libexpat.so.1 (0x00806000)

[root@localhost ~]# ffmpeg --help
ffmpeg: error while loading shared libraries: libmp3lame.so.0: cannot open shared object file: No such file or directory  //此时ffmpeg当然运行不起来
   
   我们来试试 LD_LIBRARY_PATH,看看好使不:
[root@localhost opt]# export LD_LIBRARY_PATH=/opt:$LD_LIBRARY_PATH
[root@localhost opt]#
[root@localhost opt]# ldd /usr/local/bin/ffmpeg
        linux-gate.so.1 =>  (0x00136000)
        libavdevice.so.54 => /usr/local/lib/libavdevice.so.54 (0x00552000)
        libavfilter.so.3 => /usr/local/lib/libavfilter.so.3 (0x00655000)
        libavformat.so.54 => /usr/local/lib/libavformat.so.54 (0x00243000)
        libavcodec.so.54 => /usr/local/lib/libavcodec.so.54 (0xb68a7000)
        libpostproc.so.52 => /usr/local/lib/libpostproc.so.52 (0x00137000)
        libswresample.so.0 => /usr/local/lib/libswresample.so.0 (0x00187000)
        libswscale.so.2 => /usr/local/lib/libswscale.so.2 (0x0047e000)
        libavutil.so.52 => /usr/local/lib/libavutil.so.52 (0x00a9d000)
        libm.so.6 => /lib/libm.so.6 (0x00af9000)
        libpthread.so.0 => /lib/libpthread.so.0 (0x00823000)
        libc.so.6 => /lib/libc.so.6 (0x0083e000)
        libasound.so.2 => /lib/libasound.so.2 (0x0055f000)
        libdc1394.so.22 => /usr/local/lib/libdc1394.so.22 (0x0019e000)
        librt.so.1 => /lib/librt.so.1 (0x00b3c000)
        libfreetype.so => /usr/local/lib/libfreetype.so (0x0039f000)
        libass.so.4 => /usr/local/lib/libass.so.4 (0x00f67000)
        libssl.so.1.0.0 => /usr/local/lib/libssl.so.1.0.0 (0x00cb3000)
        libcrypto.so.1.0.0 => /usr/local/lib/libcrypto.so.1.0.0 (0x00d0c000)
        librtmp.so.0 => /usr/local/lib/librtmp.so.0 (0x0020c000)
        libz.so.1 => /lib/libz.so.1 (0x00c77000)
        libx264.so.132 => /usr/local/lib/libx264.so.132 (0x00f80000)
        libvorbisenc.so.2 => /usr/local/lib/libvorbisenc.so.2 (0x07c66000)
        libvorbis.so.0 => /usr/local/lib/libvorbis.so.0 (0x0041a000)
        libvo-aacenc.so.0 => /usr/local/lib/libvo-aacenc.so.0 (0x0076c000)
        libtwolame.so.0 => /usr/local/lib/libtwolame.so.0 (0x004fe000)
        libtheoraenc.so.1 => /usr/local/lib/libtheoraenc.so.1 (0x00717000)
        libtheoradec.so.1 => /usr/local/lib/libtheoradec.so.1 (0x00f0c000)
        libspeex.so.1 => /usr/local/lib/libspeex.so.1 (0x00221000)
        libmp3lame.so.0 => not found           //纳尼??!!!
        libfaac.so.0 => /usr/local/lib/libfaac.so.0 (0x00124000)
        /lib/ld-linux.so.2 (0x00bad000)
        libdl.so.2 => /lib/libdl.so.2 (0x0023b000)
        libraw1394.so.11 => /usr/local/lib/libraw1394.so.11 (0x007b6000)
        libfribidi.so.0 => /usr/local/lib/libfribidi.so.0 (0x00442000)
        libfontconfig.so.1 => /usr/local/lib/libfontconfig.so.1 (0x0051e000)
        libogg.so.0 => /usr/local/lib/libogg.so.0 (0x009f7000)
        libexpat.so.1 => /lib/libexpat.so.1 (0x00b60000)

   还记得上面提到了软链接么,libmp3lame.so.0就是libmp3lame.so.0.0.0的软链接,这是动态库的命名规范的一种公约,我们只要在/opt/目录下建立一个名为 libmp3lame.so.0的到/opt/libmp3lame.so.0.0.0的软链接 就OK了:

[root@localhost opt]# ls
libmp3lame.so.0.0.0
[root@localhost opt]# ln -s libmp3lame.so.0.0.0 libmp3lame.so.0
[root@localhost opt]# ll
total 316
lrwxrwxrwx. 1 root root     19 Dec  7 23:27 libmp3lame.so.0 -> libmp3lame.so.0.0.0
-rwxr-xr-x. 1 root root 321228 Dec  7 23:25 libmp3lame.so.0.0.0
[root@localhost opt]# ldd /usr/local/bin/ffmpeg
        linux-gate.so.1 =>  (0x00cc4000)
        libavdevice.so.54 => /usr/local/lib/libavdevice.so.54 (0x00577000)
        libavfilter.so.3 => /usr/local/lib/libavfilter.so.3 (0x00e3f000)
        libavformat.so.54 => /usr/local/lib/libavformat.so.54 (0x00202000)
        libavcodec.so.54 => /usr/local/lib/libavcodec.so.54 (0x00f01000)
        libpostproc.so.52 => /usr/local/lib/libpostproc.so.52 (0x00170000)
        libswresample.so.0 => /usr/local/lib/libswresample.so.0 (0x00750000)
        libswscale.so.2 => /usr/local/lib/libswscale.so.2 (0x0035e000)
        libavutil.so.52 => /usr/local/lib/libavutil.so.52 (0x005ba000)
        libm.so.6 => /lib/libm.so.6 (0x00452000)
        libpthread.so.0 => /lib/libpthread.so.0 (0x001c0000)
        libc.so.6 => /lib/libc.so.6 (0x008c2000)
        libasound.so.2 => /lib/libasound.so.2 (0x0047c000)
        libdc1394.so.22 => /usr/local/lib/libdc1394.so.22 (0x003d6000)
        librt.so.1 => /lib/librt.so.1 (0x00db3000)
        libfreetype.so => /usr/local/lib/libfreetype.so (0x00a80000)
        libass.so.4 => /usr/local/lib/libass.so.4 (0x001db000)
        libssl.so.1.0.0 => /usr/local/lib/libssl.so.1.0.0 (0x005e7000)
        libcrypto.so.1.0.0 => /usr/local/lib/libcrypto.so.1.0.0 (0x00afb000)
        librtmp.so.0 => /usr/local/lib/librtmp.so.0 (0x00584000)
        libz.so.1 => /lib/libz.so.1 (0x00599000)
        libx264.so.132 => /usr/local/lib/libx264.so.132 (0x02bc9000)
        libvorbisenc.so.2 => /usr/local/lib/libvorbisenc.so.2 (0x05ccd000)
        libvorbis.so.0 => /usr/local/lib/libvorbis.so.0 (0x00640000)
        libvo-aacenc.so.0 => /usr/local/lib/libvo-aacenc.so.0 (0x00834000)
        libtwolame.so.0 => /usr/local/lib/libtwolame.so.0 (0x00668000)
        libtheoraenc.so.1 => /usr/local/lib/libtheoraenc.so.1 (0x00688000)
        libtheoradec.so.1 => /usr/local/lib/libtheoradec.so.1 (0x006ce000)
        libspeex.so.1 => /usr/local/lib/libspeex.so.1 (0x00815000)
        libmp3lame.so.0 => /opt/libmp3lame.so.0 (0x00767000)   //终于圆满了:)
        libfaac.so.0 => /usr/local/lib/libfaac.so.0 (0x006e8000)
        /lib/ld-linux.so.2 (0x003b6000)
        libdl.so.2 => /lib/libdl.so.2 (0x001f4000)
        libraw1394.so.11 => /usr/local/lib/libraw1394.so.11 (0x00444000)
        libfribidi.so.0 => /usr/local/lib/libfribidi.so.0 (0x006f8000)
        libfontconfig.so.1 => /usr/local/lib/libfontconfig.so.1 (0x00710000)
        libogg.so.0 => /usr/local/lib/libogg.so.0 (0x001f9000)
        libexpat.so.1 => /lib/libexpat.so.1 (0x007e3000)


   所以说,针对动态库路径查找的种种问题 ,无非就这么两大类,关键是找对原因,对症下药,方能药到病除。

阅读(36816) | 评论(5) | 转发(18) |
        <div class="Blog_con3_3">
          <div><span id="digg_num">1</span><a href="javascript:void(0)" id="digg" bid="4028681" url="/blog/digg.html"></a></div>
          <p>上一篇:<a href="/uid-23069658-id-3995439.html">多媒体技术基础之---重新认识声音</a></p>
          <p>下一篇:<a href="/uid-23069658-id-4047955.html">"2013":爱你不容易</a></p>    
        </div>
        
      </div>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

谈谈Linux下动态库查找路径的问题 的相关文章

  • CNDS博客等级

    CNDS博客积分规则 博客积分是CSDN对用户努力的认可和奖励 也是衡量博客水平的重要标准 博客等级也将由博客积分唯一决定 积分规则具体如下 1 每发布一篇原创或者翻译文章 可获得10分 2 每发布一篇转载文章 可获得2分 3 博主的文章每
  • 【2019年ICPC南昌网络赛】Distance on the tree【DFS+线段树合并(可持久化线段树)】

    题目链接 DSM Data Structure Master once learned about tree when he was preparing for NOIP National Olympiad in Informatics i
  • 动态标题_工作技巧

    本期重点 使用HASONEVALUE判断列中是否只有一个值被筛选 从而根据实际筛选的值实现动态变化 日常工作中我们经常会使用切片器来实现分析报告的动态变化 可是标题应该怎么随着数据变化呢 今天我们就来学一招 动态切换标题 01数据准备 首先
  • 你知道怎么离线安装全局 node 模块吗?

    大家平时是怎么离线安装 node 模块的呢 前言 在平时的开发中 我们一般都是通过在线安装的方式来安装 node 模块的 但是也保不齐会有离线安装的需求 比如 公司内网是不联网的 那如果需要安装模块的话怎么办 今天 我就通过离线安装全局 a
  • ADS1.2使用jlink调试程序(调试芯片s3c2440 arm9)

    一 软件安装 ADS1 2下载 http down drv5 cn www drv5 cn arm ads1 2 rar jlink驱动下载 http fastsoft onlinedown net down JLink Windows V
  • 2021-08-30

    Android Studio 你需要掌握的Debug技巧 上 对所有程序猿来说 写代码最让人头疼的不是某个难以实现的功能 而是辛辛苦苦码完代码却发现自己的程序里面存在着这样或那样的Bug 尤其是碰到那种让你绞尽脑汁 修改了无数次都解决不了的
  • Numpy实现矩阵转置的几种方法

    在矩阵操作中 经常需要对矩阵进行转置 或者需要交换矩阵的轴 下面介绍一下使用Numpy完成矩阵轴数据交换的几种方法 主要包括以下几种方法 1 T转置 适用于1 D 2 D矩阵 2 np transpose 适用于一次同时交换多个 大于两个
  • Vue压缩图片插件——localResizeIMG(简称lrz)

    使用前须知 GitHub localResizeIMG地址 这个项目已不再维护了 可能很长一段时间都不会更新了 插件演示地址 引用 npm i lrz S 注意 使用npm下载 不要使用cnpm下载 有坑 使用 import lrz fro
  • pycharm背景色和字体设置

    1 首先在pycharm打开FILE 点击seting 2 点击Editor 再点击Font可以设置字体大小 点击Color Scheme可以设置背景色 3 字体设置 点击Font可以选择不同字体 点击Size可以调节字体大小 右侧可以看预
  • django使用Paginator分页展示数据

    思路 view得到基本数据 提供给前端当前页面的数据 判断是否有上一页 下一页 url路由 前端展示 View逻辑 写一个简单的View 使用Paginator时 首先导入django core paginator Paginator类 初
  • # 和 ## 的区别

    参考 和 的区别 作者 枕上 发布时间 2021 07 25 08 23 40 网址 https blog csdn net jinchi boke article details 119076280 utm source app app
  • linux基本理论基础,Linux操作系统基础知识学习

    本文是我在学校自学Linux时所做的笔记 纯理论 希望对大家有所帮助 文章中 Q表示问题 A表示回答 Linux操作系统概述 Q1 什么是GNU Linux与GNU有什么关系 A 1 GNU是GNU is Not Unix的递归缩写 是自由
  • RevitAPI: Revit中求两条直线的夹角XYZ.AngleTo

    有时候我们并不知道一个函数可能会有什么行为 例如XYZ AngleTo的返回值是0 2 还是0 又找不到对应的文档 那就干脆自己动手测试一下了 代码如下 Line line1 Line CreateBound new XYZ 0 0 0 n
  • 浏览器适配Viewport 布局

    目标 使用postcss px to viewport将px单位自动转化为w h单位 安装 npm install postcss px to viewport 配置文件 根目录下新建postcss config js 复制下面代码 mod
  • QDU 算法考试复习

    第一章 算法概述 主定理 算法满足4条性质 1 输入 有零个或多个由外部提供的量作为算法的输入 2 输出 至少一个量作为输出 3 确定性 每条指令是清晰的 无歧义的 4 有限性 每条指令的执行次数是有限的 执行时间也是有限的 算法与程序的区
  • 发现【Stable-Diffusion WEBUI】的插件:不健康内容过滤器

    文章目录 零 前言 一 不健康内容过滤器 NSFW Sensor 零 前言 本篇主要提到了WEBUI的不健康内容过滤插件 它宁可错杀一千也不放过一个 可以有效避免有害内容 更多不断丰富的内容参考 继续Stable Diffusion WEB
  • odoo12从零开始:一、安装odoo运行环境(windows10)

    前言 鉴于好多朋友说没有mac电脑 windows开发其实也差不了多远 只是个人习惯问题 而且吧 windows的电脑其实配环境也挺快的其实 我在这里再稍微补一个比较简单的windows环境部署 希望可以对朋友们有一些帮助 在windows
  • 运算放大器积分电路及积分电路设计

    运算放大器积分电路及积分电路设计 积分电路 Integrator circuit 在运算放大器积分器电路中 电容器插入反馈环路中 并在反相输入端与R1一起产生一个RC时间常数 积分的物理意义 积分的物理意义我们经常会使用到 例如下面的几个例
  • 交叉编译Cubietruck的u-boot

    1 下载u boot源码 mkdir cubietruck cd cubietruck git clone https github com linux sunxi u boot sunxi git

随机推荐

  • CSS基础之动画

    动画 1 过渡 需要结合鼠标 动画 网页只要运行动画就可以立即生效 创建动画的方式 1 方式一 from 起点 to 终点 keyframes 动画的名字 from to 2 方式二 keyframes 动画的名字 0 100 如果一个元素
  • ICPC Latin American Regional – 2017 Jumping Frog

    Pog the Frog wants to compete in the World Frog Jump competition which will take place in Nlogonia In the competition ea
  • 前端代码规范

    9个前端代码规范秘籍 让你也能写出诗一样的代码 9个秘籍里边有6个文档 1本书和2个工具 如果你耐心看完 一定会提升代码质量 让你写出漂亮的代码 第一个秘籍 京东凹凸实验室前端代码规范 网址是 https guide aotu io 如果你
  • CTFHub技能树 Web-SQL注入 详解

    目录 整数型注入 字符型注入 报错注入 布尔盲注 时间盲注 MySQL结构 Cookie注入 UA注入 Refer注入 过滤空格 整数型注入 我们输入 1 不断尝试发现闭合方式就是 1 整数型 存在两列 order by 2 存在两个注入点
  • JBOSS4.2.2 Spring2.0.8 web中调用EJB异常

    从容器外能够正常调用EJB 但是web 应用中spring bean调用EJB出现下面异常
  • 深度学习分类基础概念对ACC、PPV、TPR、TNR

    举个例子 ACC 10 15 20 10 1 2 3 14 4 5 6 20 PPV 猫 10 10 1 2 解释 这里的1和2是因为狗 猪分类错误 分到了猫 PPV 狗 15 15 3 4 PPV 猪 20 20 5 6 TPR 猫 10
  • UDP与TCP报头介绍,三次握手与四次挥手详谈

    先介绍我们UDP TCP协议缓冲区 在UDP和TCP在数据传输和介绍时有有缓冲区概念的 UDP缓冲区 UDP没有真正意义上的 发送缓冲区 调用sendto会直接交给内核 由内核将数据传给网络层协议进行后 续的传输动作 UDP具有接收缓冲区
  • Python—retrying模块的使用

    使用超时参数能够加快我们整体的运行速度 但是在普通的生活中当我们使用浏览器访问网页时 如果发生速度很慢的情况 我们会做的选择是刷新页面 那么在代码中 我们是否也可以刷新请求呢 对应的 retrying模块就可以帮助我们解决 1 retryi
  • Quality Center设置开发人员修改bug状态

    使用QC时遇到了一个问题 将开发人员分配到QC默认的Developer的组中后 开发人员不能修改bug的状态 提示无权限操作 经查看原来是QC默认的Developer组对bug的权限没有 新建 gt 打开 这一操作 只有Project Ma
  • (十二)python网络爬虫(理论+实战)——实战:使用BeautfulSoup解析baidu热搜新闻数据

    系列文章 python网络爬虫专栏 目录 序言 本节学习目标 特别申明 4 7 使用BeautfulSoup解析h
  • Idea项目爆红

    解决办法 方案一 重新加载Maven依赖 方案二 清除缓存 方案三 在当前项目下执行以下命令 重新生成 iml文件 mvn idea module
  • 利用java制作桌面应用程序_Java桌面应用

    对于作Java桌面应用来说 比较烦人的就是安装部署问题 客户端是否安装有jre jre版本问题 jre去哪下载 如 何用jre启动你的Java应 用 不要说刚接触电脑的人 就算是比较熟悉电脑 如果没有接触过Java 面对一个Java应用 如
  • Mysql复习总结

    目录标题 数据库特性 原子性 一致性 隔离性 持久性 Mysql事务所存在的问题 数据库隔离级别 Mysql中的log bin log VS redo log MVCC ACID如何被保证的 存储引擎 Innodb 和 MyISAM Inn
  • 百度云盘分享:MySQL零基础入门视频教程!

    百度云盘分享 MySQL零基础入门视频教程 首先给大家介绍一下数据库工程师 数据库工程师 Database Engineer 是从事管理和维护数据库管理系统 DBMS 的相关工作人员的统称 他属于运维工程师的一个分支 主要负责业务数据库从设
  • spark内存调优

    executor内存 1 RDD存储 persist cache操作 RDD持久化在executor中 注 UnifiedMemoryManager模式可设置spark storage memoryFraction调节 默认0 6 2 sh
  • 机器学习——决策树/随机森林

    0 前言 决策树可以做分类也可以做回归 决策树容易过拟合 决策树算法的基本原理是依据信息学熵的概念设计的 Logistic回归和贝叶斯是基于概率论 熵最早起源于物理学 在信息学当中表示不确定性的度量 熵值越大表示不确定性越大 ID3算法就是
  • nginx启动报错

    nginx启动报错 nginx报错如下 nginx emerg bind to 0 0 0 0 80 failed 10013 An attempt was made to access a socket in a way forbidde
  • python爬虫xpath教程

    环境准备 pycharm 撩妹神器 人手一个 lxml python的三方库 如果电脑里没有安装lxml的伙伴 可以安装一下 在控制台输入pip intall https pypi douban com simple lxml 利用国外的源
  • Vim编辑器

    1 Vim两种状态 命令状态 按i或者a可以进入编辑状态 编辑状态 左下角有insert 在命令状态下 有一些常用命令 新增 a 从光标后开始添加文本 A 从光标所在行的末尾开始添加文本 插入 i 从光标前面开始插入文本 I 从光标所在行的
  • 谈谈Linux下动态库查找路径的问题

    p p div class Blog wz1 span style font size 16px nbsp nbsp nbsp 学习到了一个阶段之后 就需要不断的总结 沉淀 清零 然后才能继续 上路 回想起自己当年刚接触Linux时 不管是