'How to link a shared library with CMake with relative path
I want to link a third-party libLibrary.so and distribute it with my program. If user unzips my archive, he will get this folder structure:
game
libLibrary.so
game_executable
game_executable depends on ./libLibrary.so.
My project structure:
game
bin
libLibrary.so
lib
Library.h
src
game_executable.cpp
CMakeLists.txt
My CMakeLists.txt:
cmake_minimum_required(VERSION 3.7)
project(game)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_BINARY_DIR ${CMAKE_SOURCE_DIR}/bin)
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR})
set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR})
set(SOURCE_FILES src/game_executable.cpp)
include_directories(${CMAKE_SOURCE_DIR}/lib)
add_executable(game ${SOURCE_FILES})
target_link_libraries(${PROJECT_NAME} ${CMAKE_BINARY_DIR}/libLibrary.so)
However, what I get is my game_executable depends on the .../game/bin/libLibrary.so, not on the ./libLibrary.so that is in the folder with game_executable, making this totally unportable!
How can I make linking path relative instead of absolute?
Solution 1:[1]
Most of the time you want to set the RPATH to $ORIGIN instead of ., because it refers to the executable's path instead while . refers to the current directory at runtime (which can be anything else).
I find it simple to edit LINK_FLAGS instead of INSTALL_RPATH target property, because CMakes already has a variable named ORIGIN (see CMake's documentation).
So that boils down to the following:
# Find shared libraries next to the executable
set_target_properties(target_name PROPERTIES
BUILD_WITH_INSTALL_RPATH FALSE
LINK_FLAGS "-Wl,-rpath,$ORIGIN/")
Solution 2:[2]
If you use target_link_directories then cmake will add it to the linker command as a manual rpath
Solution 3:[3]
Talking about distribution the executable or shared library with dynamically linked libraries and CMake build system:
SET(CMAKE_BUILD_RPATH_USE_ORIGIN TRUE)
This var forces linking with relative path within the build tree, so in result the build directory can be movable.
If you use this command on linux machine
find <YOUR_TARGET_NAME> -type f -perm /a+x -exec ldd {} \; | grep so | sed -e '/^[^\t]/ d' | sed -e 's/\t//' | sed -e 's/.*=..//' | sed -e 's/ (0.*)//' | sort | uniq -c | sort -n
you will see the dot in the path, which indicates the relativity, example:
~/project/build/./lib/my_shared_lib.so
See more in CMake docs.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | G Huxley |
| Solution 3 | benson23 |
