실행 파일과 동일한 디렉토리에서 .so를 찾을 수 없습니까? path_to_dir ./binary 그러나 이것을 얻었다 : error while loading shared

libtest.so동적으로 연결 해야하는 실행 파일이 있으므로 동일한 디렉토리에 넣습니다.

cd path_to_dir
./binary

그러나 이것을 얻었다 :

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

libtest.so실행 파일과 같은 디렉토리에있는 파일을 어떻게 찾을 수 없습니까?



답변

로더는 명시 적으로 via로 지시되지 않는 한 현재 디렉토리에서 공유 객체를 검사하지 않습니다 $LD_LIBRARY_PATH. 자세한 내용은 ld.so(8)매뉴얼 페이지를 참조하십시오.


답변

동적 링커가 볼 위치를 알 수 있도록 LD_LIBRARY_PATH를 설정할 수 있지만 더 나은 옵션이 있습니다. 공유 라이브러리를 표준 위치 중 하나에 배치 할 수 있습니다 (이 장소 목록은 ( /etc/ld.so.confLinux) 및 /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");
}

hello.c :

#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!

답변

실행 파일과 동일한 디렉토리에서 공유 객체를로드하려면 다음을 실행하십시오.

$ LD_LIBRARY_PATH=. ./binary

참고 : 시스템의 LD_LIBRARY_PATH 변수는 수정하지 않습니다. 변경 사항은 프로그램 실행에만 영향을 미칩니다.


답변

여전히 답을 얻지 못한 사람에게는 다음과 같은 제안이 있습니다.

다음을 사용하여 ld.so.cache를 업데이트 할 수 있습니다. sudo ldconfig -v

나를 위해 일했다.


답변

빌드에 CMake 를 사용하는 사람 CMAKE_EXE_LINKER_FLAGS은 다음을 다음과 같이 설정할 수 있습니다 .

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

이렇게하면 모든 빌드 유형 (예 : 디버그, 릴리스 등)에 대한 링커 플래그가 올바르게 전파되어 현재 작업 디렉토리에서 .so 파일을 먼저 찾습니다.


답변

동적 링커는 라이브러리를 찾을 위치를 결정합니다. Linux의 경우 동적 링커는 일반적으로 GNU ld.so(또는 호환성 이유로 일반적으로 동일하게 작동하는 대안)입니다.

Wikipedia에서 인용하려면 :

GNU C 라이브러리의 동적 링커는 다음 위치에서 공유 라이브러리를 검색합니다.

  1. DT_RPATH바이너리 의 동적 섹션 속성에 존재하고 DT_RUNPATH속성이없는 경우 (콜론으로 구분 된) 경로입니다 .
  2. LD_LIBRARY_PATH실행 파일이 setuid/ setgid바이너리 가 아닌 경우 환경 변수에서 (콜론으로 구분 된) 경로 는 무시됩니다. LD_LIBRARY_PATH–library-path 옵션 (예 : /lib/ld-linux.so.2 –library-path $ HOME / mylibs myprogram)을 사용하여 동적 링커를 호출하여 재정의 할 수 있습니다.
  3. DT_RUNPATH바이너리 의 동적 섹션 속성에있는 (콜론으로 구분 된) 경로 .
  4. 기능 보강 라이브러리 경로에서 이전에 찾은 후보 라이브러리의 컴파일 된 목록을 포함하는 ldconfig 캐시 파일 (종종)에 기반한 검색 /etc/ld.so.cache(에서 설정
    /etc/ld.so.conf). 그러나 바이너리가 -z
    nodefaultlib
    링커 옵션 과 링크 된 경우 기본 라이브러리 경로의 라이브러리는 건너 뜁니다.
  5. 신뢰할 수있는 기본 경로에서 /lib다음 /usr/lib. 바이너리가 -z nodefaultlib 링커 옵션으로 링크 된 경우이 단계를 건너 뜁니다.

출처 : https://en.wikipedia.org/wiki/Rpath