Solusi 1:
Meskipun Anda dapat menyetel LD_LIBRARY_PATH agar penaut dinamis tahu ke mana harus mencari, ada opsi yang lebih baik. Anda dapat menempatkan perpustakaan bersama Anda di salah satu tempat standar, lihat /etc/ld.so.conf
(di Linux) dan /usr/bin/crle
(di Solaris) untuk daftar tempat-tempat ini
Anda dapat melewati -R <path>
ke linker saat membangun biner Anda, yang akan menambahkan <path>
ke daftar direktori yang dipindai untuk perpustakaan bersama Anda. Ini sebuah contoh. Pertama, menunjukkan masalahnya:
libtest.h:
void hello_world(void);
libtest.c:
#include <stdio.h>
void hello_world(void) {
printf("Hello world, I'm a library!\n");
}
halo.c:
#include "libtest.h"
int main(int argc, char **argv) {
hello_world();
}
Makefile (tab harus digunakan):
all: hello
hello: libtest.so.0
%.o: %.c
$(CC) $(CFLAGS) -fPIC -c -o [email protected] $<
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 $< [email protected]
clean:
rm -f hello libtest.o hello.o libtest.so.0.0.1 libtest.so.0
Mari kita jalankan:
$ 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
Bagaimana memperbaikinya? Tambahkan -R <path>
ke flag linker (di sini, dengan menyetel 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!
Melihat binernya, Anda dapat melihat bahwa itu membutuhkan libtest.so.0
:
$ objdump -p hello | grep NEEDED
NEEDED libtest.so.0
NEEDED libc.so.6
Biner akan mencari pustakanya, selain dari tempat standar, di direktori yang ditentukan:
$ objdump -p hello | grep RPATH
RPATH /home/maciej/src/tmp
Jika Anda ingin biner terlihat di direktori saat ini, Anda dapat mengatur RPATH ke $ORIGIN
. Ini agak rumit, karena Anda perlu memastikan bahwa tanda dolar tidak diartikan dengan make. Inilah salah satu cara untuk melakukannya:
$ make CFLAGS="-fPIC" LDFLAGS="-Wl,-rpath '-Wl,\$\$ORIGIN'"
$ objdump -p hello | grep RPATH
RPATH $ORIGIN
$ ./hello
Hello world, I'm a library!
Solusi 2:
Pemuat tidak pernah memeriksa direktori saat ini untuk objek bersama kecuali secara eksplisit diarahkan melalui $LD_LIBRARY_PATH
. Lihat ld.so(8)
halaman manual untuk detail lebih lanjut.
Solusi 3:
Untuk memuat objek bersama dari direktori yang sama dengan executable Anda, cukup jalankan:
$ LD_LIBRARY_PATH=. ./binary
Catatan:Ini tidak akan mengubah variabel LD_LIBRARY_PATH sistem Anda. Perubahan hanya memengaruhi ini, dan hanya ini, eksekusi program Anda.
Solusi 4:
Bagi siapa pun yang menggunakan CMake untuk build mereka, Anda dapat menyetel CMAKE_EXE_LINKER_FLAGS
berikut ini:
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath='$ORIGIN'")
Ini akan mempropagandakan flag linker dengan benar untuk semua jenis build (mis., Debug, Rilis, dll...) untuk mencari file .so di direktori kerja saat ini terlebih dahulu.
Solusi 5:
Bagi siapa pun yang masih berjuang tanpa jawaban, saya menemukan sendiri dengan saran berikut:
Anda dapat mencoba memperbarui ld.so.cache menggunakan:sudo ldconfig -v
Bekerja untuk saya.