linux动态库查找路径以及依赖关系梳理

编译时与运行时库的路径

linux下,编译时与运行时库的搜索路径是不同的

运行时动态库的路径搜索顺序

  1. LD_PRELOAD环境变量,一般用于hack

  2. 编译目标代码时指定的动态库搜索路径(指的是用 -wl,rpath 或-R选项而不是-L),readelf -d命令可以查看编译的目标文件中rpath参数;

    gcc -Wl,-rpath,/home/arc/test,-rpath,/usr/local/lib test.c
    
  3. 环境变量LD_LIBRARY_PATH指定的动态库搜索路径;

    export LD_LIBRARY_PATH=/root/test/env/lib
    ./main
    

    或者

    LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH ./main
    
  4. 配置文件 /etc/ld.so.conf 中指定的动态库搜索路径;

    将动态库路径追加到/etc/ld.so.conf文件或者/etc/ld.so.conf.d/目录下的文件后,记得一定要执行ldconfig 命令,该命令会将配置的所有路径下的库载入缓存文件/etc/ld.so.cache

    [root@callinglove ~]# cat /etc/ld.so.conf
    include ld.so.conf.d/*.conf
    /opt/opencv3.4.3/lib64
    [root@callinglove ~]# ldconfig 
    [root@callinglove ~]# ldconfig -p | grep opencv_corelibopencv_core.so.3.4 (libc6,x86-64) => /opt/opencv3.4.3/lib64/libopencv_core.so.3.4libopencv_core.so (libc6,x86-64) => /opt/opencv3.4.3/lib64/libopencv_core.so[root@callinglove ~]# cat /etc/ld.so.conf.d/mysql-x86_64.conf 
    /usr/lib64/mysql
    [root@callinglove ~]# ls /usr/lib64/mysql/
    libmysqlclient_r.so.18  libmysqlclient_r.so.18.1.0  libmysqlclient.so.18  libmysqlclient.so.18.1.0  libmysqlclient.so.21  libmysqlclient.so.21.1.17  mecab  plugin
    [root@callinglove ~]# ldconfig -p | grep libmysqlclientlibmysqlclient.so.21 (libc6,x86-64) => /usr/lib64/mysql/libmysqlclient.so.21libmysqlclient.so.18 (libc6,x86-64) => /usr/lib64/mysql/libmysqlclient.so.18
    

    mysql8将动态库的路径添加到/etc/ld.so.conf.d目录下的一个单独的conf文件中,也能完成配置,并且不会影响到其他的配置

  5. 默认的动态库搜索路径 /lib;

  6. 默认的动态库搜索路径 /usr/lib

编译时查找库的搜索路径

  1. 编译时使用 -L 指定库的路径;
    gcc main.c -o main -L./ -lcac
  2. 通过环境变量LIBRARY_PATH指定搜索路径
    LIBRARY_PATH=.:$LIBRARY_PATH gcc main.c -o main -lcac
  3. 系统标准路径/lib /usr/lib /usr/local/lib

比较

  1. 编译时查找的是静态库或动态库,而运行时查找的只是动态库;
  2. gcc参数 -L 指定编译时的链接路径,-Wl,-rpath 指定运行时链接路径;
  3. 编译时使用环境变量LIBRARY_PATH指定库的路径,运行时使用环境变量LD_LIBRARY_PATH/etc/ld.so.conf 指定库的路径;
  4. 编译时用的链接器是ld,而运行时用的链接器是 /lib/ld-linux.so.2;
  5. 编译时与运行时都会查找默认路径:/lib /usr/lib;
  6. 编译时还有一个默认路径:/usr/local/lib,而运行时不会默认找查该路径。

环境变量指定头文件的搜索路径

C_INCLUDE_PATH、CPLUS_INCLUDE_PATH以及CPATH常被用于在全局性地添加预处理C/C++时的包含目录,其中C_INCLUDE_PATH仅对预处理C有效,CPLUS_INCLUDE_PATH仅对预处理C++有效,而CPATH对所有语言均有效。

export C_INCLUDE_PATH=/usr/local/libevent/include${C_INCLUDE_PATH:+:${C_INCLUDE_PATH}}
export CPLUS_INCLUDE_PATH=/usr/local/opencv3.2/include${CPLUS_INCLUDE_PATH:+:${CPLUS_INCLUDE_PATH}}
  • 查看gcc预处理C时的的搜索目录 echo | gcc -x c -v -E -
  • 查看gcc预处理C++时的的搜索目录echo | gcc -x c++ -v -E -
  • 查看clang预处理C++时的搜索目录echo | clang -x c++ -v -E -

pkg-config

在大多数开源代码中autotool工具使用pkg-config命令来获取第三方库的相关编译与连接参数的

# pkg-config --help
Usage:pkg-config [OPTION?]Help Options:-h, --help                              Show help optionsApplication Options:--version                               output version of pkg-config--modversion                            output version for package--atleast-pkgconfig-version=VERSION     require given version of pkg-config--libs                                  output all linker flags--static                                output linker flags for static linking--short-errors                          print short errors--libs-only-l                           output -l flags--libs-only-other                       output other libs (e.g. -pthread)--libs-only-L                           output -L flags--cflags                                output all pre-processor and compiler flags--cflags-only-I                         output -I flags--cflags-only-other                     output cflags not covered by the cflags-only-I option--variable=NAME                         get the value of variable named NAME--define-variable=NAME=VALUE            set variable NAME to VALUE--exists                                return 0 if the module(s) exist--print-variables                       output list of variables defined by the module--uninstalled                           return 0 if the uninstalled version of one or more module(s) or their dependencies will be used--atleast-version=VERSION               return 0 if the module is at least version VERSION--exact-version=VERSION                 return 0 if the module is at exactly version VERSION--max-version=VERSION                   return 0 if the module is at no newer than version VERSION--list-all                              list all known packages--debug                                 show verbose debug information--print-errors                          show verbose information about missing or conflicting packages,default if --cflags or --libs given on the command line--silence-errors                        be silent about errors (default unless --cflags or --libsgiven on the command line)--errors-to-stdout                      print errors from --print-errors to stdout not stderr--print-provides                        print which packages the package provides--print-requires                        print which packages the package requires--print-requires-private                print which packages the package requires for static linking

以ffmpeg中的libavcodec库为例做一个简单说明

# cat /usr/lib64/pkgconfig/libavcodec.pc
prefix=/usr
exec_prefix=${prefix}
libdir=/usr/lib64
includedir=/usr/include/ffmpegName: libavcodec
Description: FFmpeg codec library
Version: 57.107.100
Requires: 
Requires.private: libswresample >= 2.9.100, libavutil >= 55.78.100
Conflicts:
Libs: -L${libdir}  -lavcodec 
Libs.private: -lXv -lX11 -lXext -lfontconfig -lfreetype -lSDL2 -lv4l2 -lpulse -lmodplug -ldrm -lbluray -lass -lgnutls -lgcrypt -ldl -lgpg-error -lSDL2 -lmfx -lstdc++ -ldl -lva-drm -lva-x11 -lva -lvdpau -lX11 -lva -lva-x11 -lX11 -lva -lva-drm -lva -lxcb -lxcb-shm -lxcb-xfixes -lxcb-shape -lcdio_paranoia -lcdio_cdda -lcdio -ljack -lasound -lSDL2 -lgcrypt -ldl -lgpg-error -lGL -lOpenCL -lopenal -lzvbi -lxvidcore -lx265 -lx264 -lvpx -lm -lvpx -lm -lvpx -lm -lvpx -lm -lvorbisenc -lvorbis -lm -logg -lvorbis -lm -logg -lvo-amrwbenc -lvidstab -lm -lgomp -lv4l2 -ltheoraenc -ltheoradec -logg -lspeex -lsoxr -lrsvg-2 -lm -lgio-2.0 -lgdk_pixbuf-2.0 -lcairo -lgobject-2.0 -lglib-2.0 -lpulse -lopus -lopenjp2 -lopencore-amrwb -lopencore-amrnb -lmp3lame -lmodplug -lmfx -lstdc++ -ldl -lva-drm -lva-x11 -lva -lgsm -lfribidi -lfreetype -lfontconfig -lfreetype -ldrm -lbluray -lass -lgnutls -lm -ldl -lbz2 -lz -pthread
Cflags: -I${includedir}

pkg-config的工作原理是根据指定库名称的pc文件获取相应编译参数

# pkg-config libavcodec --print-requires     // 依赖  {Requires}
# pkg-config libavcodec --print-provides     // 库提供者 {Name}:{Version}
libavcodec = 57.107.100
# pkg-config libavcodec --print-requires-private   // 库依赖的库 {Requires.private}
libswresample >= 2.9.100
libavutil >= 55.78.100
# pkg-config libavcodec --libs		// 连接该动态库时使用的连接选项  {Libs}
-lavcodec  
# pkg-config libavcodec --cflags    // 编译时使用的编译选项  {Cflags}
-I/usr/include/ffmpeg  
# pkg-config libavcodec --libs --static  // 使用静态库时使用的连接参数  {Libs} {Libs.private} {Requires.private}
-pthread -lavcodec -lXv -lXext -lvdpau -lX11 -lxcb -lxcb-shm -lxcb-xfixes -lxcb-shape -lcdio_paranoia -lcdio_cdda -lcdio -ljack -lasound -lSDL2 -lgcrypt -lgpg-error -lGL -lOpenCL -lopenal -lzvbi -lxvidcore -lx265 -lx264 -lvpx -lvorbisenc -lvorbis -lvo-amrwbenc -lvidstab -lgomp -lv4l2 -ltheoraenc -ltheoradec -logg -lspeex -lrsvg-2 -lgio-2.0 -lgdk_pixbuf-2.0 -lcairo -lgobject-2.0 -lglib-2.0 -lpulse -lopus -lopenjp2 -lopencore-amrwb -lopencore-amrnb -lmp3lame -lmodplug -lmfx -lstdc++ -lva-drm -lva-x11 -lva -lgsm -lfribidi -lfontconfig -lfreetype -lbluray -lass -lgnutls -ldl -lbz2 -lz -lswresample -lsoxr -lavutil -ldrm -lm  
# pkg-config libavcodec --cflags --static
-I/usr/include/ffmpeg

可以看出使用库的静态库使用,连接时需要连接该静态库以及静态库依赖的库(如果是静态库,需要安装依赖的开发包,yum安装的运行时库都是后缀有版本号的,连接时查找的动态库不带版本号)

连接顺序问题

https://gcc.gnu.org/onlinedocs/gcc-5.2.0/gcc/Link-Options.html#Link-Options

动态库使用实例

定义库的头文件

/*caculate.h*/#ifndef CACULATE_HEAD_
#define CACULATE_HEAD_
//加法
int add(int a, int b);
//减法
int sub(int a, int b);
//除法
int div(int a, int b);
//乘法
int mul(int a, int b);#endif

库中函数的实现

/*caculate.c文件*/
#include "caculate.h"//求两个数的和
int add(int a, int b)
{return (a + b);
}
//减法
int sub(int a, int b)
{return (a - b);
}
//除法
int div(int a, int b)
{return (int)(a / b);
}
//乘法
int mul(int a, int b)
{return (a * b);
}

编译生产libcac.so文件如下: gcc -shared -fPIC caculate.c -o libcac.so

动态库的使用方法1

#include <stdio.h>
#include "caculate.h"int main()
{int a = 20;int b = 10;printf("%d + %d = %d\n", a, b, add(a, b));printf("%d - %d = %d\n", a, b, sub(a, b));printf("%d / %d = %d\n", a, b, div(a, b));printf("%d * %d = %d\n", a, b, mul(a, b));return 0;
}

编译运行:

gcc main.c -o main -L ./ -lcac
LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH ./main

动态库的使用方法2

#include <stdio.h>
#include <dlfcn.h>#define DLL_FILE_NAME "libcac.so"int main()
{void *handle;int (*func)(int, int);char *error;int a = 30;int b = 5;handle = dlopen(DLL_FILE_NAME, RTLD_NOW);if (handle == NULL){fprintf(stderr, "Failed to open libaray %s error:%s\n", DLL_FILE_NAME, dlerror());return -1;}func = dlsym(handle, "add");printf("%d + %d = %d\n", a, b, func(a, b));func = dlsym(handle, "sub");printf("%d + %d = %d\n", a, b, func(a, b));func = dlsym(handle, "div");printf("%d + %d = %d\n", a, b, func(a, b));func = dlsym(handle, "mul");printf("%d + %d = %d\n", a, b, func(a, b));dlclose(handle);return 0;
}

编译运行

gcc call_main.c -o call_main -ldl -Wl,-rpath,./
./main

这里写图片描述

依赖静态库,编译生成动态库

opencv的动态库依赖一个三方静态库libippicv.a

$ PKG_CONFIG_PATH=/usr/local/opencv/lib/pkgconfig pkg-config --libs opencv
-L/usr/local/opencv3.1.0/lib -L/usr/local/opencv3.1.0/share/OpenCV/3rdparty/lib -lopencv_shape -lopencv_stitching -lopencv_objdetect -lopencv_superres -lopencv_videostab -lippicv -lopencv_calib3d -lopencv_features2d -lopencv_highgui -lopencv_videoio -lopencv_imgcodecs -lopencv_video -lopencv_photo -lopencv_ml -lopencv_imgproc -lopencv_flann -lopencv_core  
$ PKG_CONFIG_PATH=/usr/local/opencv/lib/pkgconfig pkg-config --cflags opencv
-I/usr/local/opencv3.1.0/include/opencv -I/usr/local/opencv3.1.0/include
  • 依赖静态库,编译生成动态库

动态库版本兼容问题

  • GCC选项_-Wl,-soname
  • 查看动态库so命令

动态库与静态库同时存在

  • linux程序同时链接动态库与静态库
  • 使用Automake生成Makefile及动态库和静态库的创建

参考

  • linux下运行时链接库的路径顺序
  • Linux动态链接库的使用
  • 技巧:Linux 动态库与静态库制作及使用详解
  • libc.so兼容问题
  • 利用LD_PRELOAD给glibc库函数加钩子
  • 警惕UNIX下的LD_PRELOAD环境变量

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/508666.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

eclipse--android开发环境搭建教程

引言 在windows安装Android的开发环境不简单也说不上算复杂&#xff0c;但由于国内无法正常访问google给android开发环境搭建带来不小的麻烦。现将本人搭建过程记录如下&#xff0c;希望会对投身android开发的小伙伴有所帮助。 android开发环境部署过程 安装JDK环境 下载安装…

eclipse--python开发环境搭建

pydev插件介绍 PyDev is a Python IDE for Eclipse pydev官方网站&#xff1a;http://www.pydev.org/ 在Eclipse中安装pydev插件 启动Eclipse, 点击Help->Install New Software… 在弹出的对话框中&#xff0c;点Add 按钮。 Name中填:Pydev, Location中填http://pydev.or…

Win7虚拟无线AP以及Android手机抓包

设备要求 Windows7操作系统装有无线网卡的笔记本或台式机无线网卡必须支持“承载网络” 查看无线网卡是否支持“承载” 方法一: 开始菜单→所有程序→附件→命令提示符→右键“以管理员权限运行”; 键入命令“netsh wlan show drivers”,查看“支持承载网络”这一项,如果是…

CMD命令之BAT脚本路径信息

CD命令解疑 cd是chdir的缩写&#xff0c;命令详解参见cd /? 可以看到/d参数的解释如下&#xff1a; 使用 /D命令行开关&#xff0c;除了改变驱动器的当前目录之外&#xff0c;还可改变当前驱动器。 通常我们在xp系统中打开cmd窗口时&#xff0c;会显示 C:\Documents and Se…

【ubuntu 22.04】安装vscode并配置正常访问应用商店

注意&#xff1a;要去vscode官网下载deb安装包&#xff0c;在软件商店下载的版本不支持输入中文 在ubuntu下用火狐浏览器无法访问vscode官网&#xff0c;此时可以手动进行DNS解析&#xff0c;打开DNS在线查询工具&#xff0c;解析以下主机地址&#xff08;复制最后一个IP地址&a…

卷积与傅立叶变换

一、卷积 1、一维的卷积 连续&#xff1a; 在泛函分析中&#xff0c;卷积是通过两个函数f(x)f(x)和g(x)g(x)生成第三个函数的一种算子&#xff0c;它代表的意义是&#xff1a;两个函数中的一个(我取g(x)g(x)&#xff0c;可以任意取)函数&#xff0c;把g(x)g(x)经过翻转平移,…

OpenCV-Python bindings是如何生成的(2)

OpenCV-Python bindings生成流程 通过上篇文章和opencv python模块中的CMakeLists.txt文件&#xff0c;可以了解到opencv-python bindings生成的整个流程: 生成headers.txt文件 将每个模块的头文件添加到list中&#xff0c;通过一些关键词过滤掉一些不需要扩展的头文件&#x…

tcp状态机-三次握手-四次挥手以及常见面试题

TCP状态机介绍 在网络协议栈中&#xff0c;目前只有TCP提供了一种面向连接的可靠性数据传输。而可靠性&#xff0c;无非就是保证&#xff0c;我发给你的&#xff0c;你一定要收到。确保中间的通信过程中&#xff0c;不会丢失数据和乱序。在TCP保证可靠性数据传输的实现来看&am…

CentOS7开发环境搭建(1)

文章目录BIOS开启VT支持U盘安装系统(2019-03-11)CentOS DNS配置CentOS网络配置配置静态IP克隆虚拟机网卡名称变更 CentOS6.5时间配置安装VMWare-tools用户管理 (2019-03-15 7.6.1810)给一般账号 root 权限Samba服务配置安装必备软件获取本机公网ipyum源和第三方库源管理配置本地…

NS2相关学习——创建Xgraph的输出文件

经过前面学习代码的编写&#xff0c;这一部分&#xff0c;我们要学会如何进行分析&#xff0c;一个很直观的方式就是将结果图形化表示出来。 ns-allinone包的一部分是“xgraph”&#xff0c;一个绘图程序&#xff0c;可用于创建模拟结果的图形表示。 在本节中&#xff0c;将向…

An Energy-Efficient Ant-Based Routing Algorithm for Wireless Sensor Networks (无线传感网中基于蚁群算法的能量有效路由)2

牙说&#xff1a;接着上一篇继续写。论文标题&#xff1a;An Energy-Efficient Ant-Based Routing Algorithm forWireless Sensor Networks作者&#xff1a;Tiago Camilo, Carlos Carreto, Jorge S Silva, Fernando Boavida正文&#xff1a; 2、相关工作可以考虑无线传感器网络…

NS2仿真分析无线网络的攻击防御(1)

这个学期有个选题是NS2仿真分析无线网络的攻击防御&#xff0c;比较有意思的样子&#xff0c;现在来慢慢学一下这个是什么东西。 首先&#xff0c;还是一篇文章&#xff08;老长老长了&#xff09;&#xff0c;还是全英文的&#xff0c;还是先来分析一下它到底在说什么&#x…

Java集合之HashMap源码分析

以下源码均为jdk1.7 HashMap概述 HashMap是基于哈希表的Map接口的非同步实现. 提供所有可选的映射操作, 并允许使用null值和null健. 此类不保证映射的顺序. 需要注意的是: HashMap不是同步的. 哈希表 哈希表定义: 哈希表是一种根据关键码去寻找值的数据映射结构, 该结构通…

NS2相关学习——可靠的MANET应用程序的Gossip协议分析

好久不写&#xff0c;应该努力啦&#xff01;老师把这篇论文给了我&#xff0c;现在还不知道它在讲什么&#xff0c;来边翻译边学习吧&#xff01; 文章链接&#xff1a;https://www.researchgate.net/publication/316844643_Analyzing_Gossip_Protocols_for_Reliable_MANET_Ap…

Java集合之LinkedList源码分析

概述 LinkedLIst和ArrayLIst一样, 都实现了List接口, 但其内部的数据结构不同, LinkedList是基于链表实现的(从名字也能看出来), 随机访问效率要比ArrayList差. 它的插入和删除操作比ArrayList更加高效, 但还是要遍历部分链表的指针才能移动到下标所指的位置, 只有在链表两头的…

lex和yacc环境配置

lex和yacc的使用很简单&#xff0c;但环境配置却是各种问题&#xff0c;本章说明lex和yacc在windows下的环境配置。 软件需求&#xff1a; 系统 win7-64位(win7-32, win8, win10全部通过) c编译器&#xff1a; vs2010(2008,2013,2015也全部通过) lex和yacc编译器&#xff1a…

Java集合之Vector源码分析

概述 Vector与ArrayLIst类似, 内部同样维护一个数组, Vector是线程安全的. 方法与ArrayList大体一致, 只是加上 synchronized 关键字, 保证线程安全, 下面就不具体分析源码了, 具体可以查看ArrayList中的源码分析. Vector源码分析 1.主要字段 2.构造函数 3.增删改查 其他方法…

Gossip协议的P2P会员管理

阅读此论文主要目的在于理解gossip协议及其背后的原理&#xff0c;此部分详细翻译&#xff0c;其余部分看时间 文章标题&#xff1a;Gossip协议的P2P会员管理 作者&#xff1a;Ayalvadi J. Ganesh, Anne-Marie Kermarrec, and Laurent Massoulie Abstract&#xff1a;基于…

Java集合之LinkedHashSet源码分析

概述 LinkedHashSet与HashSet类似, 不同的是LinkedHashSet底层使用LinkedHashMap维护元素插入的顺序. LinkedHashSet继承自HashSet, 只是重写了HashSet的构造方法, 初始化一个LinkedHashMap, 其他均与HashSet相同. LinkedHashSet构造方法 HashSet的构造方法: 以上几乎就是Li…

Java集合之ArrayList源码分析

概述 ArrayList可以理解为动态数组, 根据MSDN的说法, 就是Array的复杂版本. 与数组相比, 它的容量能动态增长. ArrayList是List接口的可变数组的实现. 实现了所有可选列表操作, 允许包括null在内的所有元素. 数组的特点, 查询快增删慢. 每个ArrayList实例都有一个容量, 该容…