ubuntu---記錄.動態庫默認路徑的踩坑


發現這個問題,還是經過一個報錯問題卡了好多天,然后請求好多人的支援,最后個人的疑問:為什么明明指明了路徑,生成 .SO 沒有問題,在調用.SO 就有問題,報錯各種找不到函數或者未定義,然后把缺的 *.so 都一頓拷貝至 /lib  或者 /usr/lib 中 有時又可以解決問題,但不是每次都好用 ?   --- 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

 

問題報錯,示例:

# 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$

 

解決問題的過程中,學會幾個命令:

grep -R <一個想要找的關鍵字>

移動文件之后,需要:sudo ldconfig  一下,使修改生效

 

參考:

一、 Linux 動態庫選擇順序指:

1.  編譯程序時用到動態庫,該從那些地方查找,按照怎么樣的順序查找?

2.  運行程序時需要動態庫,該從那些地方查找,按照怎么樣的順序查找?
二、gcc 編譯程序時查找SO順序如下:

1.  gcc 編譯時參數-L指定的路徑

2.  環境變量 LIBRARY_PATH

3.  系統默認庫位置 /lib    /usr/lib
三、Linux 程序運行時查找SO順序如下:

1.  gcc 編譯時指定的運行時庫路徑 -Wl,-rpath

2.  環境變量 LD_LIBRARY_PATH

3.  ldconfig 緩存 /etc/ld.so.cache

4  系統默認庫位置 /lib    /usr/lib
四、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。
五、鏈接選項-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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM