日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > linux >内容正文

linux

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

發(fā)布時(shí)間:2024/8/23 linux 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux动态库查找路径以及依赖关系梳理 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

編譯時(shí)與運(yùn)行時(shí)庫的路徑

linux下,編譯時(shí)與運(yùn)行時(shí)庫的搜索路徑是不同的

運(yùn)行時(shí)動(dòng)態(tài)庫的路徑搜索順序

  • LD_PRELOAD環(huán)境變量,一般用于hack

  • 編譯目標(biāo)代碼時(shí)指定的動(dòng)態(tài)庫搜索路徑(指的是用 -wl,rpath 或-R選項(xiàng)而不是-L),readelf -d命令可以查看編譯的目標(biāo)文件中rpath參數(shù);

    gcc -Wl,-rpath,/home/arc/test,-rpath,/usr/local/lib test.c
  • 環(huán)境變量LD_LIBRARY_PATH指定的動(dòng)態(tài)庫搜索路徑;

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

    或者

    LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH ./main
  • 配置文件 /etc/ld.so.conf 中指定的動(dòng)態(tài)庫搜索路徑;

    將動(dòng)態(tài)庫路徑追加到/etc/ld.so.conf文件或者/etc/ld.so.conf.d/目錄下的文件后,記得一定要執(zhí)行ldconfig 命令,該命令會(huì)將配置的所有路徑下的庫載入緩存文件/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將動(dòng)態(tài)庫的路徑添加到/etc/ld.so.conf.d目錄下的一個(gè)單獨(dú)的conf文件中,也能完成配置,并且不會(huì)影響到其他的配置

  • 默認(rèn)的動(dòng)態(tài)庫搜索路徑 /lib;

  • 默認(rèn)的動(dòng)態(tài)庫搜索路徑 /usr/lib

  • 編譯時(shí)查找?guī)斓乃阉髀窂?/h3>
  • 編譯時(shí)使用 -L 指定庫的路徑;
    gcc main.c -o main -L./ -lcac
  • 通過環(huán)境變量LIBRARY_PATH指定搜索路徑
    LIBRARY_PATH=.:$LIBRARY_PATH gcc main.c -o main -lcac
  • 系統(tǒng)標(biāo)準(zhǔn)路徑/lib /usr/lib /usr/local/lib
  • 比較

  • 編譯時(shí)查找的是靜態(tài)庫或動(dòng)態(tài)庫,而運(yùn)行時(shí)查找的只是動(dòng)態(tài)庫;
  • gcc參數(shù) -L 指定編譯時(shí)的鏈接路徑,-Wl,-rpath 指定運(yùn)行時(shí)鏈接路徑;
  • 編譯時(shí)使用環(huán)境變量LIBRARY_PATH指定庫的路徑,運(yùn)行時(shí)使用環(huán)境變量LD_LIBRARY_PATH/etc/ld.so.conf 指定庫的路徑;
  • 編譯時(shí)用的鏈接器是ld,而運(yùn)行時(shí)用的鏈接器是 /lib/ld-linux.so.2;
  • 編譯時(shí)與運(yùn)行時(shí)都會(huì)查找默認(rèn)路徑:/lib /usr/lib;
  • 編譯時(shí)還有一個(gè)默認(rèn)路徑:/usr/local/lib,而運(yùn)行時(shí)不會(huì)默認(rèn)找查該路徑。
  • 環(huán)境變量指定頭文件的搜索路徑

    C_INCLUDE_PATH、CPLUS_INCLUDE_PATH以及CPATH常被用于在全局性地添加預(yù)處理C/C++時(shí)的包含目錄,其中C_INCLUDE_PATH僅對預(yù)處理C有效,CPLUS_INCLUDE_PATH僅對預(yù)處理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預(yù)處理C時(shí)的的搜索目錄 echo | gcc -x c -v -E -
    • 查看gcc預(yù)處理C++時(shí)的的搜索目錄echo | gcc -x c++ -v -E -
    • 查看clang預(yù)處理C++時(shí)的搜索目錄echo | clang -x c++ -v -E -

    pkg-config

    在大多數(shù)開源代碼中autotool工具使用pkg-config命令來獲取第三方庫的相關(guān)編譯與連接參數(shù)的

    # 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庫為例做一個(gè)簡單說明

    # 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的工作原理是根據(jù)指定庫名稱的pc文件獲取相應(yīng)編譯參數(shù)

    # 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 // 連接該動(dòng)態(tài)庫時(shí)使用的連接選項(xiàng) {Libs} -lavcodec # pkg-config libavcodec --cflags // 編譯時(shí)使用的編譯選項(xiàng) {Cflags} -I/usr/include/ffmpeg # pkg-config libavcodec --libs --static // 使用靜態(tài)庫時(shí)使用的連接參數(shù) {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

    可以看出使用庫的靜態(tài)庫使用,連接時(shí)需要連接該靜態(tài)庫以及靜態(tài)庫依賴的庫(如果是靜態(tài)庫,需要安裝依賴的開發(fā)包,yum安裝的運(yùn)行時(shí)庫都是后綴有版本號的,連接時(shí)查找的動(dòng)態(tài)庫不帶版本號)

    連接順序問題

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

    動(dòng)態(tài)庫使用實(shí)例

    定義庫的頭文件

    /*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

    庫中函數(shù)的實(shí)現(xiàn)

    /*caculate.c文件*/ #include "caculate.h"//求兩個(gè)數(shù)的和 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); }

    編譯生產(chǎn)libcac.so文件如下: gcc -shared -fPIC caculate.c -o libcac.so

    動(dòng)態(tài)庫的使用方法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; }

    編譯運(yùn)行:

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

    動(dòng)態(tài)庫的使用方法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; }

    編譯運(yùn)行

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

    依賴靜態(tài)庫,編譯生成動(dòng)態(tài)庫

    opencv的動(dòng)態(tài)庫依賴一個(gè)三方靜態(tài)庫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
    • 依賴靜態(tài)庫,編譯生成動(dòng)態(tài)庫

    動(dòng)態(tài)庫版本兼容問題

    • GCC選項(xiàng)_-Wl,-soname
    • 查看動(dòng)態(tài)庫so命令

    動(dòng)態(tài)庫與靜態(tài)庫同時(shí)存在

    • linux程序同時(shí)鏈接動(dòng)態(tài)庫與靜態(tài)庫
    • 使用Automake生成Makefile及動(dòng)態(tài)庫和靜態(tài)庫的創(chuàng)建

    參考

    • linux下運(yùn)行時(shí)鏈接庫的路徑順序
    • Linux動(dòng)態(tài)鏈接庫的使用
    • 技巧:Linux 動(dòng)態(tài)庫與靜態(tài)庫制作及使用詳解
    • libc.so兼容問題
    • 利用LD_PRELOAD給glibc庫函數(shù)加鉤子
    • 警惕UNIX下的LD_PRELOAD環(huán)境變量
    創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

    總結(jié)

    以上是生活随笔為你收集整理的linux动态库查找路径以及依赖关系梳理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。