我正在构建一个库,我将其与一些测试和示例程序捆绑在一起。该项目能够尊重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文件?
答案 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 ()