鍍金池/ 問答/C  C++  Linux/ linux C 未鏈接到本地動態(tài)庫

linux C 未鏈接到本地動態(tài)庫

我在項目中需要鏈接一個動態(tài)庫

 gcc -o test main.c  -lsmbclient -ltalloc -ltevent

提示錯誤

/usr/bin/ld: 找不到 -lsmbclient
collect2: error: ld returned 1 exit status

沒有找到庫的路徑,所以使用 -L 添加庫的路徑

gcc -o test main.c -L. -lsmbclient -ltalloc -ltevent

編譯成功,但執(zhí)行的時候出現(xiàn)問題。猜想可能是LD_LIBRARY_PATH變量未設(shè)置的問題
根據(jù) https://www.cprogramming.com/...
設(shè)置變量,并且能夠肯定變量值設(shè)置成功,程序正常運行,但結(jié)果還是不正確。
執(zhí)行

ldd test | grep smbclient
libsmbclient.so.0 => /usr/lib/x86_64-linux-gnu/libsmbclient.so.0 (0x00007fdbb6561000)

程序鏈接的是系統(tǒng)中的庫而不是本地的庫,所以執(zhí)行結(jié)果不對。
但我設(shè)置了$LD_LIBRARY_PATH的值并沒用。
我又測試了使用 rpath 參數(shù)設(shè)置路徑,但ldd的結(jié)果還是不對
鏈接器讀取到了-L設(shè)置了庫的路徑,并且找到了庫,那為何鏈接進去的值是系統(tǒng)的?求助!?。?/p>

$ pwd
/home/chenzhen/packSource/my_samba

$ ls
get_auth_data_fn.h  libsmbclient.h  libsmbclient.so  libtalloc.so  libtevent.so  main.c  test

$ echo $LD_LIBRARY_PATH
:/home/chenzhen/packSource/my_samba/

$ gcc -L/home/chenzhen/packSource/my_samba -Wl,-rpath=/home/chenzhen/packSource/my_samba -Wall -o test main.c -lsmbclient -ltalloc -ltevent 

$ ldd -r test
    libp11-kit.so.0 => /usr/lib/x86_64-linux-gnu/libp11-kit.so.0 (0x00007f1d5ae2c000)
    libgpg-error.so.0 => /lib/x86_64-linux-gnu/libgpg-error.so.0 (0x00007f1d5ac27000)
    libwind.so.0 => /usr/lib/x86_64-linux-gnu/libwind.so.0 (0x00007f1d5a9fd000)
    ................中間省略70條左右
    libhx509.so.5 => /usr/lib/x86_64-linux-gnu/libhx509.so.5 (0x00007f1d5a5a6000)
    libsqlite3.so.0 => /usr/lib/x86_64-linux-gnu/libsqlite3.so.0 (0x00007f1d5a2ec000)
    libcrypt.so.1 => /lib/x86_64-linux-gnu/libcrypt.so.1 (0x00007f1d5a0b3000)
    libffi.so.6 => /usr/lib/x86_64-linux-gnu/libffi.so.6 (0x00007f1d59eaa000)
undefined symbol: smbc_notifydir    (./test)

$ objdump -tT libsmbclient.so | grep smbc_notify
0000000000048c1e g     F .text    000000000000001e              smbc_notifydir
0000000000048c1e g    DF .text    000000000000001e  Base        smbc_notifydir

系統(tǒng)庫是沒有這個函數(shù)的,我加入的,本地的庫可以通過objdump看到
回答
編輯回答
歆久

1.這個問題涉及到動態(tài)鏈接庫的3個不同的庫名的文件,一個link name,一個是so name,一個是real name,link name很好理解,就是編譯鏈接時使用的名稱,比如你的smbclient庫它的link name為libsmbclient.so,它的so name為libsmbclient.so.0,而real name為libsmbclient.so.0.x,“x”是什么要看你具體的版本。可以使用objdump -p /home/chenzhen/packSource/my_samba/libsmbclient.so | grep SONAME查看你重新編譯的smbclient.so庫的so name,我猜絕對是libsmbclient.so.0
2.gcc或者g++在生成可執(zhí)行程序時如果發(fā)現(xiàn)動態(tài)庫包含有so name則會把so name信息保留到可執(zhí)行文件中,可執(zhí)行文件在啟動時是使用so name去查找動態(tài)庫的,如果庫沒有so name則可執(zhí)行文件啟動時是使用link name去查找動態(tài)庫的。
3.理解了上面動態(tài)庫三個名稱文件的區(qū)別上面問題就很好解決了。你上面雖然在LD_LIBRARY_PATH中添加了/home/chenzhen/packSource/my_samba/你修改后庫所在的路徑,但是程序就是不加載這個目錄下的動態(tài)鏈接庫是因為程序啟動的時候搜索的so name,而不是link name,所以解決方案也很簡單,在/home/chenzhen/packSource/my_samba/目錄下創(chuàng)建一個so name的軟連接即可。
cd /home/chenzhen/packSource/my_samba/; ln -s libsmbclient.so.0 libsmbclient.so

2017年12月3日 07:06
編輯回答
陪妳哭

ldd -r test的結(jié)果呢?你把環(huán)境變量echo列出來。
你的so存放的位置也寫出來,還有rpath的值也寫出來。

2018年3月18日 02:43