發現這個問題,仍是通過一個報錯問題卡了好多天,而後請求好多人的支援,最後我的的疑問:爲何明明指明瞭路徑,生成 .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