C/C++程序编译与链接(五) 定位库文件


定位库文件包括两个方面:

  • 在程序构建时,需要知道所依赖库的位置及头文件。
  • 在程序运行时,需要知道所依赖库的位置,只针对动态库。

只有动态库在程序运行时加载,静态库是构建时就已经链接到程序中。

在构建过程中定位库

静态库的命名规则

lib + library name +.a

library name才是静态库实际的名字,比如libtest.a,库名为test

动态库的命名规则

lib + library name + .so + library version information

动态库相比静态库多了库的版本信息,指定了版本信息后,库名一样版本不同也是不同的库,因为包含的符号不同。经常遇见依赖多个不同版本的动态,版本号是区分这些库的重要方式。
库的实际名字也是library name
在构建时不管是依赖的静态库还是动态库,指定所依赖的库的路径都是一致的,通过通过-L-l选项来指定构建过程中库文件的路径。
gcc main.o -L../lib -ltestlib -o test
-L是指定库的目录,-l是指定库名就是库的实际名字,-ltestlib对应的库为libtestlib.so或libtestlib.a

  • -L告诉编译器用于定位库的目录。
  • -l 对于动态库,指定的库名还会写入最终生成的执行文件,在程序运行时,加载器会查找指定的库,但是定位库的规则就不是按-L的规则了。

-l后面也可以跟路径+库名的方式,比如:
gcc main.o -l/home/test/lib/libtestlib.so -o test
但是这种方式,-l后面的内容会全部写入执行文件,在程序运行时,加载器会按照固定的位置/home/test/lib/libtestlib.so加载动态库。如果编译机与运行机不一样,那么就会因为找不到库而运行失败。

运行时动态库的定位规则

按照优先级的如下规则:

  1. LD_LIBRARY_PATH
  2. ld.so.cache
  3. 默认库路径(/lib/和/usr/lib等)

动态库的定位,还有更高优先级的rpathrunpath,这两个值会被写入动态库或执行程序ELF文件。但是这个两个配置的决策过程比较复杂,并且还面临着gcc版本不同处理方式不同的问题。所以这里没有列出它们。通常我们使用LD_LIBRARY_PATHldconfig就足以。

LD_LIBRARY_PATH

设置环境变量LD_LIBRARY_PATH是我们在开发过程中经常使用的方式,但这并不是标准方式,通常临时验证下程序的正确性,可以配置该环境变量,如下:

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:动态库目录

ld.so.cache

ld.so.cache是加载器(ld.sold-linux.so)的定位库目录的缓存文件。可以通过ldconfig工具更新它。
一种标准的代码部署过程是基于ldconfig工具,它通常是包安装过程中的最后一步,通常需要将指向包含库目录的路径作为出输入参数传递,将其写入ld.so.cache文件,保证加载器能定位到所依赖的库。

ldconfig creates the necessary links and cache to the most recent shared libraries found in the directories specified on the command line, in the file /etc/ld.so.conf, and in the trusted directories (/lib and /usr/lib).

ldconfig会搜索指定的目录,/etc/ld.so.conf,系统库默认目录/lib/usr/lib。将其中库的路径信息写入/etc/ld.so.cach,它被链接器(ld.sold-linux.so)用于查找依赖库。

ldconfig还有一个重要的功能是更新动态库的版本,这个会在后面的文件详细介绍。

所以当我们需要定位我们自己的所依赖的库时,可以将目录直接写入/etc/ld.so.conf中,但是/etc/ld.so.conf通常是如下内容:

cat /etc/ld.so.conf
include ld.so.conf.d/*.conf

**include ld.so.conf.d/*.conf**表示包含了**/etc/ld.so.conf.d/**目录下所有文件,所以我们通常是在该目录下建立一个包含所依赖库目录的conf文件。

#ls -lrt /etc/ld.so.conf.d/
-rw-r--r-- 1 root root 19 89 2019 dyninst-x86_64.conf
-rw-r--r-- 1 root root 17 43 2020 mariadb-x86_64.conf
-rw-r--r-- 1 root root 26 61 2020 bind-export-x86_64.conf
-r--r--r-- 1 root root 63 826 2020 kernel-3.10.0-1127.19.1.el7.x86_64.conf
#ldconfig

再通过ldconfig让其更新目录到/etc/ld.so.cach文件中,可以通过ldconfig -p查看cach中缓存的动态库及其路径信息,确认是否已经写入(ldconfig -p | grep 依赖的动态库)。

猜你喜欢

转载自blog.csdn.net/mo4776/article/details/129695085