'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