실행 파일과 동일한 디렉토리에서 .so를 찾을 수 없습니까?


45

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실행 파일과 같은 디렉토리에있는 파일을 어떻게 찾을 수 없습니까?

답변:


25

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


echo $LD_LIBRARY_PATH내 컴퓨터에 비어 있습니다 :(
linuxer

보통입니다.
Ignacio Vazquez-Abrams

2
로더가 라이브러리를 찾을 추가 디렉토리를 지정합니다.
Ignacio Vazquez-Abrams 2018 년

1
* nix의 경로 :는 세미콜론이 아닌 콜론 ( )으로 구분됩니다.
Ignacio Vazquez-Abrams

3
LD_LIBRARY_PATH는 일반적으로 프로덕션에서 좋지 않은 선택입니다. 빠른 해킹에 유용하며, 단위 테스트를 실행할 때 제거 된 바이너리가 공유 라이브러리를 찾도록 돕는 것과 같은 것들이 있습니다 (./configure; make; check). 바이너리를 빌드 할 때 라이브러리를 표준 위치 (/etc/ld.so.conf에 나열 됨)에 놓거나 -R 플래그를 링커에 전달하여 바이너리가 어디에서 보일지 알 수 있습니다.
automatthias

57

동적 링커가 볼 위치를 알 수 있도록 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!

1
사용하지 않는 경우 make와 같은 수동으로 호출 할 때와 같이 g++, 시도 -Wl,-rpath='$ORIGIN'(작은 따옴표를 주) 방지하기 위해 $ORIGIN빈 문자열로 확장에서.
Morpork

14

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

$ LD_LIBRARY_PATH=. ./binary

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


4

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

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

나를 위해 일했다.


나를 위해 일했습니다.
Joel

3

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

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

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


0

동적 링커는 라이브러리를 찾을 위치를 결정합니다. 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

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.