我在项目中需要链接一个动态库
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
编译成功,但执行的时候出现问题。猜想可能是LD_LIBRARY_PATH变量未设置的问题
根据 https://www.cprogramming.com/...
设置变量,并且能够肯定变量值设置成功,程序正常运行,但结果还是不正确。
执行
ldd test | grep smbclient
libsmbclient.so.0 => /usr/lib/x86_64-linux-gnu/libsmbclient.so.0 (0x00007fdbb6561000)
程序链接的是系统中的库而不是本地的库,所以执行结果不对。
但我设置了$LD_LIBRARY_PATH的值并没用。
我又测试了使用 rpath 参数设置路径,但ldd的结果还是不对
链接器读取到了-L设置了库的路径,并且找到了库,那为何链接进去的值是系统的?求助!!!
$ 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
系统库是没有这个函数的,我加入的,本地的库可以通过objdump看到
1.这个问题涉及到动态链接库的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++在生成可执行程序时如果发现动态库包含有so name则会把so name信息保留到可执行文件中,可执行文件在启动时是使用so name去查找动态库的,如果库没有so name则可执行文件启动时是使用link name去查找动态库的。
3.理解了上面动态库三个名称文件的区别上面问题就很好解决了。你上面虽然在LD_LIBRARY_PATH中添加了
/home/chenzhen/packSource/my_samba/
你修改后库所在的路径,但是程序就是不加载这个目录下的动态链接库是因为程序启动的时候搜索的so name,而不是link name,所以解决方案也很简单,在/home/chenzhen/packSource/my_samba/
目录下创建一个so name的软连接即可。cd /home/chenzhen/packSource/my_samba/; ln -s libsmbclient.so.0 libsmbclient.so