Soru Yürütülebilir dosya ile aynı dizinde bulamıyor musunuz?


İle bağlantı kurması gereken bir yürütülebilir dosyam var libtest.so Dinamik olarak, onları aynı dizine koydum, sonra:

cd path_to_dir
./binary

Ama şunu aldın:

error while loading shared libraries: libtest.so: cannot open shared object file: No such file or directory

Nasıl bulamaz? libtest.so Bu zaten kendi kendini yürütülebilir ile aynı dizinde?


36
2018-06-10 08:54


Menşei




Cevaplar:


Yükleyici, açık bir şekilde yönlendirilmediği sürece paylaşılan nesneler için geçerli dizini asla denetlemez. $LD_LIBRARY_PATH. Bakın ld.so(8) Daha fazla bilgi için man sayfa.


22
2018-06-10 08:56



echo $LD_LIBRARY_PATH makinemde boş :( - linuxer
Genelde öyle. - Ignacio Vazquez-Abrams
Yükleyicinin kitaplıklara bakması için ek dizinler belirler. - Ignacio Vazquez-Abrams
* Nix'deki yollar bir kolonla ayrılır (:), noktalı virgül değil. - Ignacio Vazquez-Abrams
LD_LIBRARY_PATH genellikle üretimde zayıf bir seçimdir. Bu hızlı hackler için iyidir ve kaldırılmış ikili dosyalara yardımcı olmak, ünite testleri yaparken paylaşılan kütüphanelerini bulmaya yardımcı olur (düşün ./configure; make; make check). İkilinizi oluştururken, kütüphanenizi standart bir konuma koyabilirsiniz (/etc/ld.so.conf adresinde listelenebilir) ya da binerin nereye bakılacağını bilmesini sağlamak için linke -R bayrağını geçirebilirsiniz. - automatthias


LD_LIBRARY_PATH öğesini dinamik bağlantı aracının nereye bakılacağını bildirmek için ayarlayabilirsiniz, ancak daha iyi seçenekler vardır. Paylaşılan kitaplığınızı standart yerlerden birine yerleştirebilirsiniz, bkz. /etc/ld.so.conf (Linux'ta) ve /usr/bin/crle Bu yerlerin listesi için (Solaris üzerinde)

Geçebilirsin -R <path> senin ikili inşa ederken linker için, ekleyecek <path> Paylaşılan kitaplığınız için taranan dizinlerin listesine. İşte bir örnek. İlk olarak, sorunu göstererek:

libtest.h:

void hello_world(void);

libtest.c:

#include <stdio.h>
void hello_world(void) {
  printf("Hello world, I'm a library!\n");
}

Merhaba C:

#include "libtest.h"
int main(int argc, char **argv) {
  hello_world();
}

Makefile (sekmeler kullanılmalıdır):

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

Hadi koşalım:

$ 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

Nasıl düzeltilir? Eklemek -R <path> linker bayraklarına (burada, ayarlayarak) 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!

İkiliye baktığınızda, bunun gerekli olduğunu görebilirsiniz libtest.so.0:

$ objdump -p hello | grep NEEDED
  NEEDED               libtest.so.0
  NEEDED               libc.so.6

İkili, belirtilen dizinde standart yerlerden ayrı olarak kütüphanelerini arayacaktır:

$ objdump -p hello | grep RPATH
  RPATH                /home/maciej/src/tmp

İkilinin geçerli dizine bakmasını isterseniz, RPATH'yi $ORIGIN. Bu biraz zor, çünkü dolar işaretinin make tarafından yorumlanmadığından emin olmalısınız. İşte bunu yapmanın bir yolu:

$ make CFLAGS="-fPIC" LDFLAGS="-Wl,-rpath '-Wl,\$\$ORIGIN'"
$ objdump -p hello | grep RPATH
  RPATH                $ORIGIN
$ ./hello 
Hello world, I'm a library!

53
2018-06-18 09:14



Eğer kullanmıyorsa make, manuel olarak çağırıldığında olduğu gibi g++, Deneyin -Wl,-rpath='$ORIGIN' (tek tırnaklara dikkat ediniz) $ORIGINboş bir dizeye genişletmek. - Morpork


Paylaşılan nesneleri, yürütülebilir dizininizle aynı dizinden yüklemek için basitçe şunu uygulayın:

$ LD_LIBRARY_PATH=. ./binary

Not: Sisteminizin LD_LIBRARY_PATH değişkenini değiştirmeyecektir. Değişim sadece buna ve sadece bu programın uygulanmasına etki eder.


10
2017-08-29 00:06





Hala cevapsız mücadele eden herkes için kendimi şu öneriyle buldum:

Ld.so.cache dosyasını kullanarak güncellemeyi deneyebilirsiniz: sudo ldconfig -v

Benim için çalıştı.


3
2017-08-12 23:24





Kullanan herkes için CKağıt onların yapıları için CMAKE_EXE_LINKER_FLAGS aşağıdakilere

set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath='$ORIGIN'")

Bu, ilk önce geçerli çalışma dizinindeki .so dosyalarını aramak için tüm yapı türleri (ör. Debug, Release, vb.) İçin bağlayıcı bayraklarını düzgün şekilde çoğaltacaktır.


0