답변:
로더는 명시 적으로 via로 지시되지 않는 한 현재 디렉토리에서 공유 객체를 검사하지 않습니다 $LD_LIBRARY_PATH
. 자세한 내용은 ld.so(8)
매뉴얼 페이지를 참조하십시오.
:
는 세미콜론이 아닌 콜론 ( )으로 구분됩니다.
동적 링커가 볼 위치를 알 수 있도록 LD_LIBRARY_PATH를 설정할 수 있지만 더 나은 옵션이 있습니다. 공유 라이브러리를 표준 위치 중 하나에 배치 할 수 있습니다 (이 장소 목록은 ( /etc/ld.so.conf
Linux) 및 /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!
make
와 같은 수동으로 호출 할 때와 같이 g++
, 시도 -Wl,-rpath='$ORIGIN'
(작은 따옴표를 주) 방지하기 위해 $ORIGIN
빈 문자열로 확장에서.
빌드에 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 라이브러리의 동적 링커는 다음 위치에서 공유 라이브러리를 검색합니다.
DT_RPATH
바이너리 의 동적 섹션 속성에 존재하고DT_RUNPATH
속성이없는 경우 (콜론으로 구분 된) 경로입니다 .LD_LIBRARY_PATH
실행 파일이setuid
/setgid
바이너리 가 아닌 경우 환경 변수에서 (콜론으로 구분 된) 경로 는 무시됩니다.LD_LIBRARY_PATH
--library-path 옵션 (예 : /lib/ld-linux.so.2 --library-path $ HOME / mylibs myprogram)을 사용하여 동적 링커를 호출하여 재정의 할 수 있습니다.DT_RUNPATH
바이너리 의 동적 섹션 속성에있는 (콜론으로 구분 된) 경로 .- 기능 보강 라이브러리 경로에서 이전에 찾은 후보 라이브러리의 컴파일 된 목록을 포함하는 ldconfig 캐시 파일 (종종)에 기반한 검색
/etc/ld.so.cache
(에서 설정/etc/ld.so.conf
). 그러나 바이너리가-z nodefaultlib
링커 옵션 과 링크 된 경우 기본 라이브러리 경로의 라이브러리는 건너 뜁니다.- 신뢰할 수있는 기본 경로에서
/lib
다음/usr/lib
. 바이너리가 -z nodefaultlib 링커 옵션으로 링크 된 경우이 단계를 건너 뜁니다.
echo $LD_LIBRARY_PATH
내 컴퓨터에 비어 있습니다 :(