실행 파일이 공유 라이브러리를 찾을 수 있도록 허용하는 방법을 찾고 있지만 동일한 공유 라이브러리의 다른 버전을 사용할 수 있는 패키지와의 충돌을 피하기 위해 이러한 라이브러리를 "개인 경로"(대신)에 유지하는 것을 선호합니다. /usr/lib).
가능한 방법은 다음과 같습니다.
- 실행 파일에 rpath 포함
- 실행 파일을 시작할 때 LD_LIBRARY_PATH를 설정하십시오.
- ld.so.conf.d 파일의 ldconfig 구성에 라이브러리 경로를 추가합니다.
rpath는 대상 구조를 빌드에 연결하고, ld.so.conf.d는 시스템 경로를 구성하며, LD_LIBRARY_PATH는 호출자 프로세스가 이를 알아야 합니다.
그렇다면 실행 파일에만 적용되는 ld.so.conf.d(또는 유사한 로더 구성)를 사용할 수 있는지 궁금합니다.
답변1
쉬운 일이 아닙니다. ld.so.conf
파일 형식은 매우 간단합니다. 단지 경로 목록일 뿐입니다.
다양한 방법을 사용하여 실행 파일을 빌드하면 몇 가지 작업을 수행할 수 있습니다.통역사; 일반 값은 /lib64/ld-linux-x86-64.so.2
1 과 같 으며 실제로 동적 연결을 수행합니다. 따라서 사용자 정의 동적 링커는 다르게 보이 ld.so.conf
거나 무엇이든 할 수 있습니다. 그러나 이것은 rpath보다 훨씬 더 나쁜 것 같습니다!
더 간단한 해결책은 래퍼입니다. 바이너리를 으로 설치 program.real
하거나, 다른 곳에 설치하는 것이 더 좋습니다 /usr/local/lib/
(예: 가 아닌 $PATH
). 그런 다음 간단한 쉘 스크립트를 입력하십시오 /usr/local/bin/program
.
#!/bin/sh
export LD_LIBRARY_PATH=/path/to/libs
exec /usr/local/lib/program/program.real
이제 라이브러리 위치는 빌드와 관련이 없지만 호출자는 이에 대해 알 필요가 없습니다.
1 : 시스템에서 일반적으로 발견되는 항목을 찾는 빠른 방법: readelf /bin/bash -p .interp
. 몇 가지 다른 실행 파일을 사용해 보면 최소한 32비트 및 64비트 프로그램이 서로 다른 프로그램을 사용한다는 것을 알 수 있습니다.
답변2
상대 rpath 를 사용할 수 있습니다 $ORIGIN
.
-Wl,-rpath,'$ORIGIN/../lib'
실행 파일이 설치를 찾을 수 있도록 하는 라이브러리 에 실행 파일을 연결합니다 .
- 실행 파일은 다음 위치에 있습니다.
<base>/bin/
- 공유도서관의 위치는 다음과 같습니다.
<base>/lib/
이렇게 진행하면 해당 실행 파일에 대해서만 이 링크를 구성할 수 있으며 디렉터리 <base>
는 어디에나 위치할 수 있습니다.
답변3
filename
인수는 dlopen
절대 경로( /
" "로 시작)일 수 있습니다.
따라서 "개인 경로"는 구성 파일에 저장되고 라이브러리의 전체 이름은 이 파일에서 빌드됩니다. 또는 개인 라이브러리가 실행 파일과 동일한 디렉터리에 있다는 것을 알고 있는 경우 실행 파일 경로에서 간단한 문자열 작업을 수행하여 찾습니다.
#include <dlfcn.h>
#include <unistd.h>
#include <string.h>
static int (*foo)();
/* ... */
char buf[BUFSIZ];
char *lastslash;
void *handle;
realpath(argv[0],buf);
lastslash = strrchr(buf,'/');
strcpy(lastslash,"foo." VERSION_BUILD ".so");
dlopen(buf,RTLD_LOCAL | RTLD_LAZY);
*(void **)(&foo) = dlsym(handle, "foo");
/* ... */
printf("%d\n",foo());