Last update:
RPATH
C/C++ 실행파일이 동적 라이브러리를 사용할 때, 링커는 아래 디렉터리를 차례대로 탐색한다.
•
RPATH - 대부분의 UNIX 시스템에서 지원되며, 실행 파일에 연결되는 디렉토리 목록. RUNPATH가 있을 경우 무시됨
→ RPATH는 실행파일에 포함되는 설정임
•
LD_LIBRARY_PATH - 디렉토리 목록을 포함하는 환경 변수
•
RUNPATH - RPATH와 동일하지만, LD_LIBRARY_PATH 이후에 검색됨. 현재 대부분의 Linux 시스템에서 지원됨
•
/etc/ld.so.conf - 추가 라이브러리 디렉토리를 나열하는 ld.so의 설정 파일
•
기본 내장 디렉토리 - 기본적으로 /lib와 /usr/lib
그런데 같은 동적 라이브러리라고 하더라도, A 실행파일과 B 실행파일이 사용하고자 하는 버전이 다를 수도 있다. 이럴 경우 각 실행파일이 사용하고자 하는 라이브러리를 독립적으로 설정해주는 방법이 RPATH(또는 RUNPATH)다.
CMake와 RPATH
CMake 프로젝트에서는 실행파일을 빌드 트리에서 실행할 것이냐, 설치 트리에서 실행할 것이냐에 따라 RPATH도 달라져야 한다.
•
실행파일이 빌드 트리에서 실행될 때, 사용하는 라이브러리 역시 같은 프로젝트 내에서 빌드된 경우, RPATH는 빌드트리를 가리켜야 한다.
•
실행파일이 install된 경우는 RPATH가 빌드트리를 가리키지 않아야 한다.
하지만 애석하게도 RPATH를 간단하게 변경할 수 있는 방법은 아직 존재하지 않는다. RPATH는 컴파일될 때 실행파일에 새겨지는 설정이기 때문이다.
CMake는 버전 2.6부터 실행파일을 빌드할 때, 설치 트리의 RPATH가 빌드 트리의 RPATH보다 긴 경우, 빌드 트리의 RPATH에 패딩을 붙여놓는다. 그리고 설치할 때 RPATH를 변경하는 식으로 작동한다. 2.6버전 이전에는 install 시 RPATH를 다시 설정하기 위해 링킹 과정을 다시 거쳐야 했다.
Default RPATH 설정
CMake는 기본적으로 실행파일에서 사용한 라이브러리들의 빌드 트리 경로를 RPATH로 설정한다. 그리고 install 시에 RPATH를 지워서 빈 상태로 만든다. 아래는 Default 설정 그대로이다.
# use, i.e. don't skip the full RPATH for the build tree
set(CMAKE_SKIP_BUILD_RPATH FALSE)
# when building, don't use the install RPATH already
# (but later on when installing)
set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
# the RPATH to be used when installing
set(CMAKE_INSTALL_RPATH "")
# don't add the automatically determined parts of the RPATH
# which point to directories outside the build tree to the install RPATH
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH FALSE)
Shell
복사
Default 설정을 그대로 두면 실행파일을 빌드 트리에서 직접 실행할 수 있는 반면, install된 실행파일은 직접 LD_LIBRARY_PATH같은 환경변수에 라이브러리 위치를 추가하거나, 라이브러리를 default 라이브러리 디렉터리에 넣어주는 방법 등을 통해 링킹을 해줘야 한다.
항상 Full RPATH를 설정하기 (실행파일이 동적 라이브러리(.so) 파일을 찾도록 설정하는 방법)
필요한 라이브러리가 LD_LIBRARY_PATH나 install 위치와 관계 없이 찾을 수 있도록 하고싶은 경우 아래처럼 하면 된다.
# use, i.e. don't skip the full RPATH for the build tree
set(CMAKE_SKIP_BUILD_RPATH FALSE)
# when building, don't use the install RPATH already
# (but later on when installing)
set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
# add the automatically determined parts of the RPATH
# which point to directories outside the build tree to the install RPATH
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
# the RPATH to be used when installing, but only if it's not a system directory
list(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_PREFIX}/lib" isSystemDir)
if("${isSystemDir}" STREQUAL "-1")
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
endif("${isSystemDir}" STREQUAL "-1")
Shell
복사
/usr/bin처럼 시스템이 기본적으로 라이브러리를 찾아보는 디렉터리를 시스템 기본 링크 디렉터리라고 하는데, CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES는 그 목록을 가지고 있다. install 경로(CMAKE_INSTALL_RPATH)가 해당 목록에 없을 경우 CMAKE_INSTALL_RPATH에 등록을 해주는 것이다.
$ORIGIN
Linux에서 링커(ld.so)는 rpath 내에 있는 $ORIGIN이라는 문자열(토큰)을 현재 실행파일의 경로로 치환한다. 따라서 공유 라이브러리를 찾을 때 실행 파일의 위치를 기준으로 상대 경로를 지정할 수 있게 해주고, 어디에 복붙해 놓아도 잘 작동하는 패키지를 만들 수 있다.
set_target_properties(<target> PROPERTIES INSTALL_RPATH "$ORIGIN")
Shell
복사
RPATH 확인하기 (Ubuntu)
readelf -d main_app
Shell
복사
기타
LD_LIBRARY_PATH를 설정하는 방법도 있다(비권장)
export LD_LIBRARY_PATH=/usr/local/lib
Plain Text
복사