发现这个问题,仍是通过一个报错问题卡了好多天,而后请求好多人的支援,最后我的的疑问:为何明明指明了路径,生成 .SO 没有问题,在调用.SO 就有问题,报错各类找不到函数或者未定义,而后把缺的 *.so 都一顿拷贝至 /lib 或者 /usr/lib 中 有时又能够解决问题,但不是每次都好用 ? --- linux动态连接库的加载顺序。linux
linux动态连接库的加载顺序: 它有5个地方会查找, 1. 编译时指定的run path 2. LD_LIBRARY_PATH 指定的地方 3. ldconfig 指定的地方 4. /lib 5. /usr/lib
其它说明:
pos1 经过readelf -d test 能够看到(RPATH) Library rpath: [pos1]
pos2 须要用LD_LIBRARY_PATH 说明。此例为: export LD_LIBRARY_PATH=./pos2
pos3 须要在/etc/ld.so.conf 中指明,此例为:/home/hjj/MyTest/temp/pos3
而后ldconfig 生成缓存使设置生效。
pos4 系统目录/lib
pos5 系统目录/usr/lib
原文连接:https://blog.csdn.net/hejinjing_tom_com/article/details/52454478
问题报错,示例:c++
# Path DARKNET_PATH ?= ../darknet MOT_DEEPSORT_PATH ?= ../tracker # OPENCV_PATH ?= ../../../opencv-4.0.1 OPENCV_PATH ?= /usr/local/opencv3.4.7 #@WP # Common definitions GCC ?= g++ -g NVCC ?= $(CUDA_PATH)/bin/nvcc CCFLAGS := -fPIC -std=c++11 -lstdc++fs -Wall -O0 -Wunused-function -Wunused-variable NVCCFLAGS := --compiler-options "-fPIC -Wall -O0 -std=c++11 -mavx -mavx2" -std=c++11 -lstdc++fs # Common includes and paths INCLUDES += -I$(DARKNET_PATH)/include INCLUDES += -I$(MOT_DEEPSORT_PATH)/include INCLUDES += -I/usr/local/opencv3.4.7/include/opencv #@WP INCLUDES += -I/usr/local/opencv3.4.7/include/opencv2 #@WP INCLUDES += -I/usr/local/opencv3.4.7/include/opencv2/core #@WP #INCLUDES += -I/usr/local/opencv3.4.7/lib #@WP # Link applications against stub libraries provided in the SDKs. LDFLAGS += -L$(MOT_DEEPSORT_PATH) -ldeepsort LDFLAGS += -Wl,-rpath="/usr/local/lib" LDFLAGS += -lopencv_objdetect -lopencv_highgui -lopencv_core -lopencv_imgproc -lopencv_imgcodecs -lopencv_videoio #@WP #LDFLAGS += -L/usr/local/opencv3.4.7/lib -lopencv_objdetect -lopencv_highgui -lopencv_core -lopencv_imgproc -lopencv_imgcodecs -lopencv_videoio #@WP LDFLAGS += -L$(DARKNET_PATH) -ldarknet LDFLAGS += -Wl,-rpath="$(DARKNET_PATH)" LDFLAGS += -Wl,-rpath="$(MOT_DEEPSORT_PATH)" #这里须要根据本身在linux上配置的opencv路径修改 #INCLUDES = -I/usr/local/opencv3.4.2/include/opencv -I. #LIBS = -L/usr/local/opencv3.4.2/lib -lopencv_objdetect -lopencv_highgui -lopencv_imgcodecs -lopencv_core -lopencv_videoio -lopencv_imgproc # EXE_NAME ?= my_demo all: $(EXE_NAME) %.o: %.cpp $(GCC) $(CCFLAGS) $(INCLUDES) -c $< %.o: $(CLIENT_SERVER_PROTO)/%.cpp $(GCC) $(CCFLAGS) $(INCLUDES) -c $< %.o: $(CLIENT_SERVER_PROTO)/%.cc $(GCC) $(CCFLAGS) $(INCLUDES) -c $< $(EXE_NAME): my_demo.o $(GCC) $(CCFLAGS) $(INCLUDES) -o $@ $^ $(LDFLAGS) clean: rm -rf *.o $(EXE_NAME)
解决:缓存
u@u160406:~/sort/DeepSort_yoloV3-HOG_feature$ sudo gedit /etc/ld.so.conf
[sudo] u 的密码:
在/etc/ld.so.conf加入内容:
/usr/local/opencv3.4.7/lib /usr/local/opencv3.4.7/include
u@u160406:~/sort/DeepSort_yoloV3-HOG_feature$ source /etc/ld.so.conf include:未找到命令 bash: /usr/local/opencv3.4.7/lib: 是一个目录 bash: /usr/local/opencv3.4.7/include: 是一个目录 u@u160406:~/sort/DeepSort_yoloV3-HOG_feature$ ldconfig ^Z [1]+ 已中止 ldconfig u@u160406:~/sort/DeepSort_yoloV3-HOG_feature$ sudo ldconfig u@u160406:~/sort/DeepSort_yoloV3-HOG_feature$
解决问题的过程当中,学会几个命令:bash
grep -R <一个想要找的关键字>
移动文件以后,须要:sudo ldconfig 一下,使修改生效
参考:app
1、 Linux 动态库选择顺序指: 1. 编译程序时用到动态库,该从那些地方查找,按照怎么样的顺序查找? 2. 运行程序时须要动态库,该从那些地方查找,按照怎么样的顺序查找? 2、gcc 编译程序时查找SO顺序以下: 1. gcc 编译时参数-L指定的路径 2. 环境变量 LIBRARY_PATH 3. 系统默认库位置 /lib /usr/lib 3、Linux 程序运行时查找SO顺序以下: 1. gcc 编译时指定的运行时库路径 -Wl,-rpath 2. 环境变量 LD_LIBRARY_PATH 3. ldconfig 缓存 /etc/ld.so.cache 4 系统默认库位置 /lib /usr/lib 4、LIBRARY_PATH和LD_LIBRARY_PATH环境变量的区别 LIBRARY_PATH和LD_LIBRARY_PATH是Linux下的两个环境变量,两者的含义和做用分别以下: LIBRARY_PATH环境变量用于在程序编译期间查找动态连接库时指定查找共享库的路径,例如,指定gcc编译须要用到的动态连接库的目录。设置方法以下(其中,LIBDIR1和LIBDIR2为两个库目录): export LIBRARY_PATH=LIBDIR1:LIBDIR2:$LIBRARY_PATH LD_LIBRARY_PATH环境变量用于在程序加载运行期间查找动态连接库时指定除了系统默认路径以外的其余路径,注意,LD_LIBRARY_PATH中指定的路径会在系统默认路径以前进行查找。设置方法以下(其中,LIBDIR1和LIBDIR2为两个库目录): export LD_LIBRARY_PATH=LIBDIR1:LIBDIR2:$LD_LIBRARY_PATH 举个例子,咱们开发一个程序,常常会须要使用某个或某些动态连接库,为了保证程序的可移植性,能够先将这些编译好的动态连接库放在本身指定的目录下,而后按照上述方式将这些目录加入到LD_LIBRARY_PATH环境变量中,这样本身的程序就能够动态连接后加载库文件运行了。 区别与使用: 开发时,设置LIBRARY_PATH,以便gcc可以找到编译时须要的动态连接库。 发布时,设置LD_LIBRARY_PATH,以便程序加载运行时可以自动找到须要的动态连接库。 注意:新设置变量 LD_LIBRARY_PATH ,下次开机,一切设置将不复存在;如何把这个值持续写到 LD_LIBRARY_PATH 里呢? 咱们就会想有不有什么一劳永逸地方法,使得设置以后就不用再去设置了?答案是确定的。有两种: 1、在~/目录下打开.bash_profile文件,设置环境变量以下: LD_LIBRARY_PATH=dir:$LD_LIBRARY_PATH export LD_LIBRARY_PATH LD_LIBRARY_PATH 这个环境变量是你们最为熟悉的,它告诉loader:在哪些目录中能够找到共享库。能够设置多个搜索目录,这些目录之间用冒号分隔开。 2、在linux下,还 提供了另一种方式来完成一样的功能,你能够把这些目录加到/etc/ld.so.conf中,而后调用ldconfig。 5、连接选项-I,-l,-L,-Wl:rpath -I,添加包含路径 -I 在编译时用,告诉编译器去哪一个路径下找文件 如:-I /home/hello/include 表示将/home/hello/include目录做为第一个寻找头文件的目录。 编译器的寻找顺序是:/home/hello/include-->/usr/include-->/usr/local/include。若是在/home/hello/include中有个文件hello.h,则在程序中用#include<hello.h>就能引用到这个文件。 能够加多个包含路径,编译器的寻找顺序为添加的顺序。 -l,添加引用连接库 -l 在连接时用到,它的做用是告诉连接器,要用到哪一个库。 如:-l pthread 告诉连接器(linker),程序须要连接pthread这个库,这里的pthread是库名不是文件名,具体来讲文件句是libpthread.so。 -L,添加连接库路径 -L 后跟路径,告诉连接器从哪找库(.so文件),只有在连接时会用到。 如:-L /home/hello/lib 表示将/home/hello/lib目录做为第一个寻找库文件的目录,寻找顺序是:/home/hello/lib-->/usr/lib-->/usr/local/lib。 能够加多个包含路径,连接器的寻找顺序为添加的顺序。 -Wl:rpath,添加运行时库路径 -Wl:rpath 后面也是路径,运行的时候用。这条编译指令会在编译时记录到target文件中,因此编译以后的target文件在执行时会按这里给出的路径去找库文件。 如:-Wl:rpath=/home/hello/lib 表示将/home/hello/lib目录做为程序运行时第一个寻找库文件的目录,程序寻找顺序是:/home/hello/lib-->/usr/lib-->/usr/local/lib。 能够加多个包含路径,程序在运行时的寻找顺序为添加的顺序。 参考: https://blog.csdn.net/hejinjing_tom_com/article/details/52454478