Closed fooofei closed 5 years ago
$ ldconfig -p
344 libs found in cache `/etc/ld.so.cache'
makefile
中写了 -L 能解决项目编译生成过程中的 undefined reference 或者 undefined symbol ,
但是拿着我们的二进制到其他机器运行的时候,就可能找不到某个 .so
,这时候可以在 makefile
中使用
-Wl,rpath=<your_lib_dir>
指定一个存放运行使用到的众多 .so
目录,在运行的时候,会去这个目录找。
使用 readelf -d <ELF>
能看到这个目录。
比如我们的项目里用到了 curl,
我们 yum -y install libcurl-devel
肯定是没问题的,include
文件和 /usr/lib64/libcurl.so
都会有。
但是我不想做这一步。
我发现我的机器上本来就有
$ ll /usr/lib64/libcurl.so*
lrwxrwxrwx. 1 root root 16 3月 12 14:11 /usr/lib64/libcurl.so.4 -> libcurl.so.4.3.0
-rwxr-xr-x. 1 root root 425K 2月 2 12:49 /usr/lib64/libcurl.so.4.3.0
只是缺少 ln -s /usr/lib64/libcurl.so.4.3.0 /usr/lib64/libcurl.so
。
这一步显然我们是不能多做的,不然拿到我们代码的人,都要这么操作一遍。 如何从我们的项目入手呢?
这里说在 makefile 里写 -l:<full name>
https://stackoverflow.com/questions/828053/how-do-you-link-to-a-specific-version-of-a-shared-library-in-gcc
我试了下,还真行。
这里没有解释 https://gcc.gnu.org/onlinedocs/gcc-4.6.4/gcc/Link-Options.html
这里有解释 https://sourceware.org/binutils/docs-2.18/ld/Options.html
-lnamespec
--library=namespec
节,If namespec is of the form :filename, ld will search the library path for a file called filename, otherise it will search the library path for a file called libnamespec.a.
遇到的问题:
编译链接通过, 但是 ldd -r 有的能自动找到 /usr/lib64
/usr/local/lib
目录的文件,挺好,有的找不到,还把自己的全路径写进去了.
$ readelf -d <>
Dynamic section at offset 0x27bd08 contains 38 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [librt.so.1]
0x0000000000000001 (NEEDED) Shared library: [libm.so.6]
0x0000000000000001 (NEEDED) Shared library: [libdl.so.2]
0x0000000000000001 (NEEDED) Shared library: [libanl.so.1]
0x0000000000000001 (NEEDED) Shared library: [libnsl.so.1]
0x0000000000000001 (NEEDED) Shared library: [libcurl.so.4]
0x0000000000000001 (NEEDED) Shared library: [libmysqlclient.so.18]
0x0000000000000001 (NEEDED) Shared library: [/docker_host/xxx/src/lib/cjson/libcjson.so.1.5.5]
0x0000000000000001 (NEEDED) Shared library: [/docker_host/xxx/src/lib/cjson/libcjson_utils.so.1.5.5]
0x0000000000000001 (NEEDED) Shared library: [libz.so.1]
0x0000000000000001 (NEEDED) Shared library: [libzmq.so.5]
0x0000000000000001 (NEEDED) Shared library: [libpthread.so.0]
0x0000000000000001 (NEEDED) Shared library: [libgcc_s.so.1]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x000000000000000f (RPATH) Library rpath: [/usr/lib64/mysql:/data/lib:/usr/local/lib]
ld.so.cache
有时候疑惑,写的项目里没有写过那个
path
,但是ldd -r <elf>
能看到引用那个path
下的一个.so
文件。后来找到原因,是因为在
/etc/ld.so.conf.d
目录下,存在一个xxx.conf
文件记录了这个path
。所以会从这个path
下寻找.so
文件。验证:
当我删除
/etc/ld.so.conf.d
下的那个xxx.conf
文件后,运行ldconfig
( 修改完/etc/ld.so.conf.d
,要运行这个命令,是为了更新缓存文件/etc/ld.so.cache
,而/etc/ld.so.cache
才是 ELF 文件使用的。 ), 再次运行ldd -r <ELF>
验证不再去那个path
目录下寻找.so
文件了。ELF
会依据这个目录中文件的指引去加载.so
,这些步骤都是手动的,与ELF
文件所在的项目无关,不是修改项目makefile
做到的。ld
这个命令就是去/etc/ld.so.conf.d
目录找的。