Mặc dù bạn có thể đặt LD_LIBRARY_PATH để cho trình liên kết động biết nơi cần tìm, có nhiều tùy chọn tốt hơn. Bạn có thể đặt thư viện dùng chung của mình ở một trong những nơi tiêu chuẩn, xem /etc/ld.so.conf
(trên Linux) và /usr/bin/crle
(trên Solaris) để biết danh sách những nơi này
Bạn có thể chuyển -R <path>
đến trình liên kết khi xây dựng tệp nhị phân của mình, phần này sẽ thêm <path>
vào danh sách các thư mục được quét cho thư viện dùng chung của bạn. Đây là một ví dụ. Đầu tiên, hiển thị vấn đề:
libtest.h:
void hello_world(void);
libtest.c:
#include <stdio.h>
void hello_world(void) {
printf("Hello world, I'm a library!\n");
}
chào c:
#include "libtest.h"
int main(int argc, char **argv) {
hello_world();
}
Makefile (các tab phải được sử dụng):
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
Hãy chạy nó:
$ 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
Làm thế nào để khắc phục nó? Thêm -R <path>
vào các cờ liên kết (ở đây, bằng cách thiết lập 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!
Nhìn vào nhị phân, bạn có thể thấy rằng nó cần libtest.so.0
:
$ objdump -p hello | grep NEEDED
NEEDED libtest.so.0
NEEDED libc.so.6
Nhị phân sẽ tìm các thư viện của nó, ngoài các vị trí tiêu chuẩn, trong thư mục được chỉ định:
$ objdump -p hello | grep RPATH
RPATH /home/maciej/src/tmp
Nếu bạn muốn tệp nhị phân tìm trong thư mục hiện tại, bạn có thể đặt RPATH thành $ORIGIN
. Điều này là một chút khó khăn, bởi vì bạn cần chắc chắn rằng ký hiệu đô la không được giải thích bằng cách thực hiện. Đây là một cách để làm điều đó:
$ make CFLAGS="-fPIC" LDFLAGS="-Wl,-rpath '-Wl,\$\$ORIGIN'"
$ objdump -p hello | grep RPATH
RPATH $ORIGIN
$ ./hello
Hello world, I'm a library!
echo $LD_LIBRARY_PATH
trống trên máy của tôi :(