如何使用相对路径将共享库与CMake链接

The*_*Cat 4 c++ cmake

我想链接第三方libLibrary.so并将其与我的程序一起分发。如果用户解压缩我的存档,他将获得以下文件夹结构:

game
  libLibrary.so
  game_executable
Run Code Online (Sandbox Code Playgroud)

game_executable取决于./libLibrary.so

我的项目结构:

game
  bin
    libLibrary.so
  lib
    Library.h
  src
    game_executable.cpp
  CMakeLists.txt
Run Code Online (Sandbox Code Playgroud)

我的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)
Run Code Online (Sandbox Code Playgroud)

但是,我得到的是我的game_executable依赖于.../game/bin/libLibrary.so,而不是依赖于./libLibrary.so文件夹中的game_executable,这使得它完全不可移植!

如何使链接路径相对而不是绝对?

Cha*_*esB 10

大多数时候,您希望将 设为而不是RPATH,因为它指的是可执行文件的路径,而指的是运行时的当前目录(可以是其他目录)。$ORIGIN..

我发现编辑目标属性很简单LINK_FLAGSINSTALL_RPATH因为 CMake 已经有一个名为的变量ORIGIN(请参阅CMake 的文档)。

所以这可以归结为以下几点:

# Find shared libraries next to the executable
set_target_properties(target_name PROPERTIES
        BUILD_WITH_INSTALL_RPATH FALSE
        LINK_FLAGS "-Wl,-rpath,$ORIGIN/")
Run Code Online (Sandbox Code Playgroud)


Ste*_*mer 6

文档中

默认情况下,如果您不更改任何与RPATH相关的设置,则CMake会将具有完整RPATH的可执行文件和共享库链接到构建树中所有使用的库。

这是您看到的行为。

但是,有多种方法可以更改此设置以匹配所需的行为。

以上链接文档中的一些示例:

# 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)
Run Code Online (Sandbox Code Playgroud)

使用上述方法,您可能需要设置CMAKE_INSTALL_RPATH然后分发已安装的二进制文件。

如果要从构建树中的二进制文件分发,则还可以绕过CMake的rpath处理并使用链接器标志直接修改rpath:

set_target_properties(game PROPERTIES LINK_FLAGS "-Wl,-rpath,./")
Run Code Online (Sandbox Code Playgroud)

  • 要仅修改单个目标的运行路径,您还可以使用相同的变量名称,但在“set_target_properties”中不使用前缀“CMAKE_”。例如:`set_target_properties(game PROPERTIES BUILD_WITH_INSTALL_RPATH TRUE)`和`set_target_properties(game PROPERTIES INSTALL_RPATH "./")`。这与您的上一个示例的作用相同。 (3认同)

小智 5

谈论使用动态链接库和 CMake 构建系统分发可执行文件或共享库:

SET(CMAKE_BUILD_RPATH_USE_ORIGIN TRUE)
Run Code Online (Sandbox Code Playgroud)

此 var 强制链接到构建树中的相对路径,因此构建目录可以移动。

如果你在linux机器上使用这个命令

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
Run Code Online (Sandbox Code Playgroud)

您将在路径中看到点,它表示相对性,例如: ~/project/build/./lib/my_shared_lib.so

请参阅CMake 文档了解更多信息。