我自己构建了我的共享库(我使用lib计算斐波纳契数),并希望在CMake
构建的另一个c ++项目中使用它
我们说/path/to/my/lib
中的共享库和标题,共享库libfib.so
位于/path/to/my/lib/lib
,标题fib.h
位于{{1}我自己的项目位于/path/to/my/lib/include
这是我原来的/path/to/my/project
:
CMakeLists.txt
我使用这个脚本来构建和安装我的项目:
cmake_minimum_required(VERSION 3.2)
project(learn-lib)
set(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}")
set(FIB_INCLUDE "${FIB_PREFIX}/include")
set(FIB_LIB "${FIB_PREFIX}/lib")
set(EXE mybin)
include_directories(${FIB_INCLUDE})
link_directories(${FIB_LIB})
add_executable(${EXE} main.cpp)
target_link_libraries(${EXE} fib)
install(TARGETS ${EXE} RUNTIME DESTINATION bin)
现在,在运行安装脚本之后,我得到了两个可执行文件,一个在mkdir -p build_dir
cd build_dir
cmake -DFIB_PREFIX=/path/to/my/lib \
-DCMAKE_INSTALL_PREFIX=/path/to/my/project \
..
make
make install
cd ..
,一个在安装位置build_dir
,当在path/to/my/project/bin
中运行程序时,一切都很好,但是在运行已安装的程序时,我得到:
./ bin / mybin:加载共享库时出错:libfib.so:无法打开共享对象文件:没有这样的文件或目录
在google和stackoverflow上进行一些搜索之后,我知道build_dir
在构建时似乎删除了与可执行文件绑定的运行时搜索路径。我现在知道两种方法来解决它:
CMake
所在的库路径添加到环境变量libfib.so
LD_LIBRARY_PATH
添加到我的set_target_properties(${EXE} PROPERTIES INSTALL_RPATH_USE_LINK_PATH TRUE)
所以,我的问题是:
CMakeLists.txt
是这样设计的?安装时,为什么它会从可执行文件中删除运行时路径,而不是仅仅将构建的可执行文件复制到安装目标或保留已安装程序的链接路径?CMake
添加到set_target_properties(...)
?答案 0 :(得分:11)
您可能需要查看CMake's RPATH handling settings
这句话特别与你的困境有关:
默认情况下,如果不更改任何与RPATH相关的设置,CMake会将可执行文件和共享库与完整的RPATH链接到构建树中的所有已使用的库。安装时,它将清除这些目标的RPATH,以便安装空RPATH。
您可以使用CMAKE_INSTALL_RPATH
变量设置为已安装的二进制文件设置的RPATH,例如:
SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
并且您还可以在安装期间禁用RPATH剥离:
SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
答案 1 :(得分:3)
我只想回答问题1.为什么要这样做。 Alex已经发布了一个如何改变这种行为的解决方案。
原因是当你构建它时,你真的想要使用构建脚本在你的机器上看到的库。如果您为自己的应用程序构建了一整套librareis,那么您不会错误地认为它们不会被库选中。因此,使用库的完整rpath是有意义的。
但是在安装时,unix世界中的常见情况是使用共享的/ usr / lib和/ usr / local / lib文件。它们通常被拾取(除非使用LD_LIBRARY_PATH),这通常是你想要的。
正如您在我的措辞中所看到的,所有这些都是一团糟,因为它包含了如此多的隐式决策,如何组织构建和部署。这就是为什么“DLL地狱”这个术语曾经在Windows上流行的术语在被广泛使用时转移到Unix上的原因之一。没有技术解决方案,因为它不是技术问题(该部分已解决)。它是一个组织问题,CMake必须在默认情况下决定它在平台上支持的一种风格。恕我直言,他们明智地选择了。