CMake

时间:2017-06-30 14:34:33

标签: cmake

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

当我构建库的动态版本时,我能够设置安装rpath,以便正确找到库。 E.g:

add_library(lib ${SRC})
set_target_properties(lib INSTALL_RPATH $LIBLOC)
install(TARGETS lib LIBRARY DESTINATION lib)

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

add_executable(test ${SRC})
target_link_libraries(test lib)
set_target_properties(test INSTALL_RPATH $ORIGIN/../lib)
install(TARGETS test RUNTIME bin)

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

我们可以找到所有内容,因为测试中的rpath为$ORIGIN/../lib,找到liblib.so,然后liblib.so中的rpath为$LIBLOC,这在我的环境中设置为/path/to/dependency

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

我目前的解决方案是不满意:我在每个示例或测试程序中调整INSTALL_RPATH BUILD_SHARED_LIBS,例如

if (BUILD_SHARED_LIBS)
  set_target_properties(test INSTALL_RPATH "$ORIGIN/../lib")
else ()
  set_target_properties(test INSTALL_RPATH "$LIBLOC")
endif ()

现在我有几个目标,所有目标都要注意它们的依赖关系。依赖。加上一堆臭臭的if语句。呸!

cmake中是否有更好的方式来传递安装路径" up"我的库是静态编译时产生的第一个ELF文件?

1 个答案:

答案 0 :(得分:0)

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

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

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

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 ()