鍍金池/ 問(wèn)答/C  C++  Linux/ linux C 未鏈接到本地動(dòng)態(tài)庫(kù)

linux C 未鏈接到本地動(dòng)態(tài)庫(kù)

我在項(xiàng)目中需要鏈接一個(gè)動(dòng)態(tài)庫(kù)

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

提示錯(cuò)誤

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

沒(méi)有找到庫(kù)的路徑,所以使用 -L 添加庫(kù)的路徑

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

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

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

程序鏈接的是系統(tǒng)中的庫(kù)而不是本地的庫(kù),所以執(zhí)行結(jié)果不對(duì)。
但我設(shè)置了$LD_LIBRARY_PATH的值并沒(méi)用。
我又測(cè)試了使用 rpath 參數(shù)設(shè)置路徑,但ldd的結(jié)果還是不對(duì)
鏈接器讀取到了-L設(shè)置了庫(kù)的路徑,并且找到了庫(kù),那為何鏈接進(jìn)去的值是系統(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)庫(kù)是沒(méi)有這個(gè)函數(shù)的,我加入的,本地的庫(kù)可以通過(guò)objdump看到
回答
編輯回答
歆久

1.這個(gè)問(wèn)題涉及到動(dòng)態(tài)鏈接庫(kù)的3個(gè)不同的庫(kù)名的文件,一個(gè)link name,一個(gè)是so name,一個(gè)是real name,link name很好理解,就是編譯鏈接時(shí)使用的名稱,比如你的smbclient庫(kù)它的link name為libsmbclient.so,它的so name為libsmbclient.so.0,而real name為libsmbclient.so.0.x,“x”是什么要看你具體的版本??梢允褂?code>objdump -p /home/chenzhen/packSource/my_samba/libsmbclient.so | grep SONAME查看你重新編譯的smbclient.so庫(kù)的so name,我猜絕對(duì)是libsmbclient.so.0
2.gcc或者g++在生成可執(zhí)行程序時(shí)如果發(fā)現(xiàn)動(dòng)態(tài)庫(kù)包含有so name則會(huì)把so name信息保留到可執(zhí)行文件中,可執(zhí)行文件在啟動(dòng)時(shí)是使用so name去查找動(dòng)態(tài)庫(kù)的,如果庫(kù)沒(méi)有so name則可執(zhí)行文件啟動(dòng)時(shí)是使用link name去查找動(dòng)態(tài)庫(kù)的。
3.理解了上面動(dòng)態(tài)庫(kù)三個(gè)名稱文件的區(qū)別上面問(wèn)題就很好解決了。你上面雖然在LD_LIBRARY_PATH中添加了/home/chenzhen/packSource/my_samba/你修改后庫(kù)所在的路徑,但是程序就是不加載這個(gè)目錄下的動(dòng)態(tài)鏈接庫(kù)是因?yàn)槌绦騿?dòng)的時(shí)候搜索的so name,而不是link name,所以解決方案也很簡(jiǎn)單,在/home/chenzhen/packSource/my_samba/目錄下創(chuàng)建一個(gè)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列出來(lái)。
你的so存放的位置也寫(xiě)出來(lái),還有rpath的值也寫(xiě)出來(lái)。

2018年3月18日 02:43