【发布时间】:2026-01-12 05:30:01
【问题描述】:
我正在构建一个包含一些测试和示例程序的库。该项目能够尊重 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)
然后在每个测试/示例程序的 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 中是否有更好的方法将安装 rpath “向上”传递到静态编译我的库时生成的第一个 ELF 文件?
【问题讨论】:
-
语法
$LIBLOC不访问CMake中的环境变量。
标签: cmake