CMake中的传递RPATH属性

cha*_*ert 5 cmake

我正在建立一个与一些测试和示例程序捆绑在一起的库。该项目能够兑现cmake属性BUILD_SHARED_LIBS.so如果打开,则构建一个,.a如果关闭,则构建一个文件。该库依赖于其他一些动态库,这些动态库应该使用环境变量来找到LIBLOC(它们的约定,不是我的)。

构建动态版本的库时,可以设置安装rpath以便正确找到库。例如:

add_library(lib ${SRC})
set_target_properties(lib INSTALL_RPATH $LIBLOC)
install(TARGETS lib LIBRARY DESTINATION lib)
Run Code Online (Sandbox Code Playgroud)

然后在每个测试/示例程序的CMakeLists.txt中:

add_executable(test ${SRC})
target_link_libraries(test lib)
set_target_properties(test INSTALL_RPATH $ORIGIN/../lib)
install(TARGETS test RUNTIME bin)
Run Code Online (Sandbox Code Playgroud)

BUILD_SHARED_LIBS是时,测试程序是幸福的:

$ lddtree bin/test
test => bin/test (interpreter => /lib64/ld-linux-x86-64.so.2)
    liblib.so => /path/to/install/liblib.so
        libdep.so => /path/to/dependency/libdep.so
Run Code Online (Sandbox Code Playgroud)

我们可以找到一切,因为在测试中rpath的是$ORIGIN/../lib,它的发现liblib.so,然后将rpath的liblib.so就是$LIBLOC,这是在我的环境设置/path/to/dependency

我本来希望在安装静态库时,cmake INSTALL_RPATH将从我的库中读取该属性并将其放入测试程序中,以便测试中的rpath为$ORIGIN/../lib;$LIBLOC。而是$LIBLOC不会以任何rpath结尾。

我目前的解决方案是不满意:我调节我INSTALL_RPATHBUILD_SHARED_LIBS每个示例或测试程序,如

if (BUILD_SHARED_LIBS)
  set_target_properties(test INSTALL_RPATH "$ORIGIN/../lib")
else ()
  set_target_properties(test INSTALL_RPATH "$LIBLOC")
endif ()
Run Code Online (Sandbox Code Playgroud)

现在,我有几个目标,所有这些目标都必须了解其依赖性的依赖性。再加上一堆臭的if语句。!

在cmake中,有一种更好的方法将安装rpath“向上”传递给静态编译我的库时生成的第一个ELF文件吗?

Ale*_*ing 1

该变量可以在外部CMAKE_INSTALL_RPATH设置,并将应用于所有明确定义的目标(即可执行文件和共享库)。RPATH

对于您编写或供应商的库,您应该将它们安装到一致的结构中,以便CMAKE_INSTALL_RPATH可以在所有目标上设置$LIBLOC$ORIGIN/../lib统一设置。对于真正的依赖项,期望用户在系统范围内安装它们、设置LD_LIBRARY_PATH或使用find_dependencyCMake 包配置中的宏来查找正确的库是合理的。

如果将以下代码片段放置在创建任何目标之前,可能会对您有所帮助:

if (NOT DEFINED CMAKE_INSTALL_RPATH)
  # or perhaps it's meant to be $env{LIBLOC}?
  set(CMAKE_INSTALL_RPATH "$<IF:$<BOOL:${BUILD_SHARED_LIBS}>,$ORIGIN/../lib,$LIBLOC>")
endif ()
Run Code Online (Sandbox Code Playgroud)