Answers:
除非明确将其定向到via,否则加载器永远不会在当前目录中检查共享对象$LD_LIBRARY_PATH
。有关ld.so(8)
更多详细信息,请参见手册页。
:
)分隔,而不是分号。
您可以设置LD_LIBRARY_PATH来让动态链接程序知道在哪里查看,但还有更好的选择。您可以将共享库放在标准位置之一中,有关这些位置的列表,请参见/etc/ld.so.conf
(在Linux上)和/usr/bin/crle
(在Solaris上)
您可以-R <path>
在构建二进制文件时传递给链接器,该链接器将添加<path>
到为共享库扫描的目录列表中。这是一个例子。首先,显示问题:
libtest.h:
void hello_world(void);
libtest.c:
#include <stdio.h>
void hello_world(void) {
printf("Hello world, I'm a library!\n");
}
你好ç:
#include "libtest.h"
int main(int argc, char **argv) {
hello_world();
}
Makefile(必须使用标签):
all: hello
hello: libtest.so.0
%.o: %.c
$(CC) $(CFLAGS) -fPIC -c -o $@ $<
libtest.so.0.0.1: libtest.o
$(CC) -shared -Wl,-soname,libtest.so.0 -o libtest.so.0.0.1 libtest.o
libtest.so.0: libtest.so.0.0.1
ln -s $< $@
clean:
rm -f hello libtest.o hello.o libtest.so.0.0.1 libtest.so.0
让我们运行它:
$ make
cc -fPIC -c -o libtest.o libtest.c
cc -shared -Wl,-soname,libtest.so.0 -o libtest.so.0.0.1 libtest.o
ln -s libtest.so.0.0.1 libtest.so.0
cc hello.c libtest.so.0 -o hello
$ ./hello
./hello: error while loading shared libraries: libtest.so.0: cannot open shared object file: No such file or directory
如何解决?添加-R <path>
到链接器标志(此处通过设置LDFLAGS
)。
$ make clean
(...)
$ make LDFLAGS="-Wl,-R -Wl,/home/maciej/src/tmp"
(...)
cc -Wl,-R -Wl,/home/maciej/src/tmp hello.c libtest.so.0 -o hello
$ ./hello
Hello world, I'm a library!
查看二进制文件,您可以看到它需要libtest.so.0
:
$ objdump -p hello | grep NEEDED
NEEDED libtest.so.0
NEEDED libc.so.6
除了标准位置外,二进制文件还将在指定目录中查找其库:
$ objdump -p hello | grep RPATH
RPATH /home/maciej/src/tmp
如果希望二进制文件在当前目录中查找,则可以将RPATH设置为$ORIGIN
。这有点棘手,因为您需要确保make不会解释美元符号。这是一种实现方法:
$ make CFLAGS="-fPIC" LDFLAGS="-Wl,-rpath '-Wl,\$\$ORIGIN'"
$ objdump -p hello | grep RPATH
RPATH $ORIGIN
$ ./hello
Hello world, I'm a library!
make
,例如手动调用时g++
,请尝试-Wl,-rpath='$ORIGIN'
(请注意单引号)以防止$ORIGIN
扩展为空字符串。
动态链接器将决定在哪里寻找库。对于Linux,动态链接程序通常是GNU ld.so
(或出于兼容性原因而通常表现相同的替代程序。
要引用维基百科的话:
GNU C库的动态链接器在以下位置搜索共享库:
DT_RPATH
二进制文件的动态部分属性中的(用冒号分隔)路径(如果存在)并且该DT_RUNPATH
属性不存在。LD_LIBRARY_PATH
除非可执行文件是setuid
/setgid
二进制文件,否则环境变量中的(用冒号分隔)路径将被忽略。LD_LIBRARY_PATH
可以通过使用选项--library-path(例如/lib/ld-linux.so.2 --library-path $ HOME / mylibs myprogram)来调用动态链接器来覆盖它。DT_RUNPATH
二进制文件的动态部分属性中的(用冒号分隔)路径(如果存在)。- 基于ldconfig高速缓存文件(通常位于
/etc/ld.so.cache
)进行查找,该文件包含先前在增强库路径(由设置/etc/ld.so.conf
)中找到的候选库的已编译列表 。但是,如果二进制文件已通过-z nodefaultlib
链接器选项链接,则会跳过默认库路径中的库。- 在受信任的默认路径中
/lib
,然后/usr/lib
。如果二进制文件是使用-z nodefaultlib链接器选项链接的,则将跳过此步骤。
echo $LD_LIBRARY_PATH
在我的机器上是空的:(